16 #include <deal.II/base/exceptions.h> 17 #include <deal.II/base/point.h> 18 #include <deal.II/base/polynomial.h> 19 #include <deal.II/base/quadrature_lib.h> 20 #include <deal.II/base/std_cxx14/memory.h> 21 #include <deal.II/base/thread_management.h> 27 DEAL_II_NAMESPACE_OPEN
51 template <
typename number>
54 , in_lagrange_product_form(false)
60 template <
typename number>
62 : coefficients(n + 1, 0.)
63 , in_lagrange_product_form(false)
69 template <
typename number>
71 const unsigned int center)
72 : in_lagrange_product_form(true)
77 lagrange_support_points.reserve(supp.size() - 1);
78 number tmp_lagrange_weight = 1.;
79 for (
unsigned int i = 0; i < supp.size(); ++i)
82 lagrange_support_points.push_back(supp[i](0));
83 tmp_lagrange_weight *= supp[center](0) - supp[i](0);
87 Assert(std::fabs(tmp_lagrange_weight) > std::numeric_limits<number>::min(),
88 ExcMessage(
"Underflow in computation of Lagrange denominator."));
89 Assert(std::fabs(tmp_lagrange_weight) < std::numeric_limits<number>::max(),
90 ExcMessage(
"Overflow in computation of Lagrange denominator."));
92 lagrange_weight =
static_cast<number
>(1.) / tmp_lagrange_weight;
97 template <
typename number>
103 value(x, values.size() - 1, values.data());
108 template <
typename number>
111 const unsigned int n_derivatives,
112 number * values)
const 115 if (in_lagrange_product_form ==
true)
120 const unsigned int n_supp = lagrange_support_points.size();
121 switch (n_derivatives)
125 for (
unsigned int d = 1; d <= n_derivatives; ++d)
127 for (
unsigned int i = 0; i < n_supp; ++i)
129 const number v = x - lagrange_support_points[i];
137 for (
unsigned int k = n_derivatives; k > 0; --k)
138 values[k] = (values[k] * v + values[k - 1]);
150 number k_faculty = 1;
151 for (
unsigned int k = 0; k <= n_derivatives; ++k)
153 values[k] *= k_faculty * lagrange_weight;
154 k_faculty *=
static_cast<number
>(k + 1);
164 for (
unsigned int i = 0; i < n_supp; ++i)
166 const number v = x - lagrange_support_points[i];
169 values[0] *= lagrange_weight;
175 for (
unsigned int i = 0; i < n_supp; ++i)
177 const number v = x - lagrange_support_points[i];
178 values[1] = values[1] * v + values[0];
181 values[0] *= lagrange_weight;
182 values[1] *= lagrange_weight;
189 for (
unsigned int i = 0; i < n_supp; ++i)
191 const number v = x - lagrange_support_points[i];
192 values[2] = values[2] * v + values[1];
193 values[1] = values[1] * v + values[0];
196 values[0] *= lagrange_weight;
197 values[1] *= lagrange_weight;
198 values[2] *=
static_cast<number
>(2) * lagrange_weight;
209 if (n_derivatives == 0)
211 values[0] = value(x);
217 const unsigned int m = coefficients.size();
218 std::vector<number> a(coefficients);
219 unsigned int j_faculty = 1;
224 const unsigned int min_valuessize_m = std::min(n_derivatives + 1, m);
225 for (
unsigned int j = 0; j < min_valuessize_m; ++j)
227 for (
int k = m - 2; k >=
static_cast<int>(j); --k)
228 a[k] += x * a[k + 1];
229 values[j] =
static_cast<number
>(j_faculty) * a[j];
235 for (
unsigned int j = min_valuessize_m; j <= n_derivatives; ++j)
241 template <
typename number>
250 coefficients.resize(lagrange_support_points.size() + 1);
251 if (lagrange_support_points.size() == 0)
252 coefficients[0] = 1.;
255 coefficients[0] = -lagrange_support_points[0];
256 coefficients[1] = 1.;
257 for (
unsigned int i = 1; i < lagrange_support_points.size(); ++i)
259 coefficients[i + 1] = 1.;
260 for (
unsigned int j = i; j > 0; --j)
261 coefficients[j] = (-lagrange_support_points[i] * coefficients[j] +
262 coefficients[j - 1]);
263 coefficients[0] *= -lagrange_support_points[i];
266 for (
unsigned int i = 0; i < lagrange_support_points.size() + 1; ++i)
267 coefficients[i] *= lagrange_weight;
270 std::vector<number> new_points;
271 lagrange_support_points.swap(new_points);
272 in_lagrange_product_form =
false;
273 lagrange_weight = 1.;
278 template <
typename number>
284 for (
typename std::vector<number>::iterator c = coefficients.begin();
285 c != coefficients.end();
295 template <
typename number>
302 if (in_lagrange_product_form ==
true)
304 number inv_fact = number(1.) / factor;
305 number accumulated_fact = 1.;
306 for (
unsigned int i = 0; i < lagrange_support_points.size(); ++i)
308 lagrange_support_points[i] *= inv_fact;
309 accumulated_fact *= factor;
311 lagrange_weight *= accumulated_fact;
315 scale(coefficients, factor);
320 template <
typename number>
325 for (
typename std::vector<number>::iterator c = coefficients.begin();
326 c != coefficients.end();
333 template <
typename number>
337 if (in_lagrange_product_form ==
true)
338 lagrange_weight *= s;
341 for (
typename std::vector<number>::iterator c = coefficients.begin();
342 c != coefficients.end();
351 template <
typename number>
360 lagrange_support_points.insert(lagrange_support_points.end(),
366 else if (in_lagrange_product_form ==
true)
367 transform_into_standard_form();
372 std::unique_ptr<Polynomial<number>> q_data;
376 q_data = std_cxx14::make_unique<Polynomial<number>>(p);
377 q_data->transform_into_standard_form();
384 unsigned int new_degree = this->degree() + q->
degree();
386 std::vector<number> new_coefficients(new_degree + 1, 0.);
388 for (
unsigned int i = 0; i < q->
coefficients.size(); ++i)
389 for (
unsigned int j = 0; j < this->coefficients.size(); ++j)
390 new_coefficients[i + j] += this->coefficients[j] * q->
coefficients[i];
391 this->coefficients = new_coefficients;
398 template <
typename number>
410 if (in_lagrange_product_form ==
true)
411 transform_into_standard_form();
416 std::unique_ptr<Polynomial<number>> q_data;
420 q_data = std_cxx14::make_unique<Polynomial<number>>(p);
421 q_data->transform_into_standard_form();
432 for (
unsigned int i = 0; i < q->
coefficients.size(); ++i)
440 template <
typename number>
446 if (in_lagrange_product_form ==
true)
447 transform_into_standard_form();
452 std::unique_ptr<Polynomial<number>> q_data;
456 q_data = std_cxx14::make_unique<Polynomial<number>>(p);
457 q_data->transform_into_standard_form();
468 for (
unsigned int i = 0; i < q->
coefficients.size(); ++i)
476 template <
typename number>
488 else if (in_lagrange_product_form ==
true)
506 template <
typename number>
507 template <
typename number2>
510 const number2 offset)
518 std::vector<number2> new_coefficients(coefficients.begin(),
524 for (
unsigned int d = 1; d < new_coefficients.size(); ++d)
526 const unsigned int n = d;
531 unsigned int binomial_coefficient = 1;
536 number2 offset_power = offset;
543 for (
unsigned int k = 0; k < d; ++k)
549 binomial_coefficient = (binomial_coefficient * (n - k)) / (k + 1);
551 new_coefficients[d - k - 1] +=
552 new_coefficients[d] * binomial_coefficient * offset_power;
553 offset_power *= offset;
563 coefficients.assign(new_coefficients.begin(), new_coefficients.end());
568 template <
typename number>
569 template <
typename number2>
576 if (in_lagrange_product_form ==
true)
578 for (
unsigned int i = 0; i < lagrange_support_points.size(); ++i)
579 lagrange_support_points[i] -= offset;
583 shift(coefficients, offset);
588 template <
typename number>
597 std::unique_ptr<Polynomial<number>> q_data;
599 if (in_lagrange_product_form ==
true)
601 q_data = std_cxx14::make_unique<Polynomial<number>>(*this);
602 q_data->transform_into_standard_form();
608 std::vector<number> newcoefficients(q->
coefficients.size() - 1);
609 for (
unsigned int i = 1; i < q->
coefficients.size(); ++i)
610 newcoefficients[i - 1] = number(i) * q->
coefficients[i];
617 template <
typename number>
623 std::unique_ptr<Polynomial<number>> q_data;
625 if (in_lagrange_product_form ==
true)
627 q_data = std_cxx14::make_unique<Polynomial<number>>(*this);
628 q_data->transform_into_standard_form();
634 std::vector<number> newcoefficients(q->
coefficients.size() + 1);
635 newcoefficients[0] = 0.;
636 for (
unsigned int i = 0; i < q->
coefficients.size(); ++i)
637 newcoefficients[i + 1] = q->
coefficients[i] / number(i + 1.);
644 template <
typename number>
648 if (in_lagrange_product_form ==
true)
650 out << lagrange_weight;
651 for (
unsigned int i = 0; i < lagrange_support_points.size(); ++i)
652 out <<
" (x-" << lagrange_support_points[i] <<
")";
656 for (
int i = degree(); i >= 0; --i)
658 out << coefficients[i] <<
" x^" << i << std::endl;
666 template <
typename number>
670 std::vector<number> result(n + 1, 0.);
671 result[n] = coefficient;
677 template <
typename number>
679 :
Polynomial<number>(make_vector(n, coefficient))
684 template <
typename number>
685 std::vector<Polynomial<number>>
688 std::vector<Polynomial<number>> v;
689 v.reserve(degree + 1);
690 for (
unsigned int i = 0; i <= degree; ++i)
701 namespace LagrangeEquidistantImplementation
703 std::vector<Point<1>>
704 generate_equidistant_unit_points(
const unsigned int n)
706 std::vector<Point<1>> points(n + 1);
707 const double one_over_n = 1. / n;
708 for (
unsigned int k = 0; k <= n; ++k)
709 points[k](0) =
static_cast<double>(k) * one_over_n;
718 const unsigned int support_point)
720 generate_equidistant_unit_points(n),
731 std::vector<double> new_support_points;
742 const unsigned int support_point,
743 std::vector<double> &a)
747 unsigned int n_functions = n + 1;
748 Assert(support_point < n_functions,
750 double const *x =
nullptr;
756 static const double x1[4] = {1.0, -1.0, 0.0, 1.0};
762 static const double x2[9] = {
763 1.0, -3.0, 2.0, 0.0, 4.0, -4.0, 0.0, -1.0, 2.0};
769 static const double x3[16] = {1.0,
793 for (
unsigned int i = 0; i < n_functions; ++i)
794 a[i] = x[support_point * n_functions + i];
799 std::vector<Polynomial<double>>
804 return std::vector<Polynomial<double>>(
810 std::vector<Polynomial<double>> v;
811 for (
unsigned int i = 0; i <=
degree; ++i)
822 std::vector<Polynomial<double>>
825 std::vector<Polynomial<double>> p;
826 p.reserve(points.size());
828 for (
unsigned int i = 0; i < points.size(); ++i)
829 p.emplace_back(points, i);
851 for (
unsigned int i = 0; i < k; ++i)
858 for (
unsigned int i = 0; i < k; ++i)
865 std::vector<Polynomial<double>>
868 std::vector<Polynomial<double>> v;
870 for (
unsigned int i = 0; i <=
degree; ++i)
920 std::vector<double> legendre_coefficients_tmp1(p);
921 std::vector<double> legendre_coefficients_tmp2(p - 1);
925 legendre_coefficients_tmp1[0] = 1.0;
927 for (
unsigned int i = 2; i < p; ++i)
929 for (
unsigned int j = 0; j < i - 1; ++j)
930 legendre_coefficients_tmp2[j] = legendre_coefficients_tmp1[j];
932 for (
unsigned int j = 0; j < i; ++j)
936 std::sqrt(2 * i + 1.) *
937 ((1.0 - 2 * i) * legendre_coefficients_tmp1[0] /
938 std::sqrt(2 * i - 1.) +
939 (1.0 - i) * legendre_coefficients_tmp2[0] /
940 std::sqrt(2 * i - 3.)) /
943 for (
unsigned int j = 1; j < i - 1; ++j)
945 std::sqrt(2 * i + 1.) *
946 (std::sqrt(2 * i - 1.) *
947 (2.0 * legendre_coefficients_tmp1[j - 1] -
948 legendre_coefficients_tmp1[j]) +
949 (1.0 - i) * legendre_coefficients_tmp2[j] /
950 std::sqrt(2 * i - 3.)) /
954 (2.0 * legendre_coefficients_tmp1[i - 2] -
955 legendre_coefficients_tmp1[i - 1]) /
958 legendre_coefficients_tmp1[i - 1] / i;
961 for (
int i = p; i > 0; --i)
970 std::vector<Polynomial<double>>
973 std::vector<Polynomial<double>> basis(p + 1);
975 for (
unsigned int i = 0; i <= p; ++i)
988 std::vector<std::unique_ptr<const std::vector<double>>>
1002 unsigned int k = k_;
1009 std::lock_guard<std::mutex> lock(coefficients_lock);
1052 std::vector<double> c0(2);
1056 std::vector<double> c1(2);
1063 std_cxx14::make_unique<const std::vector<double>>(std::move(c0));
1065 std_cxx14::make_unique<const std::vector<double>>(std::move(c1));
1069 coefficients_lock.unlock();
1071 coefficients_lock.lock();
1073 std::vector<double> c2(3);
1075 const double a = 1.;
1082 std_cxx14::make_unique<const std::vector<double>>(std::move(c2));
1094 coefficients_lock.unlock();
1096 coefficients_lock.lock();
1098 std::vector<double> ck(k + 1);
1100 const double a = 1.;
1104 for (
unsigned int i = 1; i <= k - 1; ++i)
1126 std_cxx14::make_unique<const std::vector<double>>(std::move(ck));
1133 const std::vector<double> &
1143 std::lock_guard<std::mutex> lock(coefficients_lock);
1149 std::vector<Polynomial<double>>
1162 return std::vector<Polynomial<double>>(
1166 std::vector<Polynomial<double>> v;
1168 for (
unsigned int i = 0; i <=
degree; ++i)
1223 (*this) *= legendre;
1229 std::vector<Polynomial<double>>
1234 "degrees less than three"));
1235 std::vector<Polynomial<double>> basis(n + 1);
1237 for (
unsigned int i = 0; i <= n; ++i)
1253 find_support_point_x_star(
const std::vector<double> &jacobi_roots)
1259 double guess_left = 0;
1260 double guess_right = 0.5;
1261 const unsigned int degree = jacobi_roots.size() + 3;
1273 double integral_left = 0, integral_right = 0;
1274 for (
unsigned int q = 0; q < gauss.size(); ++q)
1276 const double x = gauss.point(q)[0];
1277 double poly_val_common = x;
1278 for (
unsigned int j = 0; j < degree - 3; ++j)
1279 poly_val_common *= Utilities::fixed_power<2>(x - jacobi_roots[j]);
1280 poly_val_common *= Utilities::fixed_power<4>(x - 1.);
1282 gauss.weight(q) * (poly_val_common * (x - guess_left));
1284 gauss.weight(q) * (poly_val_common * (x - guess_right));
1289 return guess_right - (guess_right - guess_left) /
1290 (integral_right - integral_left) * integral_right;
1297 const unsigned int index)
1309 else if (degree == 1)
1322 else if (degree == 2)
1330 else if (index == 1)
1343 else if (degree == 3)
1360 else if (index == 1)
1370 else if (index == 2)
1377 else if (index == 3)
1406 std::vector<double> jacobi_roots =
1407 jacobi_polynomial_roots<double>(
degree - 3, 2, 2);
1416 const double auxiliary_zero =
1417 find_support_point_x_star(jacobi_roots);
1419 for (
unsigned int m = 0; m <
degree - 3; m++)
1427 else if (index == 1)
1430 for (
unsigned int m = 0; m <
degree - 3; m++)
1443 std::vector<Point<1>> points(
degree);
1445 for (
unsigned int i = 0; i <
degree; ++i)
1452 std::vector<double> value_and_grad(2);
1453 helper.
value(0., value_and_grad);
1454 Assert(std::abs(value_and_grad[0]) > 1e-10,
1457 const double auxiliary_zero =
1458 find_support_point_x_star(jacobi_roots);
1460 (1. / auxiliary_zero - value_and_grad[1] / value_and_grad[0]) /
1463 else if (index >= 2 && index <
degree - 1)
1467 for (
unsigned int m = 0, c = 2; m <
degree - 3; m++)
1477 else if (index ==
degree - 1)
1481 for (
unsigned int m = 0; m <
degree - 3; m++)
1485 std::vector<Point<1>> points(
degree);
1487 for (
unsigned int i = 0; i <
degree; ++i)
1494 std::vector<double> value_and_grad(2);
1495 helper.
value(1., value_and_grad);
1496 Assert(std::abs(value_and_grad[0]) > 1e-10,
1499 const double auxiliary_zero =
1500 find_support_point_x_star(jacobi_roots);
1502 (-1. / auxiliary_zero - value_and_grad[1] / value_and_grad[0]) /
1505 else if (index ==
degree)
1507 const double auxiliary_zero =
1508 find_support_point_x_star(jacobi_roots);
1511 for (
unsigned int m = 0; m <
degree - 3; m++)
1523 std::vector<Polynomial<double>>
1526 std::vector<Polynomial<double>> basis(
degree + 1);
1528 for (
unsigned int i = 0; i <=
degree; ++i)
1540 template class Polynomial<float>;
1541 template class Polynomial<double>;
1542 template class Polynomial<long double>;
1557 template class Monomial<float>;
1558 template class Monomial<double>;
1559 template class Monomial<long double>;
1562 DEAL_II_NAMESPACE_CLOSE
void transform_into_standard_form()
LagrangeEquidistant(const unsigned int n, const unsigned int support_point)
#define AssertDimension(dim1, dim2)
void shift(const number2 offset)
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int p)
const std::vector< Point< dim > > & get_points() const
unsigned int degree() const
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int degree)
Legendre(const unsigned int p)
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int degree)
#define AssertIndexRange(index, range)
static std::vector< std::unique_ptr< const std::vector< double > > > recursive_coefficients
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
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)
bool in_lagrange_product_form
double value(const double x) const
std::vector< double > compute_coefficients(const unsigned int p)
__global__ void scale(Number *val, const Number *V_val, const size_type N)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define Assert(cond, exc)
HermiteInterpolation(const unsigned int p)
Lobatto(const unsigned int p=0)
static std::vector< Polynomial< number > > generate_complete_basis(const unsigned int degree)
Hierarchical(const unsigned int p)
HermiteLikeInterpolation(const unsigned int degree, const unsigned int index)
std::vector< number > coefficients
static void compute_coefficients(const unsigned int p)
static const std::vector< double > & get_coefficients(const unsigned int p)
std::vector< number > lagrange_support_points
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int degree)
static ::ExceptionBase & ExcEmptyObject()
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcZero()
std::vector< Polynomial< double > > generate_complete_Lagrange_basis(const std::vector< Point< 1 >> &points)
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int p)
static ::ExceptionBase & ExcInternalError()