16 #include <deal.II/base/tensor_product_polynomials.h> 17 #include <deal.II/base/polynomials_piecewise.h> 18 #include <deal.II/base/exceptions.h> 19 #include <deal.II/base/table.h> 21 #include <boost/container/small_vector.hpp> 24 DEAL_II_NAMESPACE_OPEN
37 void compute_tensor_index(
const unsigned int,
40 unsigned int ( &)[dim])
46 void compute_tensor_index(
const unsigned int n,
49 unsigned int (&indices)[1])
55 void compute_tensor_index(
const unsigned int n,
56 const unsigned int n_pols_0,
58 unsigned int (&indices)[2])
60 indices[0] = n % n_pols_0;
61 indices[1] = n / n_pols_0;
65 void compute_tensor_index(
const unsigned int n,
66 const unsigned int n_pols_0,
67 const unsigned int n_pols_1,
68 unsigned int (&indices)[3])
70 indices[0] = n % n_pols_0;
71 indices[1] = (n/n_pols_0) % n_pols_1;
72 indices[2] = n / (n_pols_0*n_pols_1);
79 template <
int dim,
typename PolynomialType>
84 unsigned int (&indices)[(dim > 0 ? dim : 1)])
const 87 internal::compute_tensor_index(index_map[i], polynomials.size(),
88 polynomials.size(), indices);
93 template <
int dim,
typename PolynomialType>
98 for (
unsigned int i=0; i<n_tensor_pols; ++i)
102 for (
unsigned int d=0; d<dim; ++d)
110 template <
int dim,
typename PolynomialType>
113 (
const std::vector<unsigned int> &renumber)
115 Assert(renumber.size()==index_map.size(),
119 for (
unsigned int i=0; i<index_map.size(); ++i)
120 index_map_inverse[index_map[i]]=i;
128 ::compute_value(
const unsigned int,
137 template <
int dim,
typename PolynomialType>
140 (
const unsigned int i,
145 unsigned int indices[dim];
146 compute_index (i, indices);
149 for (
unsigned int d=0; d<dim; ++d)
150 value *= polynomials[indices[d]].value(p(d));
157 template <
int dim,
typename PolynomialType>
162 unsigned int indices[dim];
163 compute_index (i, indices);
171 std::vector<double> tmp (2);
172 for (
unsigned int d=0; d<dim; ++d)
174 polynomials[indices[d]].value (p(d), tmp);
181 for (
unsigned int d=0; d<dim; ++d)
184 for (
unsigned int x=0; x<dim; ++x)
185 grad[d] *= v[x][d==x];
193 template <
int dim,
typename PolynomialType>
196 (
const unsigned int i,
199 unsigned int indices[dim];
200 compute_index (i, indices);
204 std::vector<double> tmp (3);
205 for (
unsigned int d=0; d<dim; ++d)
207 polynomials[indices[d]].value (p(d), tmp);
215 for (
unsigned int d1=0; d1<dim; ++d1)
216 for (
unsigned int d2=0; d2<dim; ++d2)
218 grad_grad[d1][d2] = 1.;
219 for (
unsigned int x=0; x<dim; ++x)
221 unsigned int derivative=0;
229 grad_grad[d1][d2] *= v[x][derivative];
239 template <
int dim,
typename PolynomialType>
243 std::vector<double> &values,
250 Assert (values.size()==n_tensor_pols || values.size()==0,
252 Assert (grads.size()==n_tensor_pols || grads.size()==0,
254 Assert (grad_grads.size()==n_tensor_pols|| grad_grads.size()==0,
256 Assert (third_derivatives.size()==n_tensor_pols|| third_derivatives.size()==0,
258 Assert (fourth_derivatives.size()==n_tensor_pols|| fourth_derivatives.size()==0,
262 update_grads = (grads.size()==n_tensor_pols),
263 update_grad_grads = (grad_grads.size()==n_tensor_pols),
265 update_4th_derivatives = (fourth_derivatives.size()==n_tensor_pols);
268 unsigned int n_values_and_derivatives = 0;
270 n_values_and_derivatives = 1;
272 n_values_and_derivatives = 2;
273 if (update_grad_grads)
274 n_values_and_derivatives = 3;
276 n_values_and_derivatives = 4;
277 if (update_4th_derivatives)
278 n_values_and_derivatives = 5;
285 const unsigned int n_polynomials = polynomials.size();
286 boost::container::small_vector<std::array<std::array<double,5>,dim>, 20> values_1d(n_polynomials);
287 if (n_values_and_derivatives == 1)
288 for (
unsigned int i=0; i<n_polynomials; ++i)
289 for (
unsigned int d=0; d<dim; ++d)
290 values_1d[i][d][0] = polynomials[i].value(p(d));
292 for (
unsigned int i=0; i<n_polynomials; ++i)
293 for (
unsigned d=0; d<dim; ++d)
294 polynomials[i].value(p(d), n_values_and_derivatives, &values_1d[i][d][0]);
296 unsigned int indices[3];
298 for (indices[2]=0; indices[2]<(dim>2?n_polynomials:1); ++indices[2])
299 for (indices[1]=0; indices[1]<(dim>1?n_polynomials:1); ++indices[1])
300 if (n_values_and_derivatives == 1)
301 for (indices[0]=0; indices[0]<n_polynomials; ++indices[0], ++ind)
303 double value = values_1d[indices[0]][0][0];
304 for (
unsigned int d=1; d<dim; ++d)
305 value *= values_1d[indices[d]][d][0];
306 values[index_map_inverse[ind]] = value;
309 for (indices[0]=0; indices[0]<n_polynomials; ++indices[0], ++ind)
311 unsigned int i = index_map_inverse[ind];
315 double value = values_1d[indices[0]][0][0];
316 for (
unsigned int x=1; x<dim; ++x)
317 value *= values_1d[indices[x]][x][0];
322 for (
unsigned int d=0; d<dim; ++d)
325 for (
unsigned int x=0; x<dim; ++x)
326 grad *= values_1d[indices[x]][x][(d==x)?1:0];
330 if (update_grad_grads)
331 for (
unsigned int d1=0; d1<dim; ++d1)
332 for (
unsigned int d2=0; d2<dim; ++d2)
335 for (
unsigned int x=0; x<dim; ++x)
337 unsigned int derivative=0;
338 if (d1==x) ++derivative;
339 if (d2==x) ++derivative;
341 der2 *= values_1d[indices[x]][x][derivative];
343 grad_grads[i][d1][d2] = der2;
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)
352 for (
unsigned int x=0; x<dim; ++x)
354 unsigned int derivative=0;
355 if (d1==x) ++derivative;
356 if (d2==x) ++derivative;
357 if (d3==x) ++derivative;
359 der3 *= values_1d[indices[x]][x][derivative];
361 third_derivatives[i][d1][d2][d3] = der3;
364 if (update_4th_derivatives)
365 for (
unsigned int d1=0; d1<dim; ++d1)
366 for (
unsigned int d2=0; d2<dim; ++d2)
367 for (
unsigned int d3=0; d3<dim; ++d3)
368 for (
unsigned int d4=0; d4<dim; ++d4)
371 for (
unsigned int x=0; x<dim; ++x)
373 unsigned int derivative=0;
374 if (d1==x) ++derivative;
375 if (d2==x) ++derivative;
376 if (d3==x) ++derivative;
377 if (d4==x) ++derivative;
379 der4 *= values_1d[indices[x]][x][derivative];
381 fourth_derivatives[i][d1][d2][d3][d4] = der4;
397 n_tensor_pols(get_n_tensor_pols(pols))
400 for (
unsigned int d=0; d<dim; ++d)
401 Assert (pols[d].size() > 0,
402 ExcMessage (
"The number of polynomials must be larger than zero " 403 "for all coordinate directions."));
413 unsigned int (&indices)[dim])
const 416 unsigned int n_poly = 1;
417 for (
unsigned int d=0; d<dim; ++d)
418 n_poly *= polynomials[d].size();
423 internal::compute_tensor_index(i, polynomials[0].size(),
426 internal::compute_tensor_index(i, polynomials[0].size(),
427 polynomials[1].size(), indices);
437 unsigned int indices[dim];
438 compute_index (i, indices);
441 for (
unsigned int d=0; d<dim; ++d)
442 value *= polynomials[d][indices[d]].value(p(d));
453 unsigned int indices[dim];
454 compute_index (i, indices);
460 std::vector<std::vector<double> > v(dim, std::vector<double> (2));
461 for (
unsigned int d=0; d<dim; ++d)
462 polynomials[d][indices[d]].value(p(d), v[d]);
465 for (
unsigned int d=0; d<dim; ++d)
468 for (
unsigned int x=0; x<dim; ++x)
469 grad[d] *= v[x][d==x];
481 unsigned int indices[dim];
482 compute_index (i, indices);
484 std::vector<std::vector<double> > v(dim, std::vector<double> (3));
485 for (
unsigned int d=0; d<dim; ++d)
486 polynomials[d][indices[d]].value(p(d), v[d]);
489 for (
unsigned int d1=0; d1<dim; ++d1)
490 for (
unsigned int d2=0; d2<dim; ++d2)
492 grad_grad[d1][d2] = 1.;
493 for (
unsigned int x=0; x<dim; ++x)
495 unsigned int derivative=0;
503 grad_grad[d1][d2] *= v[x][derivative];
517 std::vector<double> &values,
523 Assert (values.size()==n_tensor_pols || values.size()==0,
525 Assert (grads.size()==n_tensor_pols|| grads.size()==0,
527 Assert (grad_grads.size()==n_tensor_pols|| grad_grads.size()==0,
529 Assert (third_derivatives.size()==n_tensor_pols|| third_derivatives.size()==0,
531 Assert (fourth_derivatives.size()==n_tensor_pols|| fourth_derivatives.size()==0,
535 update_grads = (grads.size()==n_tensor_pols),
536 update_grad_grads = (grad_grads.size()==n_tensor_pols),
538 update_4th_derivatives = (fourth_derivatives.size()==n_tensor_pols);
543 unsigned int n_values_and_derivatives = 0;
545 n_values_and_derivatives = 1;
547 n_values_and_derivatives = 2;
548 if (update_grad_grads)
549 n_values_and_derivatives = 3;
551 n_values_and_derivatives = 4;
552 if (update_4th_derivatives)
553 n_values_and_derivatives = 5;
559 std::vector<std::vector<std::vector<double> > > v(dim);
560 for (
unsigned int d=0; d<dim; ++d)
562 v[d].resize (polynomials[d].size());
563 for (
unsigned int i=0; i<polynomials[d].size(); ++i)
565 v[d][i].resize (n_values_and_derivatives, 0.);
566 polynomials[d][i].value(p(d), v[d][i]);
570 for (
unsigned int i=0; i<n_tensor_pols; ++i)
576 unsigned int indices[dim];
577 compute_index (i, indices);
582 for (
unsigned int x=0; x<dim; ++x)
583 values[i] *= v[x][indices[x]][0];
587 for (
unsigned int d=0; d<dim; ++d)
590 for (
unsigned int x=0; x<dim; ++x)
591 grads[i][d] *= v[x][indices[x]][d==x ? 1 : 0];
594 if (update_grad_grads)
595 for (
unsigned int d1=0; d1<dim; ++d1)
596 for (
unsigned int d2=0; d2<dim; ++d2)
598 grad_grads[i][d1][d2] = 1.;
599 for (
unsigned int x=0; x<dim; ++x)
601 unsigned int derivative=0;
602 if (d1==x) ++derivative;
603 if (d2==x) ++derivative;
605 grad_grads[i][d1][d2]
606 *= v[x][indices[x]][derivative];
611 for (
unsigned int d1=0; d1<dim; ++d1)
612 for (
unsigned int d2=0; d2<dim; ++d2)
613 for (
unsigned int d3=0; d3<dim; ++d3)
615 third_derivatives[i][d1][d2][d3] = 1.;
616 for (
unsigned int x=0; x<dim; ++x)
618 unsigned int derivative=0;
619 if (d1==x) ++derivative;
620 if (d2==x) ++derivative;
621 if (d3==x) ++derivative;
623 third_derivatives[i][d1][d2][d3]
624 *= v[x][indices[x]][derivative];
628 if (update_4th_derivatives)
629 for (
unsigned int d1=0; d1<dim; ++d1)
630 for (
unsigned int d2=0; d2<dim; ++d2)
631 for (
unsigned int d3=0; d3<dim; ++d3)
632 for (
unsigned int d4=0; d4<dim; ++d4)
634 fourth_derivatives[i][d1][d2][d3][d4] = 1.;
635 for (
unsigned int x=0; x<dim; ++x)
637 unsigned int derivative=0;
638 if (d1==x) ++derivative;
639 if (d2==x) ++derivative;
640 if (d3==x) ++derivative;
641 if (d4==x) ++derivative;
643 fourth_derivatives[i][d1][d2][d3][d4]
644 *= v[x][indices[x]][derivative];
656 return n_tensor_pols;
666 for (
unsigned int d=0; d<dim; ++d)
686 DEAL_II_NAMESPACE_CLOSE
Tensor< 1, dim > compute_grad(const unsigned int i, const Point< dim > &p) const
Tensor< 1, dim > compute_grad(const unsigned int i, const Point< dim > &p) const
void compute_index(const unsigned int i, unsigned int(&indices)[(dim >0?dim:1)]) const
static ::ExceptionBase & ExcDimensionMismatch2(int arg1, int arg2, int arg3)
void output_indices(std::ostream &out) const
void set_numbering(const std::vector< unsigned int > &renumber)
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
void compute_index(const unsigned int i, unsigned int(&indices)[dim]) const
static unsigned int get_n_tensor_pols(const std::vector< std::vector< Polynomials::Polynomial< double > > > &pols)
static ::ExceptionBase & ExcMessage(std::string arg1)
Third derivatives of shape functions.
#define Assert(cond, exc)
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
AnisotropicPolynomials(const std::vector< std::vector< Polynomials::Polynomial< double > > > &base_polynomials)
double compute_value(const unsigned int i, const Point< dim > &p) const
static ::ExceptionBase & ExcNotImplemented()
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
Tensor< 2, dim > compute_grad_grad(const unsigned int i, const Point< dim > &p) const
static ::ExceptionBase & ExcInternalError()