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)
155 value *= polynomials[indices[
d]].
value(p(
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)
485 internal::compute_tensor_index(i,
490 internal::compute_tensor_index(i,
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)
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)
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)
629 for (
unsigned int i = 0; i <
polynomials[
d].size(); ++i)
631 v[
d][i].resize(n_values_and_derivatives, 0.);
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);
757 Polynomials::PiecewisePolynomial<double>>;
760 Polynomials::PiecewisePolynomial<double>>;
Tensor< 1, dim > compute_grad(const unsigned int i, const Point< dim > &p) const
Tensor< 1, dim > compute_grad(const unsigned int i, const Point< dim > &p) const
static ::ExceptionBase & ExcDimensionMismatch2(int arg1, int arg2, int arg3)
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 set_numbering(const std::vector< unsigned int > &renumber)
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)
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
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
virtual std::unique_ptr< ScalarPolynomialsBase< dim > > clone() const override
virtual std::size_t memory_consumption() const override
#define DEAL_II_NAMESPACE_CLOSE
const std::vector< std::vector< Polynomials::Polynomial< double > > > polynomials
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
void compute_index(const unsigned int i, std::array< unsigned int, dim > &indices) const
unsigned int compute_index()
#define DEAL_II_NAMESPACE_OPEN
double compute_value(const unsigned int i, const Point< dim > &p) const
static ::ExceptionBase & ExcNotImplemented()
AnisotropicPolynomials(const std::vector< std::vector< Polynomials::Polynomial< double >>> &base_polynomials)
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
double compute_value(const unsigned int i, const Point< dim > &p) const
virtual std::unique_ptr< ScalarPolynomialsBase< dim > > clone() const override
Tensor< 2, dim > compute_grad_grad(const unsigned int i, const Point< dim > &p) const
std::enable_if< std::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
static ::ExceptionBase & ExcInternalError()