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
52 template <
typename number>
56 in_lagrange_product_form (false),
62 template <
typename number>
65 coefficients (n+1, 0.),
66 in_lagrange_product_form (false),
72 template <
typename number>
74 const unsigned int center)
76 in_lagrange_product_form (true)
81 lagrange_support_points.reserve (supp.size()-1);
82 number tmp_lagrange_weight = 1.;
83 for (
unsigned int i=0; i<supp.size(); ++i)
86 lagrange_support_points.push_back(supp[i](0));
87 tmp_lagrange_weight *= supp[center](0) - supp[i](0);
91 Assert (std::fabs(tmp_lagrange_weight) > std::numeric_limits<number>::min(),
92 ExcMessage (
"Underflow in computation of Lagrange denominator."));
93 Assert (std::fabs(tmp_lagrange_weight) < std::numeric_limits<number>::max(),
94 ExcMessage (
"Overflow in computation of Lagrange denominator."));
96 lagrange_weight =
static_cast<number
>(1.)/tmp_lagrange_weight;
101 template <
typename number>
104 std::vector<number> &values)
const 108 value(x,values.size()-1,values.data());
113 template <
typename number>
116 const unsigned int n_derivatives,
117 number *values)
const 120 if (in_lagrange_product_form ==
true)
125 const unsigned int n_supp = lagrange_support_points.size();
126 switch (n_derivatives)
130 for (
unsigned int d=1; d<=n_derivatives; ++d)
132 for (
unsigned int i=0; i<n_supp; ++i)
134 const number v = x-lagrange_support_points[i];
142 for (
unsigned int k=n_derivatives; k>0; --k)
143 values[k] = (values[k] * v + values[k-1]);
155 number k_faculty = 1;
156 for (
unsigned int k=0; k<=n_derivatives; ++k)
158 values[k] *= k_faculty * lagrange_weight;
159 k_faculty *=
static_cast<number
>(k+1);
169 for (
unsigned int i=0; i<n_supp; ++i)
171 const number v = x-lagrange_support_points[i];
174 values[0] *= lagrange_weight;
180 for (
unsigned int i=0; i<n_supp; ++i)
182 const number v = x-lagrange_support_points[i];
183 values[1] = values[1] * v + values[0];
186 values[0] *= lagrange_weight;
187 values[1] *= lagrange_weight;
194 for (
unsigned int i=0; i<n_supp; ++i)
196 const number v = x-lagrange_support_points[i];
197 values[2] = values[2] * v + values[1];
198 values[1] = values[1] * v + values[0];
201 values[0] *= lagrange_weight;
202 values[1] *= lagrange_weight;
203 values[2] *=
static_cast<number
>(2) * lagrange_weight;
214 if (n_derivatives == 0)
216 values[0] = value(x);
222 const unsigned int m=coefficients.size();
223 std::vector<number> a(coefficients);
224 unsigned int j_faculty=1;
229 const unsigned int min_valuessize_m=std::min(n_derivatives+1, m);
230 for (
unsigned int j=0; j<min_valuessize_m; ++j)
232 for (
int k=m-2; k>=
static_cast<int>(j); --k)
234 values[j]=
static_cast<number
>(j_faculty)*a[j];
240 for (
unsigned int j=min_valuessize_m; j<=n_derivatives; ++j)
246 template <
typename number>
255 coefficients.resize (lagrange_support_points.size()+1);
256 if (lagrange_support_points.size() == 0)
257 coefficients[0] = 1.;
260 coefficients[0] = -lagrange_support_points[0];
261 coefficients[1] = 1.;
262 for (
unsigned int i=1; i<lagrange_support_points.size(); ++i)
264 coefficients[i+1] = 1.;
265 for (
unsigned int j=i; j>0; --j)
266 coefficients[j] = (-lagrange_support_points[i]*coefficients[j] +
268 coefficients[0] *= -lagrange_support_points[i];
271 for (
unsigned int i=0; i<lagrange_support_points.size()+1; ++i)
272 coefficients[i] *= lagrange_weight;
275 std::vector<number> new_points;
276 lagrange_support_points.swap(new_points);
277 in_lagrange_product_form =
false;
278 lagrange_weight = 1.;
283 template <
typename number>
289 for (
typename std::vector<number>::iterator c = coefficients.begin();
290 c != coefficients.end(); ++c)
299 template <
typename number>
306 if (in_lagrange_product_form ==
true)
308 number inv_fact = number(1.)/factor;
309 number accumulated_fact = 1.;
310 for (
unsigned int i=0; i<lagrange_support_points.size(); ++i)
312 lagrange_support_points[i] *= inv_fact;
313 accumulated_fact *= factor;
315 lagrange_weight *= accumulated_fact;
319 scale (coefficients, factor);
324 template <
typename number>
329 for (
typename std::vector<number>::iterator c = coefficients.begin();
330 c != coefficients.end(); ++c)
336 template <
typename number>
340 if (in_lagrange_product_form ==
true)
341 lagrange_weight *= s;
344 for (
typename std::vector<number>::iterator c = coefficients.begin();
345 c != coefficients.end(); ++c)
353 template <
typename number>
362 lagrange_support_points.insert (lagrange_support_points.end(),
368 else if (in_lagrange_product_form ==
true)
369 transform_into_standard_form();
374 std::unique_ptr<Polynomial<number> > q_data;
378 q_data = std_cxx14::make_unique<Polynomial<number>>(p);
379 q_data->transform_into_standard_form();
386 unsigned int new_degree = this->degree() + q->
degree();
388 std::vector<number> new_coefficients(new_degree+1, 0.);
391 for (
unsigned int j=0; j<this->coefficients.size(); ++j)
392 new_coefficients[i+j] += this->coefficients[j]*q->
coefficients[i];
393 this->coefficients = new_coefficients;
400 template <
typename number>
412 if (in_lagrange_product_form ==
true)
413 transform_into_standard_form();
418 std::unique_ptr<Polynomial<number> > q_data;
422 q_data = std_cxx14::make_unique<Polynomial<number>>(p);
423 q_data->transform_into_standard_form();
442 template <
typename number>
448 if (in_lagrange_product_form ==
true)
449 transform_into_standard_form();
454 std::unique_ptr<Polynomial<number> > q_data;
458 q_data = std_cxx14::make_unique<Polynomial<number>>(p);
459 q_data->transform_into_standard_form();
478 template <
typename number >
487 if (in_lagrange_product_form ==
true &&
491 else if (in_lagrange_product_form ==
true)
509 template <
typename number>
510 template <
typename number2>
513 const number2 offset)
521 std::vector<number2> new_coefficients(coefficients.begin(),
527 for (
unsigned int d=1; d<new_coefficients.size(); ++d)
529 const unsigned int n = d;
534 unsigned int binomial_coefficient = 1;
539 number2 offset_power = offset;
546 for (
unsigned int k=0; k<d; ++k)
552 binomial_coefficient = (binomial_coefficient*(n-k))/(k+1);
554 new_coefficients[d-k-1] += new_coefficients[d]
555 * binomial_coefficient
557 offset_power *= offset;
567 coefficients.assign(new_coefficients.begin(), new_coefficients.end());
572 template <
typename number>
573 template <
typename number2>
580 if (in_lagrange_product_form ==
true)
582 for (
unsigned int i=0; i<lagrange_support_points.size(); ++i)
583 lagrange_support_points[i] -= offset;
587 shift (coefficients, offset);
592 template <
typename number>
601 std::unique_ptr<Polynomial<number> > q_data;
603 if (in_lagrange_product_form ==
true)
605 q_data = std_cxx14::make_unique<Polynomial<number>>(*this);
606 q_data->transform_into_standard_form();
612 std::vector<number> newcoefficients (q->
coefficients.size()-1);
621 template <
typename number>
627 std::unique_ptr<Polynomial<number> > q_data;
629 if (in_lagrange_product_form ==
true)
631 q_data = std_cxx14::make_unique<Polynomial<number>>(*this);
632 q_data->transform_into_standard_form();
638 std::vector<number> newcoefficients (q->
coefficients.size()+1);
639 newcoefficients[0] = 0.;
648 template <
typename number>
652 if (in_lagrange_product_form ==
true)
654 out << lagrange_weight;
655 for (
unsigned int i=0; i<lagrange_support_points.size(); ++i)
656 out <<
" (x-" << lagrange_support_points[i] <<
")";
660 for (
int i=degree(); i>=0; --i)
662 out << coefficients[i] <<
" x^" << i << std::endl;
670 template <
typename number>
675 std::vector<number> result(n+1, 0.);
676 result[n] = coefficient;
682 template <
typename number>
685 :
Polynomial<number>(make_vector(n, coefficient))
690 template <
typename number>
691 std::vector<Polynomial<number> >
694 std::vector<Polynomial<number> > v;
696 for (
unsigned int i=0; i<=degree; ++i)
707 namespace LagrangeEquidistantImplementation
709 std::vector<Point<1> >
710 generate_equidistant_unit_points (
const unsigned int n)
712 std::vector<Point<1> > points (n+1);
713 const double one_over_n = 1./n;
714 for (
unsigned int k=0; k<=n; ++k)
715 points[k](0) =
static_cast<double>(k)*one_over_n;
724 const unsigned int support_point)
727 generate_equidistant_unit_points (n),
738 std::vector<double> new_support_points;
749 const unsigned int support_point,
750 std::vector<double> &a)
754 unsigned int n_functions=n+1;
755 Assert(support_point<n_functions,
757 double const *x=
nullptr;
763 static const double x1[4]=
773 static const double x2[9]=
784 static const double x3[16]=
786 1.0, -11.0/2.0, 9.0, -9.0/2.0,
787 0.0, 9.0, -45.0/2.0, 27.0/2.0,
788 0.0, -9.0/2.0, 18.0, -27.0/2.0,
789 0.0, 1.0, -9.0/2.0, 9.0/2.0
799 for (
unsigned int i=0; i<n_functions; ++i)
800 a[i]=x[support_point*n_functions+i];
805 std::vector<Polynomial<double> >
811 return std::vector<Polynomial<double> >
817 std::vector<Polynomial<double> > v;
818 for (
unsigned int i=0; i<=
degree; ++i)
829 std::vector<Polynomial<double> >
832 std::vector<Polynomial<double> > p;
833 p.reserve (points.size());
835 for (
unsigned int i=0; i<points.size(); ++i)
836 p.emplace_back (points, i);
859 for (
unsigned int i=0; i<k; ++i)
866 for (
unsigned int i=0; i<k; ++i)
873 std::vector<Polynomial<double> >
876 std::vector<Polynomial<double> > v;
878 for (
unsigned int i=0; i<=
degree; ++i)
927 std::vector<double> legendre_coefficients_tmp1 (p);
928 std::vector<double> legendre_coefficients_tmp2 (p - 1);
932 legendre_coefficients_tmp1[0] = 1.0;
934 for (
unsigned int i = 2; i < p; ++i)
936 for (
unsigned int j = 0; j < i - 1; ++j)
937 legendre_coefficients_tmp2[j] = legendre_coefficients_tmp1[j];
939 for (
unsigned int j = 0; j < i; ++j)
942 coefficients[0] = std::sqrt (2 * i + 1.) * ((1.0 - 2 * i) * legendre_coefficients_tmp1[0] / std::sqrt (2 * i - 1.) + (1.0 - i) * legendre_coefficients_tmp2[0] / std::sqrt (2 * i - 3.)) / i;
944 for (
unsigned int j = 1; j < i - 1; ++j)
945 coefficients[j] = std::sqrt (2 * i + 1.) * (std::sqrt (2 * i - 1.) * (2.0 * legendre_coefficients_tmp1[j - 1] - legendre_coefficients_tmp1[j]) + (1.0 - i) * legendre_coefficients_tmp2[j] / std::sqrt (2 * i - 3.)) / i;
947 coefficients[i - 1] = std::sqrt (4 * i * i - 1.) * (2.0 * legendre_coefficients_tmp1[i - 2] - legendre_coefficients_tmp1[i - 1]) / i;
948 coefficients[i] = 2.0 * std::sqrt (4 * i * i - 1.) * legendre_coefficients_tmp1[i - 1] / i;
951 for (
int i = p; i > 0; --i)
962 std::vector<Polynomial<double> > basis (p + 1);
964 for (
unsigned int i = 0; i <= p; ++i)
977 std::vector<std::unique_ptr<const std::vector<double> > >
1042 std::vector<double> c0(2);
1046 std::vector<double> c1(2);
1053 std_cxx14::make_unique<const std::vector<double> >(std::move(c0));
1055 std_cxx14::make_unique<const std::vector<double> >(std::move(c1));
1059 coefficients_lock.release ();
1061 coefficients_lock.acquire ();
1063 std::vector<double> c2(3);
1065 const double a = 1.;
1072 std_cxx14::make_unique<const std::vector<double> >(std::move(c2));
1084 coefficients_lock.release ();
1086 coefficients_lock.acquire ();
1088 std::vector<double> ck (k+1);
1090 const double a = 1.;
1094 for (
unsigned int i=1; i<=k-1; ++i)
1116 std_cxx14::make_unique<const std::vector<double> >(std::move(ck));
1123 const std::vector<double> &
1139 std::vector<Polynomial<double> >
1152 return std::vector<Polynomial<double> >
1156 std::vector<Polynomial<double> > v;
1158 for (
unsigned int i=0; i<=
degree; ++i)
1214 (*this) *= legendre;
1220 std::vector<Polynomial<double> >
1225 "degrees less than three"));
1226 std::vector<Polynomial<double> > basis (n + 1);
1228 for (
unsigned int i = 0; i <= n; ++i)
1243 double find_support_point_x_star (
const std::vector<double> &jacobi_roots)
1249 double guess_left = 0;
1250 double guess_right = 0.5;
1251 const unsigned int degree = jacobi_roots.size() + 3;
1261 double integral_left = 0, integral_right = 0;
1262 for (
unsigned int q=0; q<gauss.size(); ++q)
1264 const double x = gauss.point(q)[0];
1265 double poly_val_common = x;
1266 for (
unsigned int j=0; j<degree-3; ++j)
1267 poly_val_common *= Utilities::fixed_power<2>(x-jacobi_roots[j]);
1268 poly_val_common *= Utilities::fixed_power<4>(x - 1.);
1269 integral_left += gauss.weight(q)*(poly_val_common*(x - guess_left));
1270 integral_right += gauss.weight(q)*(poly_val_common*(x - guess_right));
1275 return guess_right - (guess_right-guess_left)/(integral_right-integral_left)*integral_right;
1282 const unsigned int index)
1295 else if (degree == 1)
1308 else if (degree == 2)
1316 else if (index == 1)
1392 std::vector<double> jacobi_roots = jacobi_polynomial_roots<double>(
degree-3, 2, 2);
1401 const double auxiliary_zero = find_support_point_x_star(jacobi_roots);
1403 for (
unsigned int m=0; m<
degree-3; m++)
1414 for (
unsigned int m=0; m<
degree-3; m++)
1427 std::vector<Point<1>> points(
degree);
1429 for (
unsigned int i=0; i<
degree; ++i)
1436 std::vector<double> value_and_grad(2);
1437 helper.
value(0., value_and_grad);
1438 Assert(std::abs(value_and_grad[0]) > 1e-10,
1441 const double auxiliary_zero = find_support_point_x_star(jacobi_roots);
1442 this->
lagrange_weight = (1./auxiliary_zero - value_and_grad[1]/value_and_grad[0])/ratio;
1444 else if (index>=2 && index<
degree-1)
1448 for (
unsigned int m=0, c=2; m<
degree-3; m++)
1458 else if (index==
degree-1)
1462 for (
unsigned int m=0; m<
degree-3; m++)
1466 std::vector<Point<1>> points(
degree);
1468 for (
unsigned int i=0; i<
degree; ++i)
1475 std::vector<double> value_and_grad(2);
1476 helper.
value(1., value_and_grad);
1477 Assert(std::abs(value_and_grad[0]) > 1e-10,
1480 const double auxiliary_zero = find_support_point_x_star(jacobi_roots);
1481 this->
lagrange_weight = (-1./auxiliary_zero - value_and_grad[1]/value_and_grad[0])/ratio;
1485 const double auxiliary_zero = find_support_point_x_star(jacobi_roots);
1488 for (
unsigned int m=0; m<
degree-3; m++)
1500 std::vector<Polynomial<double> >
1503 std::vector<Polynomial<double> > basis (
degree + 1);
1505 for (
unsigned int i = 0; i <=
degree; ++i)
1517 template class Polynomial<float>;
1518 template class Polynomial<double>;
1519 template class Polynomial<long double>;
1528 template class Monomial<float>;
1529 template class Monomial<double>;
1530 template class Monomial<long double>;
1533 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
std::vector< Polynomial< double > > generate_complete_Lagrange_basis(const std::vector< Point< 1 > > &points)
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)
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()
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int p)
static ::ExceptionBase & ExcInternalError()