17#ifndef dealii_simplex_barycentric_polynomials_h
18#define dealii_simplex_barycentric_polynomials_h
82template <
int dim,
typename Number =
double>
95 const Number coefficient);
110 print(std::ostream &out)
const;
127 template <
typename Number2>
134 template <
typename Number2>
141 template <
typename Number2>
148 template <
typename Number2>
180 derivative(
const unsigned int coordinate)
const;
273 std::vector<double> & values,
335 name()
const override;
340 virtual std::unique_ptr<ScalarPolynomialsBase<dim>>
341 clone()
const override;
356template <
int dim,
typename Number1,
typename Number2>
360 return bp * Number1(a);
366template <
int dim,
typename Number1,
typename Number2>
370 return bp + Number1(a);
376template <
int dim,
typename Number1,
typename Number2>
380 return bp - Number1(a);
386template <
int dim,
typename Number>
397template <
int dim,
typename Number>
401 for (
unsigned int d = 0; d < dim + 1; ++d)
403 coefficients.reinit(extents);
410template <
int dim,
typename Number>
413 const Number coefficient)
416 for (
unsigned int d = 0; d < dim + 1; ++d)
417 extents[d] = powers[d] + 1;
418 coefficients.reinit(extents);
420 coefficients(powers) = coefficient;
425template <
int dim,
typename Number>
437template <
int dim,
typename Number>
441 const auto &coeffs = this->coefficients;
442 auto first = index_to_indices(0, coeffs.size());
443 bool print_plus =
false;
444 if (coeffs(
first) != Number())
446 out << coeffs(
first);
449 for (std::size_t i = 1; i < coeffs.n_elements(); ++i)
451 const auto indices = index_to_indices(i, coeffs.size());
452 if (coeffs(indices) == Number())
456 out << coeffs(indices);
457 for (
unsigned int d = 0; d < dim + 1; ++d)
460 out <<
" * t" << d <<
'^' << indices[d];
471template <
int dim,
typename Number>
475 auto deg = coefficients.size();
476 for (
unsigned int d = 0; d < dim + 1; ++d)
483template <
int dim,
typename Number>
487 return *
this * Number(-1);
492template <
int dim,
typename Number>
493template <
typename Number2>
505template <
int dim,
typename Number>
506template <
typename Number2>
515template <
int dim,
typename Number>
516template <
typename Number2>
526 for (std::size_t i = 0; i < result.
coefficients.n_elements(); ++i)
528 const auto index = index_to_indices(i, result.
coefficients.size());
537template <
int dim,
typename Number>
538template <
typename Number2>
543 return *
this * (Number(1) / Number(a));
548template <
int dim,
typename Number>
554 for (
unsigned int d = 0; d < dim + 1; ++d)
562 for (std::size_t i = 0; i < in.n_elements(); ++i)
564 const auto index = index_to_indices(i, in.size());
569 add_coefficients(this->coefficients);
576template <
int dim,
typename Number>
581 return *
this + (-augend);
586template <
int dim,
typename Number>
592 for (
unsigned int d = 0; d < dim + 1; ++d)
594 deg[d] = multiplicand.
degrees()[d] + degrees()[d];
599 const auto &coef_1 = this->coefficients;
603 for (std::size_t i1 = 0; i1 < coef_1.n_elements(); ++i1)
605 const auto index_1 = index_to_indices(i1, coef_1.size());
606 for (std::size_t i2 = 0; i2 < coef_2.n_elements(); ++i2)
608 const auto index_2 = index_to_indices(i2, coef_2.size());
611 for (
unsigned int d = 0; d < dim + 1; ++d)
612 index_out[d] = index_1[d] + index_2[d];
613 coef_out(index_out) += coef_1(index_1) * coef_2(index_2);
622template <
int dim,
typename Number>
625 const unsigned int coordinate)
const
629 if (degrees()[coordinate] == 0)
632 auto deg = degrees();
633 deg[coordinate] -= 1;
635 std::numeric_limits<Number>::max());
636 const auto & coeffs_in = coefficients;
638 for (std::size_t i = 0; i < coeffs_out.n_elements(); ++i)
640 const auto out_index = index_to_indices(i, coeffs_out.size());
641 auto input_index = out_index;
642 input_index[coordinate] += 1;
644 coeffs_out(out_index) = coeffs_in(input_index) * input_index[coordinate];
652template <
int dim,
typename Number>
655 const unsigned int coordinate)
const
658 return -barycentric_derivative(0) + barycentric_derivative(coordinate + 1);
663template <
int dim,
typename Number>
673 std::array<Number, dim + 1> b_point;
675 for (
unsigned int d = 0; d < dim; ++d)
677 b_point[0] -= point[d];
678 b_point[d + 1] = point[d];
682 for (std::size_t i = 0; i < coefficients.n_elements(); ++i)
684 const auto indices = index_to_indices(i, coefficients.size());
685 const auto coef = coefficients(indices);
686 if (coef == Number())
689 auto temp = Number(1);
690 for (
unsigned int d = 0; d < dim + 1; ++d)
691 temp *=
std::pow(b_point[d], indices[d]);
692 result += coef * temp;
698template <
int dim,
typename Number>
702 return coefficients.memory_consumption();
705template <
int dim,
typename Number>
708 const std::size_t & index,
714 for (
unsigned int n = 0; n < dim + 1; ++n)
716 std::size_t slice_size = 1;
717 for (
unsigned int n2 = n + 1; n2 < dim + 1; ++n2)
718 slice_size *= extent[n2];
719 result[n] = temp / slice_size;
BarycentricPolynomial< dim, Number > operator*(const Number2 &a) const
std::size_t memory_consumption() const
BarycentricPolynomial< dim, Number > operator+(const Number2 &a) const
TableIndices< dim+1 > degrees() const
Table< dim+1, Number > coefficients
BarycentricPolynomial< dim, Number > barycentric_derivative(const unsigned int coordinate) const
Number value(const Point< dim > &point) const
BarycentricPolynomial< dim, Number > operator/(const Number2 &a) const
static TableIndices< dim+1 > index_to_indices(const std::size_t &index, const TableIndices< dim+1 > &extent)
BarycentricPolynomial< dim, Number > operator-() const
void print(std::ostream &out) const
static BarycentricPolynomial< dim, Number > monomial(const unsigned int d)
BarycentricPolynomial< dim, Number > derivative(const unsigned int coordinate) const
std::array< HessianType, dim > ThirdDerivativesType
Tensor< 1, dim > compute_grad(const unsigned int i, const Point< dim > &p) const override
std::array< PolyType, dim > GradType
virtual std::size_t memory_consumption() const override
Tensor< 2, dim > compute_grad_grad(const unsigned int i, const Point< dim > &p) const override
std::array< ThirdDerivativesType, dim > FourthDerivativesType
std::vector< GradType > poly_grads
std::string name() const override
Tensor< 3, dim > compute_3rd_derivative(const unsigned int i, const Point< dim > &p) const override
Tensor< 1, dim > compute_1st_derivative(const unsigned int i, const Point< dim > &p) const override
Tensor< 2, dim > compute_2nd_derivative(const unsigned int i, const Point< dim > &p) const override
static constexpr unsigned int dimension
std::vector< PolyType > polys
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
const BarycentricPolynomial< dim > & operator[](const std::size_t i) const
std::vector< ThirdDerivativesType > poly_third_derivatives
std::array< GradType, dim > HessianType
virtual std::unique_ptr< ScalarPolynomialsBase< dim > > clone() const override
Tensor< 4, dim > compute_4th_derivative(const unsigned int i, const Point< dim > &p) const override
std::vector< HessianType > poly_hessians
static BarycentricPolynomials< dim > get_fe_p_basis(const unsigned int degree)
std::vector< FourthDerivativesType > poly_fourth_derivatives
virtual unsigned int degree() const
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcDivideByZero()
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)
BarycentricPolynomial< dim, Number1 > operator-(const Number2 &a, const BarycentricPolynomial< dim, Number1 > &bp)
BarycentricPolynomial< dim, Number1 > operator+(const Number2 &a, const BarycentricPolynomial< dim, Number1 > &bp)
std::ostream & operator<<(std::ostream &out, const BarycentricPolynomial< dim, Number > &bp)
BarycentricPolynomial< dim, Number1 > operator*(const Number2 &a, const BarycentricPolynomial< dim, Number1 > &bp)