22 #include <boost/container/small_vector.hpp>
37 template <std::
size_t dim>
39 compute_tensor_index(
const unsigned int,
42 std::array<unsigned int, dim> &)
48 compute_tensor_index(
const unsigned int n,
51 std::array<unsigned int, 1> &indices)
57 compute_tensor_index(
const unsigned int n,
58 const unsigned int n_pols_0,
60 std::array<unsigned int, 2> &indices)
62 indices[0] = n % n_pols_0;
63 indices[1] = n / n_pols_0;
67 compute_tensor_index(
const unsigned int n,
68 const unsigned int n_pols_0,
69 const unsigned int n_pols_1,
70 std::array<unsigned int, 3> &indices)
72 indices[0] = n % n_pols_0;
73 indices[1] = (n / n_pols_0) % n_pols_1;
74 indices[2] = n / (n_pols_0 * n_pols_1);
81 template <
int dim,
typename PolynomialType>
85 std::array<unsigned int, dim> &indices)
const
87 Assert(i < Utilities::fixed_power<dim>(polynomials.size()),
89 internal::compute_tensor_index(index_map[i],
97 template <
int dim,
typename PolynomialType>
100 std::ostream &out)
const
102 std::array<unsigned int, dim> ix;
103 for (
unsigned int i = 0; i < this->n(); ++i)
107 for (
unsigned int d = 0;
d < dim; ++
d)
115 template <
int dim,
typename PolynomialType>
118 const std::vector<unsigned int> &renumber)
120 Assert(renumber.size() == index_map.size(),
123 index_map = renumber;
124 for (
unsigned int i = 0; i < index_map.size(); ++i)
125 index_map_inverse[index_map[i]] = i;
142 template <
int dim,
typename PolynomialType>
145 const unsigned int i,
150 std::array<unsigned int, dim> indices;
154 for (
unsigned int d = 0;
d < dim; ++
d)
162 template <
int dim,
typename PolynomialType>
165 const unsigned int i,
168 std::array<unsigned int, dim> indices;
175 std::array<std::array<double, 2>, dim> v;
177 std::vector<double> tmp(2);
178 for (
unsigned int d = 0;
d < dim; ++
d)
180 polynomials[indices[
d]].value(p(
d), tmp);
187 for (
unsigned int d = 0;
d < dim; ++
d)
190 for (
unsigned int x = 0; x < dim; ++x)
191 grad[
d] *= v[x][
d == x];
210 template <
int dim,
typename PolynomialType>
213 const unsigned int i,
216 std::array<unsigned int, dim> indices;
219 std::array<std::array<double, 3>, dim> v;
221 std::vector<double> tmp(3);
222 for (
unsigned int d = 0;
d < dim; ++
d)
224 polynomials[indices[
d]].value(p(
d), tmp);
232 for (
unsigned int d1 = 0; d1 < dim; ++d1)
233 for (
unsigned int d2 = 0; d2 < dim; ++d2)
235 grad_grad[d1][d2] = 1.;
236 for (
unsigned int x = 0; x < dim; ++x)
238 unsigned int derivative = 0;
239 if (d1 == x || d2 == x)
246 grad_grad[d1][d2] *= v[x][derivative];
266 template <
int dim,
typename PolynomialType>
270 std::vector<double> & values,
277 Assert(values.size() == this->n() || values.size() == 0,
279 Assert(grads.size() == this->n() || grads.size() == 0,
281 Assert(grad_grads.size() == this->n() || grad_grads.size() == 0,
283 Assert(third_derivatives.size() == this->n() || third_derivatives.size() == 0,
285 Assert(fourth_derivatives.size() == this->n() ||
286 fourth_derivatives.size() == 0,
290 update_grads = (grads.size() == this->n()),
291 update_grad_grads = (grad_grads.size() == this->n()),
293 update_4th_derivatives = (fourth_derivatives.size() == this->n());
296 unsigned int n_values_and_derivatives = 0;
298 n_values_and_derivatives = 1;
300 n_values_and_derivatives = 2;
301 if (update_grad_grads)
302 n_values_and_derivatives = 3;
304 n_values_and_derivatives = 4;
305 if (update_4th_derivatives)
306 n_values_and_derivatives = 5;
313 const unsigned int n_polynomials = polynomials.size();
314 boost::container::small_vector<std::array<std::array<double, 5>, dim>, 20>
315 values_1d(n_polynomials);
316 if (n_values_and_derivatives == 1)
317 for (
unsigned int i = 0; i < n_polynomials; ++i)
318 for (
unsigned int d = 0;
d < dim; ++
d)
319 values_1d[i][
d][0] = polynomials[i].
value(p(
d));
321 for (
unsigned int i = 0; i < n_polynomials; ++i)
322 for (
unsigned d = 0;
d < dim; ++
d)
323 polynomials[i].
value(p(
d),
324 n_values_and_derivatives,
325 values_1d[i][
d].data());
327 unsigned int indices[3];
328 unsigned int ind = 0;
329 for (indices[2] = 0; indices[2] < (dim > 2 ? n_polynomials : 1); ++indices[2])
330 for (indices[1] = 0; indices[1] < (dim > 1 ? n_polynomials : 1);
332 if (n_values_and_derivatives == 1)
333 for (indices[0] = 0; indices[0] < n_polynomials; ++indices[0], ++ind)
335 double value = values_1d[indices[0]][0][0];
336 for (
unsigned int d = 1;
d < dim; ++
d)
337 value *= values_1d[indices[
d]][
d][0];
338 values[index_map_inverse[ind]] =
value;
341 for (indices[0] = 0; indices[0] < n_polynomials; ++indices[0], ++ind)
343 unsigned int i = index_map_inverse[ind];
347 double value = values_1d[indices[0]][0][0];
348 for (
unsigned int x = 1; x < dim; ++x)
349 value *= values_1d[indices[x]][x][0];
354 for (
unsigned int d = 0;
d < dim; ++
d)
357 for (
unsigned int x = 0; x < dim; ++x)
358 grad *= values_1d[indices[x]][x][(
d == x) ? 1 : 0];
362 if (update_grad_grads)
363 for (
unsigned int d1 = 0; d1 < dim; ++d1)
364 for (
unsigned int d2 = 0; d2 < dim; ++d2)
367 for (
unsigned int x = 0; x < dim; ++x)
369 unsigned int derivative = 0;
375 der2 *= values_1d[indices[x]][x][derivative];
377 grad_grads[i][d1][d2] = der2;
381 for (
unsigned int d1 = 0; d1 < dim; ++d1)
382 for (
unsigned int d2 = 0; d2 < dim; ++d2)
383 for (
unsigned int d3 = 0; d3 < dim; ++d3)
386 for (
unsigned int x = 0; x < dim; ++x)
388 unsigned int derivative = 0;
396 der3 *= values_1d[indices[x]][x][derivative];
398 third_derivatives[i][d1][d2][d3] = der3;
401 if (update_4th_derivatives)
402 for (
unsigned int d1 = 0; d1 < dim; ++d1)
403 for (
unsigned int d2 = 0; d2 < dim; ++d2)
404 for (
unsigned int d3 = 0; d3 < dim; ++d3)
405 for (
unsigned int d4 = 0; d4 < dim; ++d4)
408 for (
unsigned int x = 0; x < dim; ++x)
410 unsigned int derivative = 0;
420 der4 *= values_1d[indices[x]][x][derivative];
422 fourth_derivatives[i][d1][d2][d3][d4] = der4;
429 template <
int dim,
typename PolynomialType>
430 std::unique_ptr<ScalarPolynomialsBase<dim>>
433 return std_cxx14::make_unique<TensorProductPolynomials<dim, PolynomialType>>(
439 template <
int dim,
typename PolynomialType>
460 for (
unsigned int d = 0;
d < dim; ++
d)
462 ExcMessage(
"The number of polynomials must be larger than zero "
463 "for all coordinate directions."));
471 const unsigned int i,
472 std::array<unsigned int, dim> &indices)
const
475 unsigned int n_poly = 1;
476 for (
unsigned int d = 0;
d < dim; ++
d)
477 n_poly *= polynomials[
d].size();
485 internal::compute_tensor_index(i,
486 polynomials[0].size(),
490 internal::compute_tensor_index(i,
491 polynomials[0].size(),
492 polynomials[1].size(),
503 std::array<unsigned int, dim> indices;
507 for (
unsigned int d = 0;
d < dim; ++
d)
519 std::array<unsigned int, dim> indices;
526 std::vector<std::vector<double>> v(dim, std::vector<double>(2));
527 for (
unsigned int d = 0;
d < dim; ++
d)
528 polynomials[
d][indices[
d]].
value(p(
d), v[
d]);
531 for (
unsigned int d = 0;
d < dim; ++
d)
534 for (
unsigned int x = 0; x < dim; ++x)
535 grad[
d] *= v[x][
d == x];
547 std::array<unsigned int, dim> indices;
550 std::vector<std::vector<double>> v(dim, std::vector<double>(3));
551 for (
unsigned int d = 0;
d < dim; ++
d)
552 polynomials[
d][indices[
d]].
value(p(
d), v[
d]);
555 for (
unsigned int d1 = 0; d1 < dim; ++d1)
556 for (
unsigned int d2 = 0; d2 < dim; ++d2)
558 grad_grad[d1][d2] = 1.;
559 for (
unsigned int x = 0; x < dim; ++x)
561 unsigned int derivative = 0;
562 if (d1 == x || d2 == x)
569 grad_grad[d1][d2] *= v[x][derivative];
582 std::vector<double> & values,
588 Assert(values.size() == this->n() || values.size() == 0,
590 Assert(grads.size() == this->n() || grads.size() == 0,
592 Assert(grad_grads.size() == this->n() || grad_grads.size() == 0,
594 Assert(third_derivatives.size() == this->n() || third_derivatives.size() == 0,
596 Assert(fourth_derivatives.size() == this->n() ||
597 fourth_derivatives.size() == 0,
601 update_grads = (grads.size() == this->n()),
602 update_grad_grads = (grad_grads.size() == this->n()),
604 update_4th_derivatives = (fourth_derivatives.size() == this->n());
609 unsigned int n_values_and_derivatives = 0;
611 n_values_and_derivatives = 1;
613 n_values_and_derivatives = 2;
614 if (update_grad_grads)
615 n_values_and_derivatives = 3;
617 n_values_and_derivatives = 4;
618 if (update_4th_derivatives)
619 n_values_and_derivatives = 5;
625 std::vector<std::vector<std::vector<double>>> v(dim);
626 for (
unsigned int d = 0;
d < dim; ++
d)
628 v[
d].resize(polynomials[
d].size());
629 for (
unsigned int i = 0; i < polynomials[
d].size(); ++i)
631 v[
d][i].resize(n_values_and_derivatives, 0.);
632 polynomials[
d][i].value(p(
d), v[
d][i]);
636 for (
unsigned int i = 0; i < this->n(); ++i)
642 std::array<unsigned int, dim> indices;
648 for (
unsigned int x = 0; x < dim; ++x)
649 values[i] *= v[x][indices[x]][0];
653 for (
unsigned int d = 0;
d < dim; ++
d)
656 for (
unsigned int x = 0; x < dim; ++x)
657 grads[i][
d] *= v[x][indices[x]][
d == x ? 1 : 0];
660 if (update_grad_grads)
661 for (
unsigned int d1 = 0; d1 < dim; ++d1)
662 for (
unsigned int d2 = 0; d2 < dim; ++d2)
664 grad_grads[i][d1][d2] = 1.;
665 for (
unsigned int x = 0; x < dim; ++x)
667 unsigned int derivative = 0;
673 grad_grads[i][d1][d2] *= v[x][indices[x]][derivative];
678 for (
unsigned int d1 = 0; d1 < dim; ++d1)
679 for (
unsigned int d2 = 0; d2 < dim; ++d2)
680 for (
unsigned int d3 = 0; d3 < dim; ++d3)
682 third_derivatives[i][d1][d2][d3] = 1.;
683 for (
unsigned int x = 0; x < dim; ++x)
685 unsigned int derivative = 0;
693 third_derivatives[i][d1][d2][d3] *=
694 v[x][indices[x]][derivative];
698 if (update_4th_derivatives)
699 for (
unsigned int d1 = 0; d1 < dim; ++d1)
700 for (
unsigned int d2 = 0; d2 < dim; ++d2)
701 for (
unsigned int d3 = 0; d3 < dim; ++d3)
702 for (
unsigned int d4 = 0; d4 < dim; ++d4)
704 fourth_derivatives[i][d1][d2][d3][d4] = 1.;
705 for (
unsigned int x = 0; x < dim; ++x)
707 unsigned int derivative = 0;
717 fourth_derivatives[i][d1][d2][d3][d4] *=
718 v[x][indices[x]][derivative];
731 for (
unsigned int d = 0;
d < dim; ++
d)
738 std::unique_ptr<ScalarPolynomialsBase<dim>>
741 return std_cxx14::make_unique<AnisotropicPolynomials<dim>>(*this);