22#include <boost/container/small_vector.hpp>
38 template <std::
size_t dim>
40 compute_tensor_index(
const unsigned int,
43 std::array<unsigned int, dim> &)
49 compute_tensor_index(
const unsigned int n,
52 std::array<unsigned int, 1> &indices)
58 compute_tensor_index(
const unsigned int n,
59 const unsigned int n_pols_0,
61 std::array<unsigned int, 2> &indices)
63 indices[0] = n % n_pols_0;
64 indices[1] = n / n_pols_0;
68 compute_tensor_index(
const unsigned int n,
69 const unsigned int n_pols_0,
70 const unsigned int n_pols_1,
71 std::array<unsigned int, 3> &indices)
73 indices[0] = n % n_pols_0;
74 indices[1] = (n / n_pols_0) % n_pols_1;
75 indices[2] = n / (n_pols_0 * n_pols_1);
82template <
int dim,
typename PolynomialType>
86 std::array<unsigned int, dim> &indices)
const
88 Assert(i < Utilities::fixed_power<dim>(polynomials.size()),
90 internal::compute_tensor_index(index_map[i],
102 std::array<unsigned int, 0> &)
const
104 constexpr int dim = 0;
110template <
int dim,
typename PolynomialType>
113 std::ostream &out)
const
115 std::array<unsigned int, dim> ix;
116 for (
unsigned int i = 0; i < this->n(); ++i)
118 compute_index(i, ix);
120 for (
unsigned int d = 0; d < dim; ++d)
131 std::ostream &)
const
133 constexpr int dim = 0;
139template <
int dim,
typename PolynomialType>
142 const std::vector<unsigned int> &renumber)
144 Assert(renumber.size() == index_map.size(),
147 index_map = renumber;
148 for (
unsigned int i = 0; i < index_map.size(); ++i)
149 index_map_inverse[index_map[i]] = i;
157 const std::vector<unsigned int> &)
159 constexpr int dim = 0;
165template <
int dim,
typename PolynomialType>
168 const unsigned int i,
173 std::array<unsigned int, dim> indices;
174 compute_index(i, indices);
177 for (
unsigned int d = 0; d < dim; ++d)
178 value *= polynomials[indices[d]].value(p(d));
191 constexpr int dim = 0;
199template <
int dim,
typename PolynomialType>
202 const unsigned int i,
205 std::array<unsigned int, dim> indices;
206 compute_index(i, indices);
214 std::vector<double> tmp(2);
215 for (
unsigned int d = 0; d < dim; ++d)
217 polynomials[indices[d]].value(p(d), tmp);
224 for (
unsigned int d = 0; d < dim; ++d)
227 for (
unsigned int x = 0; x < dim; ++x)
228 grad[d] *= v[x][d == x];
242 constexpr int dim = 0;
250template <
int dim,
typename PolynomialType>
253 const unsigned int i,
256 std::array<unsigned int, dim> indices;
257 compute_index(i, indices);
261 std::vector<double> tmp(3);
262 for (
unsigned int d = 0; d < dim; ++d)
264 polynomials[indices[d]].value(p(d), tmp);
272 for (
unsigned int d1 = 0; d1 < dim; ++d1)
273 for (
unsigned int d2 = 0; d2 < dim; ++d2)
275 grad_grad[d1][d2] = 1.;
276 for (
unsigned int x = 0; x < dim; ++x)
278 unsigned int derivative = 0;
279 if (d1 == x || d2 == x)
286 grad_grad[d1][d2] *= v[x][derivative];
306template <
int dim,
typename PolynomialType>
310 std::vector<double> & values,
317 Assert(values.size() == this->n() || values.size() == 0,
319 Assert(grads.size() == this->n() || grads.size() == 0,
321 Assert(grad_grads.size() == this->n() || grad_grads.size() == 0,
323 Assert(third_derivatives.size() == this->n() || third_derivatives.size() == 0,
325 Assert(fourth_derivatives.size() == this->n() ||
326 fourth_derivatives.size() == 0,
330 update_grads = (grads.size() == this->n()),
331 update_grad_grads = (grad_grads.size() == this->n()),
333 update_4th_derivatives = (fourth_derivatives.size() == this->n());
336 unsigned int n_values_and_derivatives = 0;
338 n_values_and_derivatives = 1;
340 n_values_and_derivatives = 2;
341 if (update_grad_grads)
342 n_values_and_derivatives = 3;
344 n_values_and_derivatives = 4;
345 if (update_4th_derivatives)
346 n_values_and_derivatives = 5;
353 const unsigned int n_polynomials = polynomials.size();
354 boost::container::small_vector<ndarray<double, dim, 5>, 20> values_1d(
356 if (n_values_and_derivatives == 1)
357 for (
unsigned int i = 0; i < n_polynomials; ++i)
358 for (
unsigned int d = 0; d < dim; ++d)
359 values_1d[i][d][0] = polynomials[i].value(p(d));
361 for (
unsigned int i = 0; i < n_polynomials; ++i)
362 for (
unsigned d = 0; d < dim; ++d)
363 polynomials[i].value(p(d),
364 n_values_and_derivatives,
365 values_1d[i][d].data());
367 unsigned int indices[3];
368 unsigned int ind = 0;
369 for (indices[2] = 0; indices[2] < (dim > 2 ? n_polynomials : 1); ++indices[2])
370 for (indices[1] = 0; indices[1] < (dim > 1 ? n_polynomials : 1);
372 if (n_values_and_derivatives == 1)
373 for (indices[0] = 0; indices[0] < n_polynomials; ++indices[0], ++ind)
375 double value = values_1d[indices[0]][0][0];
376 for (
unsigned int d = 1; d < dim; ++d)
377 value *= values_1d[indices[d]][d][0];
378 values[index_map_inverse[ind]] = value;
381 for (indices[0] = 0; indices[0] < n_polynomials; ++indices[0], ++ind)
383 const unsigned int i = index_map_inverse[ind];
387 double value = values_1d[indices[0]][0][0];
388 for (
unsigned int x = 1; x < dim; ++x)
389 value *= values_1d[indices[x]][x][0];
394 for (
unsigned int d = 0; d < dim; ++d)
397 for (
unsigned int x = 0; x < dim; ++x)
398 grad *= values_1d[indices[x]][x][(d == x) ? 1 : 0];
402 if (update_grad_grads)
403 for (
unsigned int d1 = 0; d1 < dim; ++d1)
404 for (
unsigned int d2 = 0; d2 < dim; ++d2)
407 for (
unsigned int x = 0; x < dim; ++x)
409 unsigned int derivative = 0;
415 der2 *= values_1d[indices[x]][x][derivative];
417 grad_grads[i][d1][d2] = der2;
421 for (
unsigned int d1 = 0; d1 < dim; ++d1)
422 for (
unsigned int d2 = 0; d2 < dim; ++d2)
423 for (
unsigned int d3 = 0; d3 < dim; ++d3)
426 for (
unsigned int x = 0; x < dim; ++x)
428 unsigned int derivative = 0;
436 der3 *= values_1d[indices[x]][x][derivative];
438 third_derivatives[i][d1][d2][d3] = der3;
441 if (update_4th_derivatives)
442 for (
unsigned int d1 = 0; d1 < dim; ++d1)
443 for (
unsigned int d2 = 0; d2 < dim; ++d2)
444 for (
unsigned int d3 = 0; d3 < dim; ++d3)
445 for (
unsigned int d4 = 0; d4 < dim; ++d4)
448 for (
unsigned int x = 0; x < dim; ++x)
450 unsigned int derivative = 0;
460 der4 *= values_1d[indices[x]][x][derivative];
462 fourth_derivatives[i][d1][d2][d3][d4] = der4;
473 std::vector<double> &,
479 constexpr int dim = 0;
485template <
int dim,
typename PolynomialType>
486std::unique_ptr<ScalarPolynomialsBase<dim>>
489 return std::make_unique<TensorProductPolynomials<dim, PolynomialType>>(*this);
494template <
int dim,
typename PolynomialType>
505template <
int dim,
typename PolynomialType>
506std::vector<PolynomialType>
525 for (
const auto &pols_d : pols)
529 ExcMessage(
"The number of polynomials must be larger than zero "
530 "for all coordinate directions."));
539 const unsigned int i,
540 std::array<unsigned int, dim> &indices)
const
543 unsigned int n_poly = 1;
544 for (
unsigned int d = 0; d < dim; ++d)
545 n_poly *= polynomials[d].size();
552 internal::compute_tensor_index(i,
553 polynomials[0].size(),
557 internal::compute_tensor_index(i,
558 polynomials[0].size(),
559 polynomials[1].size(),
568 std::array<unsigned int, 0> &)
const
570 constexpr int dim = 0;
581 std::array<unsigned int, dim> indices;
582 compute_index(i, indices);
585 for (
unsigned int d = 0; d < dim; ++d)
586 value *= polynomials[d][indices[d]].value(p(d));
598 constexpr int dim = 0;
611 std::array<unsigned int, dim> indices;
612 compute_index(i, indices);
619 for (
unsigned int d = 0; d < dim; ++d)
620 polynomials[d][indices[d]].value(p(d), 1, v[d].data());
623 for (
unsigned int d = 0; d < dim; ++d)
626 for (
unsigned int x = 0; x < dim; ++x)
627 grad[d] *= v[x][d == x];
640 constexpr int dim = 0;
653 std::array<unsigned int, dim> indices;
654 compute_index(i, indices);
657 for (
unsigned int d = 0; d < dim; ++d)
658 polynomials[d][indices[d]].value(p(d), 2, v[d].data());
661 for (
unsigned int d1 = 0; d1 < dim; ++d1)
662 for (
unsigned int d2 = 0; d2 < dim; ++d2)
664 grad_grad[d1][d2] = 1.;
665 for (
unsigned int x = 0; x < dim; ++x)
667 unsigned int derivative = 0;
668 if (d1 == x || d2 == x)
675 grad_grad[d1][d2] *= v[x][derivative];
689 constexpr int dim = 0;
701 std::vector<double> & values,
707 Assert(values.size() == this->n() || values.size() == 0,
709 Assert(grads.size() == this->n() || grads.size() == 0,
711 Assert(grad_grads.size() == this->n() || grad_grads.size() == 0,
713 Assert(third_derivatives.size() == this->n() || third_derivatives.size() == 0,
715 Assert(fourth_derivatives.size() == this->n() ||
716 fourth_derivatives.size() == 0,
720 update_grads = (grads.size() == this->n()),
721 update_grad_grads = (grad_grads.size() == this->n()),
723 update_4th_derivatives = (fourth_derivatives.size() == this->n());
728 unsigned int n_values_and_derivatives = 0;
730 n_values_and_derivatives = 1;
732 n_values_and_derivatives = 2;
733 if (update_grad_grads)
734 n_values_and_derivatives = 3;
736 n_values_and_derivatives = 4;
737 if (update_4th_derivatives)
738 n_values_and_derivatives = 5;
744 std::size_t max_n_polynomials = 0;
745 for (
unsigned int d = 0; d < dim; ++d)
746 max_n_polynomials =
std::max(max_n_polynomials, polynomials[d].size());
750 for (
unsigned int d = 0; d < dim; ++d)
751 for (
unsigned int i = 0; i < polynomials[d].size(); ++i)
752 polynomials[d][i].value(p(d),
753 n_values_and_derivatives - 1,
756 for (
unsigned int i = 0; i < this->n(); ++i)
762 std::array<unsigned int, dim> indices;
763 compute_index(i, indices);
768 for (
unsigned int x = 0; x < dim; ++x)
769 values[i] *= v(x, indices[x])[0];
773 for (
unsigned int d = 0; d < dim; ++d)
776 for (
unsigned int x = 0; x < dim; ++x)
777 grads[i][d] *= v(x, indices[x])[d == x ? 1 : 0];
780 if (update_grad_grads)
781 for (
unsigned int d1 = 0; d1 < dim; ++d1)
782 for (
unsigned int d2 = 0; d2 < dim; ++d2)
784 grad_grads[i][d1][d2] = 1.;
785 for (
unsigned int x = 0; x < dim; ++x)
787 unsigned int derivative = 0;
793 grad_grads[i][d1][d2] *= v(x, indices[x])[derivative];
798 for (
unsigned int d1 = 0; d1 < dim; ++d1)
799 for (
unsigned int d2 = 0; d2 < dim; ++d2)
800 for (
unsigned int d3 = 0; d3 < dim; ++d3)
802 third_derivatives[i][d1][d2][d3] = 1.;
803 for (
unsigned int x = 0; x < dim; ++x)
805 unsigned int derivative = 0;
813 third_derivatives[i][d1][d2][d3] *=
814 v(x, indices[x])[derivative];
818 if (update_4th_derivatives)
819 for (
unsigned int d1 = 0; d1 < dim; ++d1)
820 for (
unsigned int d2 = 0; d2 < dim; ++d2)
821 for (
unsigned int d3 = 0; d3 < dim; ++d3)
822 for (
unsigned int d4 = 0; d4 < dim; ++d4)
824 fourth_derivatives[i][d1][d2][d3][d4] = 1.;
825 for (
unsigned int x = 0; x < dim; ++x)
827 unsigned int derivative = 0;
837 fourth_derivatives[i][d1][d2][d3][d4] *=
838 v(x, indices[x])[derivative];
849 std::vector<double> &,
855 constexpr int dim = 0;
867 for (
unsigned int d = 0; d < dim; ++d)
879 constexpr int dim = 0;
888std::unique_ptr<ScalarPolynomialsBase<dim>>
891 return std::make_unique<AnisotropicPolynomials<dim>>(*this);
void evaluate(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 override
double compute_value(const unsigned int i, const Point< dim > &p) const override
AnisotropicPolynomials(const std::vector< std::vector< Polynomials::Polynomial< double > > > &base_polynomials)
static unsigned int get_n_tensor_pols(const std::vector< std::vector< Polynomials::Polynomial< double > > > &pols)
void compute_index(const unsigned int i, std::array< unsigned int, dim > &indices) const
Tensor< 2, dim > compute_grad_grad(const unsigned int i, const Point< dim > &p) const override
Tensor< 1, dim > compute_grad(const unsigned int i, const Point< dim > &p) const override
virtual std::unique_ptr< ScalarPolynomialsBase< dim > > clone() const override
void evaluate(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 override
void output_indices(std::ostream &out) const
void compute_index(const unsigned int i, std::array< unsigned int, dim > &indices) const
double compute_value(const unsigned int i, const Point< dim > &p) const override
virtual std::size_t memory_consumption() const override
Tensor< 1, dim > compute_grad(const unsigned int i, const Point< dim > &p) const override
virtual std::unique_ptr< ScalarPolynomialsBase< dim > > clone() const override
std::vector< PolynomialType > get_underlying_polynomials() const
void set_numbering(const std::vector< unsigned int > &renumber)
Tensor< 2, dim > compute_grad_grad(const unsigned int i, const Point< dim > &p) const override
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcDimensionMismatch2(std::size_t arg1, std::size_t arg2, std::size_t arg3)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
@ update_values
Shape function values.
@ update_3rd_derivatives
Third derivatives of shape functions.
std::enable_if_t< std::is_fundamental< T >::value, std::size_t > memory_consumption(const T &t)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
typename internal::ndarray::HelperArray< T, Ns... >::type ndarray