1
1
//---------------------------------------------------------------------------
2
// $Id: polynomial.cc 14038 2006-10-23 02:46:34Z bangerth $
2
// $Id: polynomial.cc 20941 2010-04-06 04:00:59Z bangerth $
5
// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 by the deal.II authors
5
// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010 by the deal.II authors
7
7
// This file is subject to QPL and may not be distributed
8
8
// without copyright and license information. Please refer
31
31
// to be a problem since we only need it on very rare occasions. if
32
32
// someone finds this is a bottleneck, feel free to replace it by a
33
33
// more fine-grained solution
36
36
Threads::ThreadMutex coefficients_lock;
55
55
template <typename number>
57
Polynomial<number>::value (const number x) const
59
Assert (coefficients.size() > 0, ExcEmptyObject());
60
const unsigned int m=coefficients.size();
63
number value = coefficients.back();
64
for (int k=m-2; k>=0; --k)
65
value = value*x + coefficients[k];
56
Polynomial<number>::Polynomial (const unsigned int n)
77
68
Assert (coefficients.size() > 0, ExcEmptyObject());
78
69
Assert (values.size() > 0, ExcZero());
79
70
const unsigned int values_size=values.size();
82
73
// if we only need the value, then
83
74
// call the other function since
84
75
// that is significantly faster
178
169
unsigned int new_degree = this->degree() + p.degree();
180
171
std::vector<number> new_coefficients(new_degree+1, 0.);
182
173
for (unsigned int i=0; i<p.coefficients.size(); ++i)
183
174
for (unsigned int j=0; j<this->coefficients.size(); ++j)
184
175
new_coefficients[i+j] += this->coefficients[j]*p.coefficients[i];
185
176
this->coefficients = new_coefficients;
191
182
template <typename number>
192
183
Polynomial<number>&
193
184
Polynomial<number>::operator += (const Polynomial<number>& p)
223
214
template <typename number>
224
215
template <typename number2>
226
217
Polynomial<number>::shift(std::vector<number>& coefficients,
227
218
const number2 offset)
229
220
#ifdef DEAL_II_LONG_DOUBLE_LOOP_BUG
230
221
AssertThrow (false,
231
222
ExcMessage("Sorry, but the compiler you are using has a bug that disallows "
237
228
// args. note that this code is
238
229
// actually unreachable
239
230
coefficients[0] = offset;
241
232
// Copy coefficients to a vector of
242
233
// accuracy given by the argument
243
234
std::vector<number2> new_coefficients(coefficients.begin(),
244
235
coefficients.end());
246
237
// Traverse all coefficients from
247
238
// c_1. c_0 will be modified by
248
239
// higher degrees, only.
352
343
result[n] = coefficient;
357
348
template <typename number>
358
349
Monomial<number>::Monomial (unsigned int n,
359
350
double coefficient)
360
351
: Polynomial<number>(make_vector(n, coefficient))
364
355
template <typename number>
365
356
std::vector<Polynomial<number> >
366
357
Monomial<number>::generate_complete_basis (const unsigned int degree)
376
367
LagrangeEquidistant::LagrangeEquidistant (const unsigned int n,
377
368
const unsigned int support_point)
379
Polynomial<double>(compute_coefficients(n,support_point))
372
this->coefficients.resize(n+1);
373
compute_coefficients(n, support_point, this->coefficients);
377
// We have precomputed tables
378
// up to degree 10. For
379
// higher order, we have to
382
// Start with the constant one
383
this->coefficients.resize(1);
384
this->coefficients[0] = 1.;
386
// Then compute the Lagrange
387
// polynomial as the product
389
std::vector<double> two (2, 1.);
391
for (unsigned int k=0;k<=n;++k)
393
if (k != support_point)
396
Polynomial<double> factor(two);
397
factor.scale(1.*n/(support_point - k));
385
406
LagrangeEquidistant::compute_coefficients (const unsigned int n,
386
const unsigned int support_point)
407
const unsigned int support_point,
408
std::vector<double>& a)
388
std::vector<double> a (n+1);
389
410
Assert(support_point<n+1, ExcIndexRange(support_point, 0, n+1));
391
412
unsigned int n_functions=n+1;
392
413
Assert(support_point<n_functions,
393
414
ExcIndexRange(support_point, 0, n_functions));
394
415
double const *x=0;
595
Assert(false, ExcNotImplemented());
616
Assert(false, ExcInternalError())
598
619
Assert(x!=0, ExcInternalError());
599
620
for (unsigned int i=0; i<n_functions; ++i)
600
621
a[i]=x[support_point*n_functions+i];
638
657
std::vector<double> linear(2, 1.);
639
658
// We start with a constant polynomial
640
659
std::vector<double> one(1, 1.);
642
661
for (unsigned int i=0;i<p.size();++i)
644
663
// Construct interpolation formula
683
702
// ------------------ class Legendre --------------- //
686
//TODO:[?] This class leaks memory, but only at the very end of a program.
687
// Since it expands the Legendre<number>::coefficients array, the elements
688
// of this static variable are not destroyed at the end of the program
689
// run. While this is not a problem (since the returned memory could
690
// not be used anyway then), it is a little confusing when looking at
691
// a memory checker such as "purify". Maybe, this should be handled somehow
692
// to avoid this confusion in future.
694
705
// Reserve space for polynomials up to degree 19. Should be sufficient
695
706
// for the start.
696
std::vector<const std::vector<double> *>
697
Legendre::recursive_coefficients(20,
698
static_cast<const std::vector<double>*>(0));
699
std::vector<const std::vector<double> *>
700
Legendre::shifted_coefficients(20,
701
static_cast<const std::vector<double>*>(0));
707
std::vector<std_cxx1x::shared_ptr<const std::vector<double> > >
708
Legendre::recursive_coefficients(20);
709
std::vector<std_cxx1x::shared_ptr<const std::vector<double> > >
710
Legendre::shifted_coefficients(20);
704
713
Legendre::Legendre (const unsigned int k)
738
747
// already exist?
739
748
if ((recursive_coefficients.size() < k+1) ||
740
749
((recursive_coefficients.size() >= k+1) &&
741
(recursive_coefficients[k] == 0)))
750
(recursive_coefficients[k] ==
751
std_cxx1x::shared_ptr<const std::vector<double> >())))
742
752
// no, then generate the
743
753
// respective coefficients
745
recursive_coefficients.resize (k+1, 0);
755
recursive_coefficients.resize (k+1);
749
759
// create coefficients
764
774
// now make these arrays
766
recursive_coefficients[0] = c0;
767
recursive_coefficients[1] = c1;
775
// const. use shared_ptr for
776
// recursive_coefficients because
777
// that avoids a memory leak that
778
// would appear if we used plain
780
recursive_coefficients[0] =
781
std_cxx1x::shared_ptr<const std::vector<double> >(c0);
782
recursive_coefficients[1] =
783
std_cxx1x::shared_ptr<const std::vector<double> >(c1);
768
785
// Compute polynomials
769
786
// orthogonal on [0,1]
770
787
c0 = new std::vector<double>(*c0);
771
788
c1 = new std::vector<double>(*c1);
773
790
Polynomial<double>::shift<SHIFT_TYPE> (*c0, -1.);
774
791
Polynomial<double>::scale(*c0, 2.);
775
792
Polynomial<double>::shift<SHIFT_TYPE> (*c1, -1.);
776
793
Polynomial<double>::scale(*c1, 2.);
777
794
Polynomial<double>::multiply(*c1, std::sqrt(3.));
778
shifted_coefficients[0]=c0;
779
shifted_coefficients[1]=c1;
795
shifted_coefficients[0]=std_cxx1x::shared_ptr<const std::vector<double> >(c0);
796
shifted_coefficients[1]=std_cxx1x::shared_ptr<const std::vector<double> >(c1);
793
810
coefficients_lock.acquire ();
795
812
std::vector<double> *ck = new std::vector<double>(k+1);
797
814
const double a = 1./(k);
798
815
const double b = a*(2*k-1);
799
816
const double c = a*(k-1);
801
818
(*ck)[k] = b*(*recursive_coefficients[k-1])[k-1];
802
819
(*ck)[k-1] = b*(*recursive_coefficients[k-1])[k-2];
803
820
for (unsigned int i=1 ; i<= k-2 ; ++i)
810
827
// created vector to the
811
828
// const pointer in the
812
829
// coefficients array
813
recursive_coefficients[k] = ck;
830
recursive_coefficients[k] =
831
std_cxx1x::shared_ptr<const std::vector<double> >(ck);
814
832
// and compute the
815
833
// coefficients for [0,1]
816
834
ck = new std::vector<double>(*ck);
817
835
Polynomial<double>::shift<SHIFT_TYPE> (*ck, -1.);
818
836
Polynomial<double>::scale(*ck, 2.);
819
837
Polynomial<double>::multiply(*ck, std::sqrt(2.*k+1.));
820
shifted_coefficients[k] = ck;
838
shifted_coefficients[k] =
839
std_cxx1x::shared_ptr<const std::vector<double> >(ck);
883
902
// until we quit this function
884
903
Threads::ThreadMutex::ScopedLock lock(coefficients_lock);
886
// The first 2 coefficients
905
// The first 2 coefficients
887
906
// are hard-coded
890
909
// check: does the information
891
910
// already exist?
892
911
if ( (recursive_coefficients.size() < k+1) ||
893
((recursive_coefficients.size() >= k+1) &&
912
((recursive_coefficients.size() >= k+1) &&
894
913
(recursive_coefficients[k] == 0)) )
895
914
// no, then generate the
896
915
// respective coefficients
898
917
recursive_coefficients.resize (k+1, 0);
902
921
// create coefficients
951
970
coefficients_lock.acquire ();
953
972
std::vector<double> *ck = new std::vector<double>(k+1);
955
974
const double a = 1.; //1./(2.*k);
957
976
(*ck)[0] = - a*(*recursive_coefficients[k-1])[0];
959
978
for (unsigned int i=1; i<=k-1; ++i)
960
979
(*ck)[i] = a*( 2.*(*recursive_coefficients[k-1])[i-1]
961
980
- (*recursive_coefficients[k-1])[i] );
963
982
(*ck)[k] = a*2.*(*recursive_coefficients[k-1])[k-1];
964
983
// for even degrees, we need
965
984
// to add a multiple of