13#ifndef dealii_polynomial_h
14#define dealii_polynomial_h
29#include <shared_mutex>
69 template <
typename number>
109 const unsigned int j);
139 value(
const number x, std::vector<number> &values)
const;
159 template <
typename Number2>
162 const unsigned int n_derivatives,
163 Number2 *values)
const;
177 template <std::
size_t n_entries,
typename Number2>
183 const unsigned int n_derivatives,
184 std::array<Number2, n_entries> *values)
const;
202 scale(
const number factor);
219 template <
typename number2>
221 shift(
const number2 offset);
270 print(std::ostream &out)
const;
277 template <
class Archive>
297 template <
typename number2>
349 template <
typename number>
357 Monomial(
const unsigned int n,
const double coefficient = 1.);
365 static std::vector<Polynomial<number>>
376 static std::vector<Point<1>>
414 static std::vector<Polynomial<double>>
424 const unsigned int support_point,
425 std::vector<double> &a);
436 std::vector<Polynomial<double>>
468 static std::vector<Polynomial<double>>
498 Lobatto(
const unsigned int p = 0);
504 static std::vector<Polynomial<double>>
573 static std::vector<Polynomial<double>>
587 static const std::vector<double> &
598 static std::vector<std::unique_ptr<const std::vector<double>>>
651 static std::vector<Polynomial<double>>
766 const unsigned int index);
772 static std::vector<Polynomial<double>>
789 template <
typename Number>
795 const bool rescale_to_dealii_unit_interval =
true);
809 template <
typename Number>
815 const bool rescale_to_dealii_unit_interval);
829 template <
typename Number>
832 const unsigned int degree,
836 const bool rescale_to_dealii_unit_interval);
856 template <
typename Number>
875 template <
typename Number>
890 template <
typename Number>
893 const unsigned int order_s,
894 const unsigned int degree,
908 template <
typename number>
910 : in_lagrange_product_form(false)
911 , lagrange_weight(1.)
916 template <
typename number>
920 if (in_lagrange_product_form ==
true)
922 return lagrange_support_points.size();
927 return coefficients.size() - 1;
933 template <
typename number>
937 if (in_lagrange_product_form ==
false)
942 const unsigned int m = coefficients.size();
943 number value = coefficients.back();
944 for (
int k = m - 2; k >= 0; --k)
945 value = value * x + coefficients[k];
951 const unsigned int m = lagrange_support_points.size();
953 for (
unsigned int j = 0; j < m; ++j)
954 value *= x - lagrange_support_points[j];
955 value *= lagrange_weight;
962 template <
typename number>
963 template <
typename Number2>
966 const unsigned int n_derivatives,
967 Number2 *values)
const
969 values_of_array(std::array<Number2, 1ul>{{x}},
971 reinterpret_cast<std::array<Number2, 1ul> *
>(values));
976 template <
typename number>
977 template <std::
size_t n_entries,
typename Number2>
984 const std::array<Number2, n_entries> &x,
985 const unsigned int n_derivatives,
986 std::array<Number2, n_entries> *values)
const
989 if (in_lagrange_product_form ==
true)
994 const unsigned int n_supp = lagrange_support_points.size();
995 const number weight = lagrange_weight;
996 switch (n_derivatives)
999 for (
unsigned int e = 0; e < n_entries; ++e)
1000 values[0][e] = weight;
1001 for (
unsigned int k = 1; k <= n_derivatives; ++k)
1002 for (
unsigned int e = 0; e < n_entries; ++e)
1004 for (
unsigned int i = 0; i < n_supp; ++i)
1006 std::array<Number2, n_entries> v = x;
1007 for (
unsigned int e = 0; e < n_entries; ++e)
1008 v[e] -= lagrange_support_points[i];
1016 for (
unsigned int k = n_derivatives; k > 0; --k)
1017 for (
unsigned int e = 0; e < n_entries; ++e)
1018 values[k][e] = (values[k][e] * v[e] + values[k - 1][e]);
1019 for (
unsigned int e = 0; e < n_entries; ++e)
1020 values[0][e] *= v[e];
1025 number k_factorial = 2;
1026 for (
unsigned int k = 2; k <= n_derivatives; ++k)
1028 for (
unsigned int e = 0; e < n_entries; ++e)
1029 values[k][e] *= k_factorial;
1030 k_factorial *=
static_cast<number
>(k + 1);
1042 std::array<Number2, n_entries> value;
1043 for (
unsigned int e = 0; e < n_entries; ++e)
1045 for (
unsigned int i = 0; i < n_supp; ++i)
1046 for (
unsigned int e = 0; e < n_entries; ++e)
1047 value[e] *= (x[e] - lagrange_support_points[i]);
1049 for (
unsigned int e = 0; e < n_entries; ++e)
1050 values[0][e] = value[e];
1056 std::array<Number2, n_entries> value, derivative = {};
1057 for (
unsigned int e = 0; e < n_entries; ++e)
1059 for (
unsigned int i = 0; i < n_supp; ++i)
1060 for (
unsigned int e = 0; e < n_entries; ++e)
1062 const Number2 v = x[e] - lagrange_support_points[i];
1063 derivative[e] = derivative[e] * v + value[e];
1067 for (
unsigned int e = 0; e < n_entries; ++e)
1069 values[0][e] = value[e];
1070 values[1][e] = derivative[e];
1077 std::array<Number2, n_entries> value, derivative = {},
1079 for (
unsigned int e = 0; e < n_entries; ++e)
1081 for (
unsigned int i = 0; i < n_supp; ++i)
1082 for (
unsigned int e = 0; e < n_entries; ++e)
1084 const Number2 v = x[e] - lagrange_support_points[i];
1086 derivative[e] = derivative[e] * v + value[e];
1090 for (
unsigned int e = 0; e < n_entries; ++e)
1092 values[0][e] = value[e];
1093 values[1][e] = derivative[e];
1094 values[2][e] =
static_cast<number
>(2) *
second[e];
1106 const unsigned int m = coefficients.size();
1107 std::vector<std::array<Number2, n_entries>> a(coefficients.size());
1108 for (
unsigned int i = 0; i < coefficients.size(); ++i)
1109 for (
unsigned int e = 0; e < n_entries; ++e)
1110 a[i][e] = coefficients[i];
1112 unsigned int j_factorial = 1;
1117 const unsigned int min_valuessize_m =
std::min(n_derivatives + 1, m);
1118 for (
unsigned int j = 0; j < min_valuessize_m; ++j)
1120 for (
int k = m - 2; k >=
static_cast<int>(j); --k)
1121 for (
unsigned int e = 0; e < n_entries; ++e)
1122 a[k][e] += x[e] * a[k + 1][e];
1123 for (
unsigned int e = 0; e < n_entries; ++e)
1124 values[j][e] =
static_cast<number
>(j_factorial) * a[j][e];
1126 j_factorial *= j + 1;
1130 for (
unsigned int j = min_valuessize_m; j <= n_derivatives; ++j)
1131 for (
unsigned int e = 0; e < n_entries; ++e)
1137 template <
typename number>
1138 template <
class Archive>
1145 ar &in_lagrange_product_form;
1146 ar &lagrange_support_points;
1147 ar &lagrange_weight;
1152 template <
typename Number>
1158 const bool rescale_to_dealii_unit_interval)
1160 Assert(alpha >= 0 && beta >= 0,
1167 const Number xeval =
1168 rescale_to_dealii_unit_interval ? Number(-1) + 2. * x : x;
1174 p1 = ((alpha + beta + 2) * xeval + (alpha - beta)) / 2;
1178 for (
unsigned int i = 1; i < degree; ++i)
1180 const Number v = 2 * i + (alpha + beta);
1181 const Number a1 = 2 * (i + 1) * (i + (alpha + beta + 1)) * v;
1182 const Number a2 = (v + 1) * (alpha * alpha - beta * beta);
1183 const Number a3 = v * (v + 1) * (v + 2);
1184 const Number a4 = 2 * (i + alpha) * (i + beta) * (v + 2);
1186 const Number pn = ((a2 + a3 * xeval) * p1 - a4 * p0) / a1;
1195 template <
typename Number>
1201 const bool rescale_to_dealii_unit_interval)
1204 1, degree, alpha, beta, x, rescale_to_dealii_unit_interval);
1209 template <
typename Number>
1212 const unsigned int degree,
1216 const bool rescale_to_dealii_unit_interval)
1218 Assert(alpha >= 0 && beta >= 0,
1221 if (derivative_order > degree)
1226 if (degree == 0 && derivative_order != 0)
1231 Number pre_factor = 1.0;
1232 for (
unsigned int i = 1; i < derivative_order + 1; ++i)
1233 pre_factor *= (alpha + beta + degree + i);
1235 if (rescale_to_dealii_unit_interval)
1237 alpha + derivative_order,
1238 beta + derivative_order,
1242 return std::pow(0.5, derivative_order) * pre_factor *
1244 alpha + derivative_order,
1245 beta + derivative_order,
1252 template <
typename Number>
1258 std::vector<Number> x(degree, 0.5);
1269 const Number tolerance =
1270 4 *
std::max(
static_cast<Number
>(std::numeric_limits<double>::epsilon()),
1271 std::numeric_limits<Number>::epsilon());
1279 const unsigned int n_points = (alpha == beta ? degree / 2 : degree);
1280 for (
unsigned int k = 0; k < n_points; ++k)
1284 Number r = 0.5 - 0.5 *
std::cos(
static_cast<Number
>(2 * k + 1) /
1287 r = (r + x[k - 1]) / 2;
1290 for (
unsigned int it = 1; it < 1000; ++it)
1293 for (
unsigned int i = 0; i < k; ++i)
1294 s += 1. / (r - x[i]);
1298 (alpha + beta + degree + 1) *
1303 const Number delta = f / (f * s - J_x);
1311 if (it == converged + 1)
1316 ExcMessage(
"Newton iteration for zero of Jacobi polynomial "
1317 "did not converge."));
1323 for (
unsigned int k = n_points; k < degree; ++k)
1324 x[k] = 1.0 - x[degree - k - 1];
1331 template <
typename Number>
1339 Assert(alpha >= 0 && beta >= 0,
1351 p1 = ((alpha + beta + 2.0) * (2.0 * x - s) + s * (alpha - beta)) / 2.0;
1355 for (
unsigned int i = 1; i < degree; ++i)
1357 const Number v = 2 * i + (alpha + beta);
1358 const Number a1 = 2 * (i + 1) * (i + (alpha + beta + 1)) * v;
1359 const Number a2 = (v + 1) * (alpha * alpha - beta * beta);
1360 const Number a3 = v * (v + 1) * (v + 2);
1361 const Number a4 = 2 * (i + alpha) * (i + beta) * (v + 2);
1364 ((a2 * s + a3 * (2.0 * x - s)) * p1 - a4 * s * s * p0) / a1;
1373 template <
typename Number>
1376 const unsigned int order_s,
1377 const unsigned int degree,
1383 Assert(alpha >= 0 && beta >= 0,
1386 if (order_x + order_s > degree)
1388 if (degree == 0 && (order_x + order_s != 0))
1393 Number pre_factor = 1.0;
1394 for (
unsigned int i = 1; i < order_x + 1; ++i)
1395 pre_factor *= (alpha + beta + degree + i);
1397 for (
unsigned int i = 0; i < order_s; ++i)
1398 pre_factor *= (degree + beta - i);
1400 const Number derivative =
1401 std::pow(-1.0, order_s) * pre_factor *
1402 jacobi_polynomial_homogenized_value<Number>(degree - order_x - order_s,
1403 alpha + order_x + order_s,
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int p)
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int degree)
static std::vector< std::unique_ptr< const std::vector< double > > > recursive_coefficients
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)
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int degree)
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int degree)
std::vector< double > compute_coefficients(const unsigned int p)
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int p)
static std::vector< Polynomial< number > > generate_complete_basis(const unsigned int degree)
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)
void values_of_array(const std::array< Number2, n_entries > &points, const unsigned int n_derivatives, std::array< Number2, n_entries > *values) const
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
void serialize(Archive &ar, const unsigned int version)
static void multiply(std::vector< number > &coefficients, const number factor)
void value(const Number2 x, const unsigned int n_derivatives, Number2 *values) const
Polynomial< number > & operator*=(const double s)
virtual std::size_t memory_consumption() const
unsigned int degree() const
#define DEAL_II_ALWAYS_INLINE
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcEmptyObject()
#define Assert(cond, exc)
static ::ExceptionBase & ExcMessage(std::string arg1)
Number jacobi_polynomial_kth_derivative(const unsigned int derivative_order, const unsigned int degree, const int alpha, const int beta, const Number x, const bool rescale_to_dealii_unit_interval)
Number jacobi_polynomial_homogenized_derivative(const unsigned int order_x, const unsigned int order_s, const unsigned int degree, const int alpha, const int beta, const Number x, const Number s)
Number jacobi_polynomial_derivative(const unsigned int degree, const int alpha, const int beta, const Number x, const bool rescale_to_dealii_unit_interval)
std::vector< Polynomial< double > > generate_complete_Lagrange_basis(const std::vector< Point< 1 > > &points)
Number jacobi_polynomial_homogenized_value(const unsigned int degree, const int alpha, const int beta, const Number x, const Number s)
std::vector< Number > jacobi_polynomial_roots(const unsigned int degree, const int alpha, const int beta)
Number jacobi_polynomial_value(const unsigned int degree, const int alpha, const int beta, const Number x, const bool rescale_to_dealii_unit_interval=true)
constexpr unsigned int invalid_unsigned_int
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > cos(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)