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> 20 #include <deal.II/base/std_cxx11/array.h> 22 DEAL_II_NAMESPACE_OPEN
35 void compute_tensor_index(
const unsigned int,
38 unsigned int ( &)[dim])
44 void compute_tensor_index(
const unsigned int n,
47 unsigned int (&indices)[1])
53 void compute_tensor_index(
const unsigned int n,
54 const unsigned int n_pols_0,
56 unsigned int (&indices)[2])
58 indices[0] = n % n_pols_0;
59 indices[1] = n / n_pols_0;
63 void compute_tensor_index(
const unsigned int n,
64 const unsigned int n_pols_0,
65 const unsigned int n_pols_1,
66 unsigned int (&indices)[3])
68 indices[0] = n % n_pols_0;
69 indices[1] = (n/n_pols_0) % n_pols_1;
70 indices[2] = n / (n_pols_0*n_pols_1);
77 template <
int dim,
typename PolynomialType>
82 unsigned int (&indices)[(dim > 0 ? dim : 1)])
const 85 internal::compute_tensor_index(index_map[i], polynomials.size(),
86 polynomials.size(), indices);
91 template <
int dim,
typename PolynomialType>
96 for (
unsigned int i=0; i<n_tensor_pols; ++i)
100 for (
unsigned int d=0; d<dim; ++d)
108 template <
int dim,
typename PolynomialType>
111 (
const std::vector<unsigned int> &renumber)
113 Assert(renumber.size()==index_map.size(),
117 for (
unsigned int i=0; i<index_map.size(); ++i)
118 index_map_inverse[index_map[i]]=i;
126 ::compute_value(
const unsigned int,
135 template <
int dim,
typename PolynomialType>
138 (
const unsigned int i,
143 unsigned int indices[dim];
144 compute_index (i, indices);
147 for (
unsigned int d=0; d<dim; ++d)
148 value *= polynomials[indices[d]].value(p(d));
155 template <
int dim,
typename PolynomialType>
160 unsigned int indices[dim];
161 compute_index (i, indices);
169 std::vector<double> tmp (2);
170 for (
unsigned int d=0; d<dim; ++d)
172 polynomials[indices[d]].value (p(d), tmp);
179 for (
unsigned int d=0; d<dim; ++d)
182 for (
unsigned int x=0; x<dim; ++x)
183 grad[d] *= v[x][d==x];
191 template <
int dim,
typename PolynomialType>
194 (
const unsigned int i,
197 unsigned int indices[dim];
198 compute_index (i, indices);
202 std::vector<double> tmp (3);
203 for (
unsigned int d=0; d<dim; ++d)
205 polynomials[indices[d]].value (p(d), tmp);
213 for (
unsigned int d1=0; d1<dim; ++d1)
214 for (
unsigned int d2=0; d2<dim; ++d2)
216 grad_grad[d1][d2] = 1.;
217 for (
unsigned int x=0; x<dim; ++x)
219 unsigned int derivative=0;
227 grad_grad[d1][d2] *= v[x][derivative];
237 template <
int dim,
typename PolynomialType>
241 std::vector<double> &values,
247 Assert (values.size()==n_tensor_pols || values.size()==0,
249 Assert (grads.size()==n_tensor_pols || grads.size()==0,
251 Assert (grad_grads.size()==n_tensor_pols|| grad_grads.size()==0,
253 Assert (third_derivatives.size()==n_tensor_pols|| third_derivatives.size()==0,
255 Assert (fourth_derivatives.size()==n_tensor_pols|| fourth_derivatives.size()==0,
259 update_grads = (grads.size()==n_tensor_pols),
260 update_grad_grads = (grad_grads.size()==n_tensor_pols),
262 update_4th_derivatives = (fourth_derivatives.size()==n_tensor_pols);
267 unsigned int n_values_and_derivatives = 0;
269 n_values_and_derivatives = 1;
271 n_values_and_derivatives = 2;
272 if (update_grad_grads)
273 n_values_and_derivatives = 3;
275 n_values_and_derivatives = 4;
276 if (update_4th_derivatives)
277 n_values_and_derivatives = 5;
288 if (n_values_and_derivatives == 1)
290 const unsigned int n_polynomials = polynomials.size();
291 const unsigned int factor = n_tensor_pols/n_polynomials;
293 std::fill(values.begin(),values.end(),1.0);
295 for (
unsigned int polynomial=0; polynomial<n_polynomials; ++polynomial)
297 for (
unsigned int d=0; d<dim; ++d)
299 const double value = polynomials[polynomial].value(p(d));
301 for (
unsigned int f=0; f<factor; ++f)
303 unsigned int index = 0;
307 index = polynomial+f*n_polynomials;
310 index = polynomial*n_polynomials + (f/n_polynomials)*n_polynomials*n_polynomials + f%n_polynomials;
313 index = polynomial*factor + f;
319 const unsigned int i = index_map_inverse[index];
337 std_cxx11::array<std_cxx11::array<double,5>, dim> *v;
338 std_cxx11::array<std_cxx11::array<std_cxx11::array<double,5>, dim>, 20> small_array;
339 std::vector<std_cxx11::array<std_cxx11::array<double,5>, dim> > large_array;
341 const unsigned int n_polynomials = polynomials.size();
342 if (n_polynomials > 20)
344 large_array.resize(n_polynomials);
350 for (
unsigned int i=0; i<n_polynomials; ++i)
351 for (
unsigned int d=0; d<dim; ++d)
352 polynomials[i].value(p(d), n_values_and_derivatives, &v[i][d][0]);
354 for (
unsigned int i=0; i<n_tensor_pols; ++i)
360 unsigned int indices[dim];
361 compute_index (i, indices);
366 for (
unsigned int x=0; x<dim; ++x)
367 values[i] *= v[indices[x]][x][0];
371 for (
unsigned int d=0; d<dim; ++d)
374 for (
unsigned int x=0; x<dim; ++x)
375 grads[i][d] *= v[indices[x]][x][d==x];
378 if (update_grad_grads)
379 for (
unsigned int d1=0; d1<dim; ++d1)
380 for (
unsigned int d2=0; d2<dim; ++d2)
382 grad_grads[i][d1][d2] = 1.;
383 for (
unsigned int x=0; x<dim; ++x)
385 unsigned int derivative=0;
386 if (d1==x) ++derivative;
387 if (d2==x) ++derivative;
389 grad_grads[i][d1][d2]
390 *= v[indices[x]][x][derivative];
395 for (
unsigned int d1=0; d1<dim; ++d1)
396 for (
unsigned int d2=0; d2<dim; ++d2)
397 for (
unsigned int d3=0; d3<dim; ++d3)
399 third_derivatives[i][d1][d2][d3] = 1.;
400 for (
unsigned int x=0; x<dim; ++x)
402 unsigned int derivative=0;
403 if (d1==x) ++derivative;
404 if (d2==x) ++derivative;
405 if (d3==x) ++derivative;
407 third_derivatives[i][d1][d2][d3]
408 *= v[indices[x]][x][derivative];
412 if (update_4th_derivatives)
413 for (
unsigned int d1=0; d1<dim; ++d1)
414 for (
unsigned int d2=0; d2<dim; ++d2)
415 for (
unsigned int d3=0; d3<dim; ++d3)
416 for (
unsigned int d4=0; d4<dim; ++d4)
418 fourth_derivatives[i][d1][d2][d3][d4] = 1.;
419 for (
unsigned int x=0; x<dim; ++x)
421 unsigned int derivative=0;
422 if (d1==x) ++derivative;
423 if (d2==x) ++derivative;
424 if (d3==x) ++derivative;
425 if (d4==x) ++derivative;
427 fourth_derivatives[i][d1][d2][d3][d4]
428 *= v[indices[x]][x][derivative];
445 n_tensor_pols(get_n_tensor_pols(pols))
448 for (
unsigned int d=0; d<dim; ++d)
449 Assert (pols[d].size() > 0,
450 ExcMessage (
"The number of polynomials must be larger than zero " 451 "for all coordinate directions."));
461 unsigned int (&indices)[dim])
const 464 unsigned int n_poly = 1;
465 for (
unsigned int d=0; d<dim; ++d)
466 n_poly *= polynomials[d].size();
471 internal::compute_tensor_index(i, polynomials[0].size(),
474 internal::compute_tensor_index(i, polynomials[0].size(),
475 polynomials[1].size(), indices);
485 unsigned int indices[dim];
486 compute_index (i, indices);
489 for (
unsigned int d=0; d<dim; ++d)
490 value *= polynomials[d][indices[d]].value(p(d));
501 unsigned int indices[dim];
502 compute_index (i, indices);
508 std::vector<std::vector<double> > v(dim, std::vector<double> (2));
509 for (
unsigned int d=0; d<dim; ++d)
510 polynomials[d][indices[d]].value(p(d), v[d]);
513 for (
unsigned int d=0; d<dim; ++d)
516 for (
unsigned int x=0; x<dim; ++x)
517 grad[d] *= v[x][d==x];
529 unsigned int indices[dim];
530 compute_index (i, indices);
532 std::vector<std::vector<double> > v(dim, std::vector<double> (3));
533 for (
unsigned int d=0; d<dim; ++d)
534 polynomials[d][indices[d]].value(p(d), v[d]);
537 for (
unsigned int d1=0; d1<dim; ++d1)
538 for (
unsigned int d2=0; d2<dim; ++d2)
540 grad_grad[d1][d2] = 1.;
541 for (
unsigned int x=0; x<dim; ++x)
543 unsigned int derivative=0;
551 grad_grad[d1][d2] *= v[x][derivative];
565 std::vector<double> &values,
571 Assert (values.size()==n_tensor_pols || values.size()==0,
573 Assert (grads.size()==n_tensor_pols|| grads.size()==0,
575 Assert (grad_grads.size()==n_tensor_pols|| grad_grads.size()==0,
577 Assert (third_derivatives.size()==n_tensor_pols|| third_derivatives.size()==0,
579 Assert (fourth_derivatives.size()==n_tensor_pols|| fourth_derivatives.size()==0,
583 update_grads = (grads.size()==n_tensor_pols),
584 update_grad_grads = (grad_grads.size()==n_tensor_pols),
586 update_4th_derivatives = (fourth_derivatives.size()==n_tensor_pols);
591 unsigned int n_values_and_derivatives = 0;
593 n_values_and_derivatives = 1;
595 n_values_and_derivatives = 2;
596 if (update_grad_grads)
597 n_values_and_derivatives = 3;
599 n_values_and_derivatives = 4;
600 if (update_4th_derivatives)
601 n_values_and_derivatives = 5;
607 std::vector<std::vector<std::vector<double> > > v(dim);
608 for (
unsigned int d=0; d<dim; ++d)
610 v[d].resize (polynomials[d].size());
611 for (
unsigned int i=0; i<polynomials[d].size(); ++i)
613 v[d][i].resize (n_values_and_derivatives, 0.);
614 polynomials[d][i].value(p(d), v[d][i]);
618 for (
unsigned int i=0; i<n_tensor_pols; ++i)
624 unsigned int indices[dim];
625 compute_index (i, indices);
630 for (
unsigned int x=0; x<dim; ++x)
631 values[i] *= v[x][indices[x]][0];
635 for (
unsigned int d=0; d<dim; ++d)
638 for (
unsigned int x=0; x<dim; ++x)
639 grads[i][d] *= v[x][indices[x]][d==x ? 1 : 0];
642 if (update_grad_grads)
643 for (
unsigned int d1=0; d1<dim; ++d1)
644 for (
unsigned int d2=0; d2<dim; ++d2)
646 grad_grads[i][d1][d2] = 1.;
647 for (
unsigned int x=0; x<dim; ++x)
649 unsigned int derivative=0;
650 if (d1==x) ++derivative;
651 if (d2==x) ++derivative;
653 grad_grads[i][d1][d2]
654 *= v[x][indices[x]][derivative];
659 for (
unsigned int d1=0; d1<dim; ++d1)
660 for (
unsigned int d2=0; d2<dim; ++d2)
661 for (
unsigned int d3=0; d3<dim; ++d3)
663 third_derivatives[i][d1][d2][d3] = 1.;
664 for (
unsigned int x=0; x<dim; ++x)
666 unsigned int derivative=0;
667 if (d1==x) ++derivative;
668 if (d2==x) ++derivative;
669 if (d3==x) ++derivative;
671 third_derivatives[i][d1][d2][d3]
672 *= v[x][indices[x]][derivative];
676 if (update_4th_derivatives)
677 for (
unsigned int d1=0; d1<dim; ++d1)
678 for (
unsigned int d2=0; d2<dim; ++d2)
679 for (
unsigned int d3=0; d3<dim; ++d3)
680 for (
unsigned int d4=0; d4<dim; ++d4)
682 fourth_derivatives[i][d1][d2][d3][d4] = 1.;
683 for (
unsigned int x=0; x<dim; ++x)
685 unsigned int derivative=0;
686 if (d1==x) ++derivative;
687 if (d2==x) ++derivative;
688 if (d3==x) ++derivative;
689 if (d4==x) ++derivative;
691 fourth_derivatives[i][d1][d2][d3][d4]
692 *= v[x][indices[x]][derivative];
704 return n_tensor_pols;
714 for (
unsigned int d=0; d<dim; ++d)
734 DEAL_II_NAMESPACE_CLOSE
Tensor< 1, dim > compute_grad(const unsigned int i, const Point< dim > &p) const
AnisotropicPolynomials(const std::vector< std::vector< Polynomials::Polynomial< double > > > &pols)
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
#define AssertThrow(cond, exc)
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
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()