19#include <boost/container/small_vector.hpp>
35 template <std::
size_t dim>
37 compute_tensor_index(
const unsigned int,
40 std::array<unsigned int, dim> &)
46 compute_tensor_index(
const unsigned int n,
49 std::array<unsigned int, 1> &indices)
55 compute_tensor_index(
const unsigned int n,
56 const unsigned int n_pols_0,
58 std::array<unsigned int, 2> &indices)
60 indices[0] = n % n_pols_0;
61 indices[1] = n / n_pols_0;
65 compute_tensor_index(
const unsigned int n,
66 const unsigned int n_pols_0,
67 const unsigned int n_pols_1,
68 std::array<unsigned int, 3> &indices)
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);
79template <
int dim,
typename PolynomialType>
83 std::array<unsigned int, dim> &indices)
const
85 if constexpr (dim == 0)
104template <
int dim,
typename PolynomialType>
107 std::ostream &out)
const
109 if constexpr (dim == 0)
116 std::array<unsigned int, dim> ix;
117 for (
unsigned int i = 0; i < this->
n(); ++i)
121 for (
unsigned int d = 0; d < dim; ++d)
131const std::vector<unsigned int> &
140const std::vector<unsigned int> &
151 const std::vector<unsigned int> &renumber)
157 for (
unsigned int i = 0; i <
index_map.size(); ++i)
172template <
int dim,
typename PolynomialType>
175 const std::vector<unsigned int> &renumber)
181 for (
unsigned int i = 0; i <
index_map.size(); ++i)
190 const std::vector<unsigned int> &)
197template <
int dim,
typename PolynomialType>
200 const unsigned int i,
203 if constexpr (dim == 0)
212 std::array<unsigned int, dim> indices;
216 for (
unsigned int d = 0; d < dim; ++d)
225template <
int dim,
typename PolynomialType>
228 const unsigned int i,
231 if constexpr (dim == 0)
240 std::array<unsigned int, dim> indices;
241 compute_index(i, indices);
249 std::vector<double> tmp(2);
250 for (
unsigned int d = 0; d < dim; ++d)
259 for (
unsigned int d = 0;
d < dim; ++
d)
262 for (
unsigned int x = 0; x < dim; ++x)
263 grad[d] *= v[x][d == x];
272template <
int dim,
typename PolynomialType>
275 const unsigned int i,
278 if constexpr (dim == 0)
287 std::array<unsigned int, dim> indices;
292 std::vector<double> tmp(3);
293 for (
unsigned int d = 0; d < dim; ++d)
303 for (
unsigned int d1 = 0; d1 < dim; ++d1)
304 for (
unsigned int d2 = 0; d2 < dim; ++d2)
306 grad_grad[d1][d2] = 1.;
307 for (
unsigned int x = 0; x < dim; ++x)
309 unsigned int derivative = 0;
310 if (d1 == x || d2 == x)
317 grad_grad[d1][d2] *= v[x][derivative];
337 template <
int dim, std::
size_t dim1>
340 const unsigned int n_derivatives,
343 const unsigned int size_x,
344 const boost::container::small_vector<std::array<unsigned int, dim1>, 64>
346 const std::vector<unsigned int> &index_map,
347 std::vector<double> &values,
353 const bool update_values = (values.size() == indices.size() * size_x);
354 const bool update_grads = (grads.size() == indices.size() * size_x);
355 const bool update_grad_grads =
356 (grad_grads.size() == indices.size() * size_x);
358 (third_derivatives.size() == indices.size() * size_x);
359 const bool update_4th_derivatives =
360 (fourth_derivatives.size() == indices.size() * size_x);
364 if (n_derivatives == 0)
365 for (
unsigned int i = 0, i1 = 0; i1 < indices.size(); ++i1)
367 double value_outer = 1.;
368 if constexpr (dim > 1)
369 for (
unsigned int d = 1; d < dim; ++d)
370 value_outer *= values_1d[indices[i1][d - 1]][0][d];
371 if (index_map.empty())
372 for (
unsigned int ix = 0; ix < size_x; ++ix, ++i)
373 values[i] = value_outer * values_1d[ix][0][0];
375 for (
unsigned int ix = 0; ix < size_x; ++ix, ++i)
376 values[index_map[i]] = value_outer * values_1d[ix][0][0];
379 for (
unsigned int iy = 0, i1 = 0; i1 < indices.size(); ++i1)
382 std::array<double, dim + (dim * (dim - 1)) / 2> value_outer;
384 if constexpr (dim > 1)
386 for (
unsigned int x = 1; x < dim; ++x)
387 value_outer[0] *= values_1d[indices[i1][x - 1]][0][x];
388 for (
unsigned int d = 1; d < dim; ++d)
390 value_outer[d] = values_1d[indices[i1][d - 1]][1][d];
391 for (
unsigned int x = 1; x < dim; ++x)
393 value_outer[d] *= values_1d[indices[i1][x - 1]][0][x];
395 for (
unsigned int d1 = 1, count = dim; d1 < dim; ++d1)
396 for (
unsigned int d2 = d1; d2 < dim; ++d2, ++count)
398 value_outer[count] = 1.;
399 for (
unsigned int x = 1; x < dim; ++x)
401 unsigned int derivative = 0;
407 value_outer[count] *=
408 values_1d[indices[i1][x - 1]][derivative][x];
415 for (
unsigned int ix = 0, i = iy; ix < size_x; ++ix, ++i)
417 std::array<double, 3> val_x{{values_1d[ix][0][0],
419 values_1d[ix][2][0]}};
420 const unsigned int index =
421 (index_map.empty() ? i : index_map[i]);
424 values[
index] = value_outer[0] * val_x[0];
428 grads[
index][0] = value_outer[0] * val_x[1];
429 if constexpr (dim > 1)
430 for (
unsigned int d = 1; d < dim; ++d)
431 grads[
index][d] = value_outer[d] * val_x[0];
434 if (update_grad_grads)
436 grad_grads[
index][0][0] = value_outer[0] * val_x[2];
437 if constexpr (dim > 1)
439 for (
unsigned int d = 1; d < dim; ++d)
440 grad_grads[
index][0][d] = grad_grads[
index][d][0] =
441 value_outer[d] * val_x[1];
442 for (
unsigned int d1 = 1, count = dim; d1 < dim; ++d1)
443 for (
unsigned int d2 = d1; d2 < dim; ++d2, ++count)
444 grad_grads[
index][d1][d2] =
445 grad_grads[
index][d2][d1] =
446 value_outer[count] * val_x[0];
453 for (
unsigned int ix = 0, i = iy; ix < size_x; ++ix, ++i)
455 const unsigned int index =
456 (index_map.empty() ? i : index_map[i]);
457 std::array<unsigned int, dim> my_indices;
459 if constexpr (dim > 1)
460 for (
unsigned int d = 1; d < dim; ++d)
461 my_indices[d] = indices[i1][d - 1];
462 for (
unsigned int d1 = 0; d1 < dim; ++d1)
463 for (
unsigned int d2 = 0; d2 < dim; ++d2)
464 for (
unsigned int d3 = 0; d3 < dim; ++d3)
467 for (
unsigned int x = 0; x < dim; ++x)
469 unsigned int derivative = 0;
477 der3 *= values_1d[my_indices[x]][derivative][x];
479 third_derivatives[
index][d1][d2][d3] = der3;
483 if (update_4th_derivatives)
484 for (
unsigned int ix = 0, i = iy; ix < size_x; ++ix, ++i)
486 const unsigned int index =
487 (index_map.empty() ? i : index_map[i]);
488 std::array<unsigned int, dim> my_indices;
490 if constexpr (dim > 1)
491 for (
unsigned int d = 1; d < dim; ++d)
492 my_indices[d] = indices[i1][d - 1];
493 for (
unsigned int d1 = 0; d1 < dim; ++d1)
494 for (
unsigned int d2 = 0; d2 < dim; ++d2)
495 for (
unsigned int d3 = 0; d3 < dim; ++d3)
496 for (
unsigned int d4 = 0; d4 < dim; ++d4)
499 for (
unsigned int x = 0; x < dim; ++x)
501 unsigned int derivative = 0;
511 der4 *= values_1d[my_indices[x]][derivative][x];
513 fourth_derivatives[
index][d1][d2][d3][d4] = der4;
525template <
int dim,
typename PolynomialType>
529 std::vector<double> &values,
535 if constexpr (dim == 0)
541 (void)third_derivatives;
542 (void)fourth_derivatives;
548 Assert(values.size() == this->n() || values.empty(),
550 Assert(grads.size() == this->n() || grads.empty(),
552 Assert(grad_grads.size() == this->n() || grad_grads.empty(),
554 Assert(third_derivatives.size() == this->n() || third_derivatives.empty(),
556 Assert(fourth_derivatives.size() == this->n() ||
557 fourth_derivatives.empty(),
561 unsigned int n_derivatives = 0;
562 if (values.size() == this->n())
564 if (grads.size() == this->n())
566 if (grad_grads.size() == this->n())
568 if (third_derivatives.size() == this->n())
570 if (fourth_derivatives.size() == this->n())
576 const unsigned int n_polynomials =
polynomials.size();
577 boost::container::small_vector<ndarray<double, 5, dim>, 10> values_1d(
579 if constexpr (std::is_same_v<PolynomialType,
582 std::array<double, dim> point_array;
583 for (
unsigned int d = 0; d < dim; ++d)
584 point_array[d] = p[d];
585 for (
unsigned int i = 0; i < n_polynomials; ++i)
588 values_1d[i].data());
591 for (
unsigned int i = 0; i < n_polynomials; ++i)
592 for (
unsigned int d = 0; d < dim; ++d)
594 std::array<double, 5> derivatives;
595 polynomials[i].value(p[d], n_derivatives, derivatives.data());
596 for (
unsigned int j = 0; j <= n_derivatives; ++j)
597 values_1d[i][j][d] = derivatives[j];
602 constexpr unsigned int dim1 = dim > 1 ? dim - 1 : 1;
603 boost::container::small_vector<std::array<unsigned int, dim1>, 64>
605 if constexpr (dim > 1)
606 for (
unsigned int d = 1; d < dim; ++d)
608 const unsigned int size = indices.size();
609 for (
unsigned int i = 1; i < n_polynomials; ++i)
610 for (
unsigned int j = 0; j < size; ++j)
612 std::array<unsigned int, dim1> next_index = indices[j];
613 next_index[d - 1] = i;
614 indices.push_back(next_index);
635template <
int dim,
typename PolynomialType>
636std::unique_ptr<ScalarPolynomialsBase<dim>>
639 return std::make_unique<TensorProductPolynomials<dim, PolynomialType>>(*this);
644template <
int dim,
typename PolynomialType>
655template <
int dim,
typename PolynomialType>
656std::vector<PolynomialType>
677 for (
const auto &pols_d : pols)
681 ExcMessage(
"The number of polynomials must be larger than zero "
682 "for all coordinate directions."));
687 for (
unsigned int i = 0; i < this->
n(); ++i)
699 const unsigned int i,
700 std::array<unsigned int, dim> &indices)
const
702 if constexpr (dim == 0)
712 unsigned int n_poly = 1;
713 for (
unsigned int d = 0; d < dim; ++d)
722 internal::compute_tensor_index(
index_map[i],
727 internal::compute_tensor_index(
index_map[i],
741 if constexpr (dim == 0)
750 std::array<unsigned int, dim> indices;
754 for (
unsigned int d = 0; d < dim; ++d)
768 if constexpr (dim == 0)
777 std::array<unsigned int, dim> indices;
785 for (
unsigned int d = 0; d < dim; ++d)
789 for (
unsigned int d = 0; d < dim; ++d)
792 for (
unsigned int x = 0; x < dim; ++x)
793 grad[d] *= v[x][d == x];
807 if constexpr (dim == 0)
816 std::array<unsigned int, dim> indices;
820 for (
unsigned int d = 0; d < dim; ++d)
824 for (
unsigned int d1 = 0; d1 < dim; ++d1)
825 for (
unsigned int d2 = 0; d2 < dim; ++d2)
827 grad_grad[d1][d2] = 1.;
828 for (
unsigned int x = 0; x < dim; ++x)
830 unsigned int derivative = 0;
831 if (d1 == x || d2 == x)
838 grad_grad[d1][d2] *= v[x][derivative];
852 std::vector<double> &values,
858 if constexpr (dim == 0)
864 (void)third_derivatives;
865 (void)fourth_derivatives;
870 Assert(values.size() == this->n() || values.empty(),
872 Assert(grads.size() == this->n() || grads.empty(),
874 Assert(grad_grads.size() == this->n() || grad_grads.empty(),
876 Assert(third_derivatives.size() == this->n() || third_derivatives.empty(),
878 Assert(fourth_derivatives.size() == this->n() ||
879 fourth_derivatives.empty(),
883 unsigned int n_derivatives = 0;
884 if (values.size() == this->n())
886 if (grads.size() == this->n())
888 if (grad_grads.size() == this->n())
890 if (third_derivatives.size() == this->n())
892 if (fourth_derivatives.size() == this->n())
897 std::size_t max_n_polynomials = 0;
898 for (
unsigned int d = 0; d < dim; ++d)
902 boost::container::small_vector<ndarray<double, 5, dim>, 10> values_1d(
904 if (n_derivatives == 0)
905 for (
unsigned int d = 0; d < dim; ++d)
906 for (
unsigned int i = 0; i <
polynomials[d].size(); ++i)
909 for (
unsigned int d = 0; d < dim; ++d)
910 for (
unsigned int i = 0; i <
polynomials[d].size(); ++i)
915 std::array<double, 5> derivatives;
916 polynomials[d][i].value(p[d], n_derivatives, derivatives.data());
917 for (
unsigned int j = 0; j <= n_derivatives; ++j)
918 values_1d[i][j][d] = derivatives[j];
922 constexpr unsigned int dim1 = dim > 1 ? dim - 1 : 1;
923 boost::container::small_vector<std::array<unsigned int, dim1>, 64>
925 for (
unsigned int d = 1; d < dim; ++d)
927 const unsigned int size = indices.size();
928 for (
unsigned int i = 1; i <
polynomials[d].size(); ++i)
929 for (
unsigned int j = 0; j < size; ++j)
931 std::array<unsigned int, dim1> next_index = indices[j];
932 next_index[d - 1] = i;
933 indices.push_back(next_index);
958 if constexpr (dim == 0)
967 for (
unsigned int d = 0; d < dim; ++d)
976std::unique_ptr<ScalarPolynomialsBase<dim>>
979 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)
const std::vector< std::vector< Polynomials::Polynomial< double > > > 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
ScalarPolynomialsBase(const unsigned int deg, const unsigned int n_polynomials)
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< unsigned int > index_map
std::vector< unsigned int > index_map_inverse
std::vector< PolynomialType > get_underlying_polynomials() const
std::vector< PolynomialType > polynomials
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
void set_numbering(const std::vector< unsigned int > &)
TensorProductPolynomials(const std::vector< Pol > &pols)
#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)
const bool IsBlockVector< VectorType >::value
@ update_values
Shape function values.
@ update_3rd_derivatives
Third derivatives of shape functions.
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 fixed_power(const T t)
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