19#include <boost/container/small_vector.hpp>
36 compute_tensor_index(
const unsigned int n,
39 std::array<unsigned int, 1> &indices)
45 compute_tensor_index(
const unsigned int n,
46 const unsigned int n_pols_0,
48 std::array<unsigned int, 2> &indices)
50 indices[0] = n % n_pols_0;
51 indices[1] = n / n_pols_0;
55 compute_tensor_index(
const unsigned int n,
56 const unsigned int n_pols_0,
57 const unsigned int n_pols_1,
58 std::array<unsigned int, 3> &indices)
60 indices[0] = n % n_pols_0;
61 indices[1] = (n / n_pols_0) % n_pols_1;
62 indices[2] = n / (n_pols_0 * n_pols_1);
69template <
int dim,
typename PolynomialType>
73 std::array<unsigned int, dim> &indices)
const
75 if constexpr (dim == 0)
83 Assert(i < Utilities::fixed_power<dim>(polynomials.size()),
85 internal::compute_tensor_index(index_map[i],
94template <
int dim,
typename PolynomialType>
97 std::ostream &out)
const
99 if constexpr (dim == 0)
106 std::array<unsigned int, dim> ix;
107 for (
unsigned int i = 0; i < this->n(); ++i)
109 compute_index(i, ix);
111 for (
unsigned int d = 0; d < dim; ++d)
121const std::vector<unsigned int> &
130const std::vector<unsigned int> &
133 return index_map_inverse;
141 const std::vector<unsigned int> &renumber)
143 Assert(renumber.size() == index_map.size(),
146 index_map = renumber;
147 for (
unsigned int i = 0; i < index_map.size(); ++i)
148 index_map_inverse[index_map[i]] = i;
162template <
int dim,
typename PolynomialType>
165 const std::vector<unsigned int> &renumber)
167 Assert(renumber.size() == index_map.size(),
170 index_map = renumber;
171 for (
unsigned int i = 0; i < index_map.size(); ++i)
172 index_map_inverse[index_map[i]] = i;
180 const std::vector<unsigned int> &)
187template <
int dim,
typename PolynomialType>
190 const unsigned int i,
193 if constexpr (dim == 0)
202 std::array<unsigned int, dim> indices;
203 compute_index(i, indices);
206 for (
unsigned int d = 0; d < dim; ++d)
207 value *= polynomials[indices[d]].value(p[d]);
215template <
int dim,
typename PolynomialType>
218 const unsigned int i,
221 if constexpr (dim == 0)
230 std::array<unsigned int, dim> indices;
231 compute_index(i, indices);
239 std::vector<double> tmp(2);
240 for (
unsigned int d = 0; d < dim; ++d)
242 polynomials[indices[d]].value(p[d], tmp);
249 for (
unsigned int d = 0;
d < dim; ++
d)
252 for (
unsigned int x = 0; x < dim; ++x)
253 grad[d] *= v[x][d == x];
262template <
int dim,
typename PolynomialType>
265 const unsigned int i,
268 if constexpr (dim == 0)
277 std::array<unsigned int, dim> indices;
278 compute_index(i, indices);
282 std::vector<double> tmp(3);
283 for (
unsigned int d = 0; d < dim; ++d)
285 polynomials[indices[d]].value(p[d], tmp);
293 for (
unsigned int d1 = 0; d1 < dim; ++d1)
294 for (
unsigned int d2 = 0; d2 < dim; ++d2)
296 grad_grad[d1][d2] = 1.;
297 for (
unsigned int x = 0; x < dim; ++x)
299 unsigned int derivative = 0;
300 if (d1 == x || d2 == x)
307 grad_grad[d1][d2] *= v[x][derivative];
327 template <
int dim, std::
size_t dim1>
330 const unsigned int n_derivatives,
333 const unsigned int size_x,
334 const boost::container::small_vector<std::array<unsigned int, dim1>, 64>
336 const std::vector<unsigned int> &index_map,
337 std::vector<double> &values,
343 const bool update_values = (values.size() == indices.size() * size_x);
344 const bool update_grads = (grads.size() == indices.size() * size_x);
345 const bool update_grad_grads =
346 (grad_grads.size() == indices.size() * size_x);
348 (third_derivatives.size() == indices.size() * size_x);
349 const bool update_4th_derivatives =
350 (fourth_derivatives.size() == indices.size() * size_x);
354 if (n_derivatives == 0)
355 for (
unsigned int i = 0, i1 = 0; i1 < indices.size(); ++i1)
357 double value_outer = 1.;
358 if constexpr (dim > 1)
359 for (
unsigned int d = 1; d < dim; ++d)
360 value_outer *= values_1d[indices[i1][d - 1]][0][d];
361 if (index_map.empty())
362 for (
unsigned int ix = 0; ix < size_x; ++ix, ++i)
363 values[i] = value_outer * values_1d[ix][0][0];
365 for (
unsigned int ix = 0; ix < size_x; ++ix, ++i)
366 values[index_map[i]] = value_outer * values_1d[ix][0][0];
369 for (
unsigned int iy = 0, i1 = 0; i1 < indices.size(); ++i1)
372 std::array<double, dim + (dim * (dim - 1)) / 2> value_outer;
374 if constexpr (dim > 1)
376 for (
unsigned int x = 1; x < dim; ++x)
377 value_outer[0] *= values_1d[indices[i1][x - 1]][0][x];
378 for (
unsigned int d = 1; d < dim; ++d)
380 value_outer[d] = values_1d[indices[i1][d - 1]][1][d];
381 for (
unsigned int x = 1; x < dim; ++x)
383 value_outer[d] *= values_1d[indices[i1][x - 1]][0][x];
385 for (
unsigned int d1 = 1, count = dim; d1 < dim; ++d1)
386 for (
unsigned int d2 = d1; d2 < dim; ++d2, ++count)
388 value_outer[count] = 1.;
389 for (
unsigned int x = 1; x < dim; ++x)
391 unsigned int derivative = 0;
397 value_outer[count] *=
398 values_1d[indices[i1][x - 1]][derivative][x];
405 for (
unsigned int ix = 0, i = iy; ix < size_x; ++ix, ++i)
407 std::array<double, 3> val_x{{values_1d[ix][0][0],
409 values_1d[ix][2][0]}};
410 const unsigned int index =
411 (index_map.empty() ? i : index_map[i]);
414 values[
index] = value_outer[0] * val_x[0];
418 grads[
index][0] = value_outer[0] * val_x[1];
419 if constexpr (dim > 1)
420 for (
unsigned int d = 1; d < dim; ++d)
421 grads[
index][d] = value_outer[d] * val_x[0];
424 if (update_grad_grads)
426 grad_grads[
index][0][0] = value_outer[0] * val_x[2];
427 if constexpr (dim > 1)
429 for (
unsigned int d = 1; d < dim; ++d)
430 grad_grads[
index][0][d] = grad_grads[
index][d][0] =
431 value_outer[d] * val_x[1];
432 for (
unsigned int d1 = 1, count = dim; d1 < dim; ++d1)
433 for (
unsigned int d2 = d1; d2 < dim; ++d2, ++count)
434 grad_grads[
index][d1][d2] =
435 grad_grads[
index][d2][d1] =
436 value_outer[count] * val_x[0];
443 for (
unsigned int ix = 0, i = iy; ix < size_x; ++ix, ++i)
445 const unsigned int index =
446 (index_map.empty() ? i : index_map[i]);
447 std::array<unsigned int, dim> my_indices;
449 if constexpr (dim > 1)
450 for (
unsigned int d = 1; d < dim; ++d)
451 my_indices[d] = indices[i1][d - 1];
452 for (
unsigned int d1 = 0; d1 < dim; ++d1)
453 for (
unsigned int d2 = 0; d2 < dim; ++d2)
454 for (
unsigned int d3 = 0; d3 < dim; ++d3)
457 for (
unsigned int x = 0; x < dim; ++x)
459 unsigned int derivative = 0;
467 der3 *= values_1d[my_indices[x]][derivative][x];
469 third_derivatives[
index][d1][d2][d3] = der3;
473 if (update_4th_derivatives)
474 for (
unsigned int ix = 0, i = iy; ix < size_x; ++ix, ++i)
476 const unsigned int index =
477 (index_map.empty() ? i : index_map[i]);
478 std::array<unsigned int, dim> my_indices;
480 if constexpr (dim > 1)
481 for (
unsigned int d = 1; d < dim; ++d)
482 my_indices[d] = indices[i1][d - 1];
483 for (
unsigned int d1 = 0; d1 < dim; ++d1)
484 for (
unsigned int d2 = 0; d2 < dim; ++d2)
485 for (
unsigned int d3 = 0; d3 < dim; ++d3)
486 for (
unsigned int d4 = 0; d4 < dim; ++d4)
489 for (
unsigned int x = 0; x < dim; ++x)
491 unsigned int derivative = 0;
501 der4 *= values_1d[my_indices[x]][derivative][x];
503 fourth_derivatives[
index][d1][d2][d3][d4] = der4;
515template <
int dim,
typename PolynomialType>
519 std::vector<double> &values,
525 if constexpr (dim == 0)
531 (void)third_derivatives;
532 (void)fourth_derivatives;
538 Assert(values.size() == this->n() || values.empty(),
540 Assert(grads.size() == this->n() || grads.empty(),
542 Assert(grad_grads.size() == this->n() || grad_grads.empty(),
544 Assert(third_derivatives.size() == this->n() || third_derivatives.empty(),
546 Assert(fourth_derivatives.size() == this->n() ||
547 fourth_derivatives.empty(),
551 unsigned int n_derivatives = 0;
552 if (values.size() == this->n())
554 if (grads.size() == this->n())
556 if (grad_grads.size() == this->n())
558 if (third_derivatives.size() == this->n())
560 if (fourth_derivatives.size() == this->n())
566 const unsigned int n_polynomials = polynomials.size();
567 boost::container::small_vector<ndarray<double, 5, dim>, 10> values_1d(
569 if constexpr (std::is_same_v<PolynomialType,
572 std::array<double, dim> point_array;
573 for (
unsigned int d = 0; d < dim; ++d)
574 point_array[d] = p[d];
575 for (
unsigned int i = 0; i < n_polynomials; ++i)
576 polynomials[i].values_of_array(point_array,
578 values_1d[i].
data());
581 for (
unsigned int i = 0; i < n_polynomials; ++i)
582 for (
unsigned int d = 0; d < dim; ++d)
584 std::array<double, 5> derivatives;
585 polynomials[i].value(p[d], n_derivatives, derivatives.data());
586 for (
unsigned int j = 0; j <= n_derivatives; ++j)
587 values_1d[i][j][d] = derivatives[j];
592 constexpr unsigned int dim1 = dim > 1 ? dim - 1 : 1;
593 boost::container::small_vector<std::array<unsigned int, dim1>, 64>
595 if constexpr (dim > 1)
596 for (
unsigned int d = 1; d < dim; ++d)
598 const unsigned int size = indices.size();
599 for (
unsigned int i = 1; i < n_polynomials; ++i)
600 for (
unsigned int j = 0; j <
size; ++j)
602 std::array<unsigned int, dim1> next_index = indices[j];
603 next_index[d - 1] = i;
604 indices.push_back(next_index);
609 internal::TensorProductPolynomials::evaluate_tensor_product<dim>(
625template <
int dim,
typename PolynomialType>
626std::unique_ptr<ScalarPolynomialsBase<dim>>
629 return std::make_unique<TensorProductPolynomials<dim, PolynomialType>>(*this);
634template <
int dim,
typename PolynomialType>
645template <
int dim,
typename PolynomialType>
646std::vector<PolynomialType>
663 , index_map(this->n())
664 , index_map_inverse(this->n())
667 for (
const auto &pols_d : pols)
671 ExcMessage(
"The number of polynomials must be larger than zero "
672 "for all coordinate directions."));
677 for (
unsigned int i = 0; i < this->
n(); ++i)
689 const unsigned int i,
690 std::array<unsigned int, dim> &indices)
const
692 if constexpr (dim == 0)
702 unsigned int n_poly = 1;
703 for (
unsigned int d = 0; d < dim; ++d)
704 n_poly *= polynomials[d].
size();
712 internal::compute_tensor_index(index_map[i],
713 polynomials[0].
size(),
717 internal::compute_tensor_index(index_map[i],
718 polynomials[0].
size(),
719 polynomials[1].
size(),
731 if constexpr (dim == 0)
740 std::array<unsigned int, dim> indices;
741 compute_index(i, indices);
744 for (
unsigned int d = 0; d < dim; ++d)
745 value *= polynomials[d][indices[d]].value(p[d]);
758 if constexpr (dim == 0)
767 std::array<unsigned int, dim> indices;
768 compute_index(i, indices);
775 for (
unsigned int d = 0; d < dim; ++d)
776 polynomials[d][indices[d]].value(p[d], 1, v[d].
data());
779 for (
unsigned int d = 0; d < dim; ++d)
782 for (
unsigned int x = 0; x < dim; ++x)
783 grad[d] *= v[x][d == x];
797 if constexpr (dim == 0)
806 std::array<unsigned int, dim> indices;
807 compute_index(i, indices);
810 for (
unsigned int d = 0; d < dim; ++d)
811 polynomials[d][indices[d]].value(p[d], 2, v[d].
data());
814 for (
unsigned int d1 = 0; d1 < dim; ++d1)
815 for (
unsigned int d2 = 0; d2 < dim; ++d2)
817 grad_grad[d1][d2] = 1.;
818 for (
unsigned int x = 0; x < dim; ++x)
820 unsigned int derivative = 0;
821 if (d1 == x || d2 == x)
828 grad_grad[d1][d2] *= v[x][derivative];
842 std::vector<double> &values,
848 if constexpr (dim == 0)
854 (void)third_derivatives;
855 (void)fourth_derivatives;
860 Assert(values.size() == this->n() || values.empty(),
862 Assert(grads.size() == this->n() || grads.empty(),
864 Assert(grad_grads.size() == this->n() || grad_grads.empty(),
866 Assert(third_derivatives.size() == this->n() || third_derivatives.empty(),
868 Assert(fourth_derivatives.size() == this->n() ||
869 fourth_derivatives.empty(),
873 unsigned int n_derivatives = 0;
874 if (values.size() == this->n())
876 if (grads.size() == this->n())
878 if (grad_grads.size() == this->n())
880 if (third_derivatives.size() == this->n())
882 if (fourth_derivatives.size() == this->n())
887 std::size_t max_n_polynomials = 0;
888 for (
unsigned int d = 0; d < dim; ++d)
889 max_n_polynomials =
std::max(max_n_polynomials, polynomials[d].
size());
892 boost::container::small_vector<ndarray<double, 5, dim>, 10> values_1d(
894 if (n_derivatives == 0)
895 for (
unsigned int d = 0; d < dim; ++d)
896 for (
unsigned int i = 0; i < polynomials[d].size(); ++i)
897 values_1d[i][0][d] = polynomials[d][i].value(p[d]);
899 for (
unsigned int d = 0; d < dim; ++d)
900 for (
unsigned int i = 0; i < polynomials[d].size(); ++i)
905 std::array<double, 5> derivatives;
906 polynomials[d][i].value(p[d], n_derivatives, derivatives.data());
907 for (
unsigned int j = 0; j <= n_derivatives; ++j)
908 values_1d[i][j][d] = derivatives[j];
912 constexpr unsigned int dim1 = dim > 1 ? dim - 1 : 1;
913 boost::container::small_vector<std::array<unsigned int, dim1>, 64>
915 for (
unsigned int d = 1; d < dim; ++d)
917 const unsigned int size = indices.size();
918 for (
unsigned int i = 1; i < polynomials[d].size(); ++i)
919 for (
unsigned int j = 0; j <
size; ++j)
921 std::array<unsigned int, dim1> next_index = indices[j];
922 next_index[d - 1] = i;
923 indices.push_back(next_index);
927 internal::TensorProductPolynomials::evaluate_tensor_product<dim>(
930 polynomials[0].
size(),
948 if constexpr (dim == 0)
957 for (
unsigned int d = 0; d < dim; ++d)
966std::unique_ptr<ScalarPolynomialsBase<dim>>
969 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
void set_numbering(const std::vector< unsigned int > &renumber)
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)
std::vector< unsigned int > index_map
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
const std::vector< unsigned int > & get_numbering() const
Tensor< 1, dim > compute_grad(const unsigned int i, const Point< dim > &p) const override
std::vector< unsigned int > index_map_inverse
const std::vector< unsigned int > & get_numbering_inverse() const
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
constexpr bool running_in_debug_mode()
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_NOT_IMPLEMENTED()
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcDimensionMismatch2(std::size_t arg1, std::size_t arg2, std::size_t arg3)
#define AssertDimension(dim1, dim2)
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::vector< index_type > data
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
constexpr T pow(const T base, const int iexp)
void evaluate_tensor_product(const unsigned int n_derivatives, const boost::container::small_vector<::ndarray< double, 5, dim >, 10 > &values_1d, const unsigned int size_x, const boost::container::small_vector< std::array< unsigned int, dim1 >, 64 > &indices, const std::vector< unsigned int > &index_map, 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)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
typename internal::ndarray::HelperArray< T, Ns... >::type ndarray