24#include <shared_mutex>
35 template <
typename number>
38 , in_lagrange_product_form(false)
44 template <
typename number>
46 : coefficients(n + 1, 0.)
47 , in_lagrange_product_form(false)
53 template <
typename number>
55 const unsigned int center)
56 : in_lagrange_product_form(true)
62 number tmp_lagrange_weight = 1.;
63 for (
unsigned int i = 0; i < supp.size(); ++i)
67 tmp_lagrange_weight *= supp[center][0] - supp[i][0];
71 Assert(std::fabs(tmp_lagrange_weight) > std::numeric_limits<number>::min(),
72 ExcMessage(
"Underflow in computation of Lagrange denominator."));
73 Assert(std::fabs(tmp_lagrange_weight) < std::numeric_limits<number>::max(),
74 ExcMessage(
"Overflow in computation of Lagrange denominator."));
81 template <
typename number>
87 value(x, values.size() - 1, values.data());
92 template <
typename number>
101 coefficients.resize(lagrange_support_points.size() + 1);
102 if (lagrange_support_points.empty())
103 coefficients[0] = 1.;
106 coefficients[0] = -lagrange_support_points[0];
107 coefficients[1] = 1.;
108 for (
unsigned int i = 1; i < lagrange_support_points.size(); ++i)
110 coefficients[i + 1] = 1.;
111 for (
unsigned int j = i; j > 0; --j)
112 coefficients[j] = (-lagrange_support_points[i] * coefficients[j] +
113 coefficients[j - 1]);
114 coefficients[0] *= -lagrange_support_points[i];
117 for (
unsigned int i = 0; i < lagrange_support_points.size() + 1; ++i)
118 coefficients[i] *= lagrange_weight;
121 std::vector<number> new_points;
122 lagrange_support_points.swap(new_points);
123 in_lagrange_product_form =
false;
124 lagrange_weight = 1.;
129 template <
typename number>
135 for (
typename std::vector<number>::iterator c = coefficients.begin();
136 c != coefficients.end();
146 template <
typename number>
153 if (in_lagrange_product_form ==
true)
155 number inv_fact = number(1.) / factor;
156 number accumulated_fact = 1.;
157 for (
unsigned int i = 0; i < lagrange_support_points.size(); ++i)
159 lagrange_support_points[i] *= inv_fact;
160 accumulated_fact *= factor;
162 lagrange_weight *= accumulated_fact;
166 scale(coefficients, factor);
171 template <
typename number>
176 for (
typename std::vector<number>::iterator c = coefficients.begin();
177 c != coefficients.end();
184 template <
typename number>
188 if (in_lagrange_product_form ==
true)
189 lagrange_weight *= s;
192 for (
typename std::vector<number>::iterator c = coefficients.begin();
193 c != coefficients.end();
202 template <
typename number>
211 lagrange_support_points.insert(lagrange_support_points.end(),
217 else if (in_lagrange_product_form ==
true)
218 transform_into_standard_form();
223 std::unique_ptr<Polynomial<number>> q_data;
227 q_data = std::make_unique<Polynomial<number>>(p);
235 unsigned int new_degree = this->degree() + q->
degree();
237 std::vector<number> new_coefficients(new_degree + 1, 0.);
239 for (
unsigned int i = 0; i < q->
coefficients.size(); ++i)
240 for (
unsigned int j = 0; j < this->coefficients.size(); ++j)
241 new_coefficients[i + j] += this->coefficients[j] * q->
coefficients[i];
242 this->coefficients = std::move(new_coefficients);
249 template <
typename number>
261 if (in_lagrange_product_form ==
true)
262 transform_into_standard_form();
267 std::unique_ptr<Polynomial<number>> q_data;
271 q_data = std::make_unique<Polynomial<number>>(p);
283 for (
unsigned int i = 0; i < q->
coefficients.size(); ++i)
291 template <
typename number>
297 if (in_lagrange_product_form ==
true)
298 transform_into_standard_form();
303 std::unique_ptr<Polynomial<number>> q_data;
307 q_data = std::make_unique<Polynomial<number>>(p);
319 for (
unsigned int i = 0; i < q->
coefficients.size(); ++i)
327 template <
typename number>
339 else if (in_lagrange_product_form ==
true)
357 template <
typename number>
358 template <
typename number2>
361 const number2 offset)
369 std::vector<number2> new_coefficients(coefficients.begin(),
375 for (
unsigned int d = 1; d < new_coefficients.size(); ++d)
377 const unsigned int n = d;
382 unsigned int binomial_coefficient = 1;
387 number2 offset_power = offset;
394 for (
unsigned int k = 0; k < d; ++k)
400 binomial_coefficient = (binomial_coefficient * (n - k)) / (k + 1);
402 new_coefficients[d - k - 1] +=
403 new_coefficients[d] * binomial_coefficient * offset_power;
404 offset_power *= offset;
414 coefficients.assign(new_coefficients.begin(), new_coefficients.end());
419 template <
typename number>
420 template <
typename number2>
427 if (in_lagrange_product_form ==
true)
429 for (
unsigned int i = 0; i < lagrange_support_points.size(); ++i)
430 lagrange_support_points[i] -= offset;
434 shift(coefficients, offset);
439 template <
typename number>
448 std::unique_ptr<Polynomial<number>> q_data;
450 if (in_lagrange_product_form ==
true)
452 q_data = std::make_unique<Polynomial<number>>(*this);
459 std::vector<number> newcoefficients(q->
coefficients.size() - 1);
460 for (
unsigned int i = 1; i < q->
coefficients.size(); ++i)
461 newcoefficients[i - 1] = number(i) * q->
coefficients[i];
468 template <
typename number>
474 std::unique_ptr<Polynomial<number>> q_data;
476 if (in_lagrange_product_form ==
true)
478 q_data = std::make_unique<Polynomial<number>>(*this);
485 std::vector<number> newcoefficients(q->
coefficients.size() + 1);
486 newcoefficients[0] = 0.;
487 for (
unsigned int i = 0; i < q->
coefficients.size(); ++i)
488 newcoefficients[i + 1] = q->
coefficients[i] / number(i + 1.);
495 template <
typename number>
499 if (in_lagrange_product_form ==
true)
501 out << lagrange_weight;
502 for (
unsigned int i = 0; i < lagrange_support_points.size(); ++i)
503 out <<
" (x-" << lagrange_support_points[i] <<
")";
507 for (
int i = degree(); i >= 0; --i)
509 out << coefficients[i] <<
" x^" << i << std::endl;
514 template <
typename number>
528 template <
typename number>
529 std::vector<Point<1>>
538 std::vector<Point<1>> vector(n + 1);
545 template <
typename number>
547 :
Polynomial<number>(create_vector_of_roots(n), 0)
554 template <
typename number>
555 std::vector<Polynomial<number>>
558 std::vector<Polynomial<number>> v;
559 v.reserve(degree + 1);
560 for (
unsigned int i = 0; i <= degree; ++i)
571 namespace LagrangeEquidistantImplementation
573 std::vector<Point<1>>
576 std::vector<Point<1>> points(n + 1);
577 const double one_over_n = 1. / n;
578 for (
unsigned int k = 0; k <= n; ++k)
579 points[k][0] =
static_cast<double>(k) * one_over_n;
588 const unsigned int support_point)
590 generate_equidistant_unit_points(n),
601 std::vector<double> new_support_points;
612 const unsigned int support_point,
613 std::vector<double> &a)
617 unsigned int n_functions = n + 1;
619 const double *x =
nullptr;
625 static const double x1[4] = {1.0, -1.0, 0.0, 1.0};
631 static const double x2[9] = {
632 1.0, -3.0, 2.0, 0.0, 4.0, -4.0, 0.0, -1.0, 2.0};
638 static const double x3[16] = {1.0,
662 for (
unsigned int i = 0; i < n_functions; ++i)
663 a[i] = x[support_point * n_functions + i];
668 std::vector<Polynomial<double>>
673 return std::vector<Polynomial<double>>(
679 std::vector<Polynomial<double>> v;
680 for (
unsigned int i = 0; i <=
degree; ++i)
691 std::vector<Polynomial<double>>
694 std::vector<Polynomial<double>> p;
695 p.reserve(points.size());
697 for (
unsigned int i = 0; i < points.size(); ++i)
698 p.emplace_back(points, i);
720 for (
unsigned int i = 0; i < k; ++i)
727 for (
unsigned int i = 0; i < k; ++i)
734 std::vector<Polynomial<double>>
737 std::vector<Polynomial<double>> v;
739 for (
unsigned int i = 0; i <=
degree; ++i)
789 std::vector<double> legendre_coefficients_tmp1(p);
790 std::vector<double> legendre_coefficients_tmp2(p - 1);
794 legendre_coefficients_tmp1[0] = 1.0;
796 for (
unsigned int i = 2; i < p; ++i)
798 for (
unsigned int j = 0; j < i - 1; ++j)
799 legendre_coefficients_tmp2[j] = legendre_coefficients_tmp1[j];
801 for (
unsigned int j = 0; j < i; ++j)
806 ((1.0 - 2 * i) * legendre_coefficients_tmp1[0] /
808 (1.0 - i) * legendre_coefficients_tmp2[0] /
812 for (
unsigned int j = 1; j < i - 1; ++j)
816 (2.0 * legendre_coefficients_tmp1[j - 1] -
817 legendre_coefficients_tmp1[j]) +
818 (1.0 - i) * legendre_coefficients_tmp2[j] /
823 (2.0 * legendre_coefficients_tmp1[i - 2] -
824 legendre_coefficients_tmp1[i - 1]) /
827 legendre_coefficients_tmp1[i - 1] / i;
830 for (
int i = p; i > 0; --i)
839 std::vector<Polynomial<double>>
842 std::vector<Polynomial<double>> basis(p + 1);
844 for (
unsigned int i = 0; i <= p; ++i)
856 std::vector<std::unique_ptr<const std::vector<double>>>
930 std::vector<double> c0(2);
934 std::vector<double> c1(2);
941 std::make_unique<const std::vector<double>>(std::move(c0));
943 std::make_unique<const std::vector<double>>(std::move(c1));
951 std::vector<double> c2(3);
960 std::make_unique<const std::vector<double>>(std::move(c2));
976 std::vector<double> ck(k + 1);
982 for (
unsigned int i = 1; i <= k - 1; ++i)
1004 std::make_unique<const std::vector<double>>(std::move(ck));
1010 const std::vector<double> &
1025 std::vector<Polynomial<double>>
1038 return std::vector<Polynomial<double>>(
1042 std::vector<Polynomial<double>> v;
1044 for (
unsigned int i = 0; i <=
degree; ++i)
1099 (*this) *= legendre;
1105 std::vector<Polynomial<double>>
1110 "degrees less than three"));
1111 std::vector<Polynomial<double>> basis(n + 1);
1113 for (
unsigned int i = 0; i <= n; ++i)
1129 find_support_point_x_star(
const std::vector<double> &jacobi_roots)
1135 double guess_left = 0;
1136 double guess_right = 0.5;
1137 const unsigned int degree = jacobi_roots.size() + 3;
1149 double integral_left = 0, integral_right = 0;
1150 for (
unsigned int q = 0; q < gauss.size(); ++q)
1152 const double x = gauss.point(q)[0];
1153 double poly_val_common = x;
1154 for (
unsigned int j = 0; j < degree - 3; ++j)
1155 poly_val_common *= Utilities::fixed_power<2>(x - jacobi_roots[j]);
1156 poly_val_common *= Utilities::fixed_power<4>(x - 1.);
1158 gauss.weight(q) * (poly_val_common * (x - guess_left));
1160 gauss.weight(q) * (poly_val_common * (x - guess_right));
1165 return guess_right - (guess_right - guess_left) /
1166 (integral_right - integral_left) * integral_right;
1173 const unsigned int index)
1185 else if (degree == 1)
1198 else if (degree == 2)
1206 else if (index == 1)
1219 else if (degree == 3)
1236 else if (index == 1)
1246 else if (index == 2)
1253 else if (index == 3)
1284 std::vector<double> jacobi_roots =
1285 jacobi_polynomial_roots<double>(
degree - 3, 4, 4);
1294 const double auxiliary_zero =
1295 find_support_point_x_star(jacobi_roots);
1297 for (
unsigned int m = 0; m <
degree - 3; ++m)
1305 else if (index == 1)
1308 for (
unsigned int m = 0; m <
degree - 3; ++m)
1321 std::vector<Point<1>> points(
degree);
1323 for (
unsigned int i = 0; i <
degree; ++i)
1330 std::vector<double> value_and_grad(2);
1331 helper.
value(0., value_and_grad);
1335 const double auxiliary_zero =
1336 find_support_point_x_star(jacobi_roots);
1338 (1. / auxiliary_zero - value_and_grad[1] / value_and_grad[0]) /
1341 else if (index >= 2 && index <
degree - 1)
1345 for (
unsigned int m = 0, c = 2; m <
degree - 3; ++m)
1355 else if (index ==
degree - 1)
1359 for (
unsigned int m = 0; m <
degree - 3; ++m)
1363 std::vector<Point<1>> points(
degree);
1365 for (
unsigned int i = 0; i <
degree; ++i)
1372 std::vector<double> value_and_grad(2);
1373 helper.
value(1., value_and_grad);
1377 const double auxiliary_zero =
1378 find_support_point_x_star(jacobi_roots);
1380 (-1. / auxiliary_zero - value_and_grad[1] / value_and_grad[0]) /
1383 else if (index ==
degree)
1385 const double auxiliary_zero =
1386 find_support_point_x_star(jacobi_roots);
1389 for (
unsigned int m = 0; m <
degree - 3; ++m)
1401 std::vector<Polynomial<double>>
1404 std::vector<Polynomial<double>> basis(
degree + 1);
1406 for (
unsigned int i = 0; i <=
degree; ++i)
1419 template class Polynomial<float>;
1420 template class Polynomial<double>;
1421 template class Polynomial<long double>;
1436 template class Monomial<float>;
1437 template class Monomial<double>;
1438 template class Monomial<long double>;
HermiteInterpolation(const unsigned int p)
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int p)
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int degree)
HermiteLikeInterpolation(const unsigned int degree, const unsigned int index)
static std::vector< std::unique_ptr< const std::vector< double > > > recursive_coefficients
Hierarchical(const unsigned int p)
static void compute_coefficients(const unsigned int p)
static const std::vector< double > & get_coefficients(const unsigned int p)
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int degree)
static std::shared_mutex coefficients_lock
static void compute_coefficients(const unsigned int n, const unsigned int support_point, std::vector< double > &a)
LagrangeEquidistant(const unsigned int n, const unsigned int support_point)
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int degree)
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int degree)
Legendre(const unsigned int p)
std::vector< double > compute_coefficients(const unsigned int p)
Lobatto(const unsigned int p=0)
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int p)
static std::vector< Polynomial< number > > generate_complete_basis(const unsigned int degree)
Monomial(const unsigned int n, const double coefficient=1.)
static std::vector< Point< 1 > > create_vector_of_roots(unsigned int n)
number value(const number x) const
bool operator==(const Polynomial< number > &p) const
std::vector< number > coefficients
Polynomial< number > primitive() const
Polynomial< number > & operator+=(const Polynomial< number > &p)
Polynomial< number > derivative() const
void transform_into_standard_form()
void scale(const number factor)
Polynomial< number > & operator-=(const Polynomial< number > &p)
std::vector< number > lagrange_support_points
void shift(const number2 offset)
void print(std::ostream &out) const
bool in_lagrange_product_form
static void multiply(std::vector< number > &coefficients, const number factor)
Polynomial< number > & operator*=(const double s)
virtual std::size_t memory_consumption() const
unsigned int degree() const
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_ASSERT_UNREACHABLE()
static ::ExceptionBase & ExcZero()
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcEmptyObject()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
std::vector< Point< 1 > > generate_equidistant_unit_points(const unsigned int n)
std::vector< Polynomial< double > > generate_complete_Lagrange_basis(const std::vector< Point< 1 > > &points)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)