Nektar++
Polylib.cpp
Go to the documentation of this file.
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <math.h>
4 #include "Polylib.h"
5 #include <float.h>
6 #include <complex>
7 
8 #include <boost/core/ignore_unused.hpp>
9 
11 /// Maximum number of iterations in polynomial defalation routine Jacobz
12 #define STOP 30
13 /// Precision tolerance for two points to be similar
14 #define EPS 100*DBL_EPSILON
15 /// return the sign(b)*a
16 #define sign(a,b) ((b)<0 ? -fabs(a) : fabs(a))
17 
18 namespace Polylib {
19 
20  /// The following function is used to circumvent/reduce "Subtractive Cancellation"
21  /// The expression 1/dz is replaced by optinvsub(.,.)
22  /// Added on 26 April 2017
23  double optdiff(double xl, double xr)
24  {
25  double m_xln, m_xrn;
26  int m_expn;
27  int m_digits = static_cast<int>(fabs(floor(log10(DBL_EPSILON)))-1);
28 
29  if (fabs(xl-xr)<1.e-4){
30 
31  m_expn = static_cast<int>(floor(log10(fabs(xl-xr))));
32  m_xln = xl*powl(10.0L,-m_expn)-floor(xl*powl(10.0L,-m_expn)); // substract the digits overlap part
33  m_xrn = xr*powl(10.0L,-m_expn)-floor(xl*powl(10.0L,-m_expn)); // substract the common digits overlap part
34  m_xln = round(m_xln*powl(10.0L,m_digits+m_expn)); // git rid of rubbish
35  m_xrn = round(m_xrn*powl(10.0L,m_digits+m_expn));
36 
37  return powl(10.0L,-m_digits)*(m_xln-m_xrn);
38  }else{
39  return (xl-xr);
40  }
41  }
42 
43  double laginterp(double z, int j, const double *zj, int np)
44  {
45  double temp = 1.0;
46  for (int i=0; i<np; i++)
47  {
48  if (j != i)
49  {
50  temp *=optdiff(z,zj[i])/(zj[j]-zj[i]);
51  }
52  }
53  return temp;
54  }
55  /// Define whether to use polynomial deflation (1) or tridiagonal solver (0).
56 #define POLYNOMIAL_DEFLATION 0
57 
58 #ifdef POLYNOMIAL_DEFLATION
59  /// zero determination using Newton iteration with polynomial deflation
60 #define jacobz(n,z,alpha,beta) Jacobz(n,z,alpha,beta)
61 #else
62  /// zero determination using eigenvalues of tridiagaonl matrix
63 #define jacobz(n,z,alpha,beta) JacZeros(n,z,alpha,beta)
64 #endif
65 
66 
67 
68  /* local functions */
69  static void Jacobz (const int n, double *z, const double alpha,
70  const double beta);
71  // static void JacZeros (const int n, double *a, const double alpha,
72  // const double beta);
73  //static void TriQL (const int n, double *d, double *e);
74  static void TriQL(const int, double *,double *, double **);
75  double gammaF (const double);
76  static void RecCoeff(const int, double *, double *,const double,
77  const double);
78  void JKMatrix(int, double *, double *);
79  void chri1(int,double*,double*,double*,double*,double);
80 
81  /**
82  \brief Gauss-Jacobi zeros and weights.
83 
84  \li Generate \a np Gauss Jacobi zeros, \a z, and weights,\a w,
85  associated with the Jacobi polynomial \f$ P^{\alpha,\beta}_{np}(z)
86  \f$,
87 
88  \li Exact for polynomials of order \a 2np-1 or less
89  */
90 
91  void zwgj (double *z, double *w, const int np, const double alpha,
92  const double beta)
93  {
94  int i;
95  double fac, one = 1.0, two = 2.0, apb = alpha + beta;
96 
97  jacobz (np,z,alpha,beta);
98  jacobd (np,z,w,np,alpha,beta);
99 
100  fac = pow(two,apb + one)*gammaF(alpha + np + one)*gammaF(beta + np + one);
101  fac /= gammaF(np + one)*gammaF(apb + np + one);
102 
103  for(i = 0; i < np; ++i) w[i] = fac/(w[i]*w[i]*(one-z[i]*z[i]));
104 
105  return;
106  }
107 
108 
109  /**
110  \brief Gauss-Radau-Jacobi zeros and weights with end point at \a z=-1.
111 
112  \li Generate \a np Gauss-Radau-Jacobi zeros, \a z, and weights,\a w,
113  associated with the polynomial \f$(1+z) P^{\alpha,\beta+1}_{np-1}(z)
114  \f$.
115 
116  \li Exact for polynomials of order \a 2np-2 or less
117  */
118 
119  void zwgrjm(double *z, double *w, const int np, const double alpha,
120  const double beta)
121  {
122 
123  if(np == 1){
124  z[0] = 0.0;
125  w[0] = 2.0;
126  }
127  else{
128  int i;
129  double fac, one = 1.0, two = 2.0, apb = alpha + beta;
130 
131  z[0] = -one;
132  jacobz (np-1,z+1,alpha,beta+1);
133  jacobfd (np,z,w,NULL,np-1,alpha,beta);
134 
135  fac = pow(two,apb)*gammaF(alpha + np)*gammaF(beta + np);
136  fac /= gammaF(np)*(beta + np)*gammaF(apb + np + 1);
137 
138  for(i = 0; i < np; ++i) w[i] = fac*(1-z[i])/(w[i]*w[i]);
139  w[0] *= (beta + one);
140  }
141 
142  return;
143  }
144 
145 
146  /**
147  \brief Gauss-Radau-Jacobi zeros and weights with end point at \a z=1
148 
149 
150  \li Generate \a np Gauss-Radau-Jacobi zeros, \a z, and weights,\a w,
151  associated with the polynomial \f$(1-z) P^{\alpha+1,\beta}_{np-1}(z)
152  \f$.
153 
154  \li Exact for polynomials of order \a 2np-2 or less
155  */
156 
157  void zwgrjp(double *z, double *w, const int np, const double alpha,
158  const double beta)
159  {
160 
161  if(np == 1){
162  z[0] = 0.0;
163  w[0] = 2.0;
164  }
165  else{
166  int i;
167  double fac, one = 1.0, two = 2.0, apb = alpha + beta;
168 
169  jacobz (np-1,z,alpha+1,beta);
170  z[np-1] = one;
171  jacobfd (np,z,w,NULL,np-1,alpha,beta);
172 
173  fac = pow(two,apb)*gammaF(alpha + np)*gammaF(beta + np);
174  fac /= gammaF(np)*(alpha + np)*gammaF(apb + np + 1);
175 
176  for(i = 0; i < np; ++i) w[i] = fac*(1+z[i])/(w[i]*w[i]);
177  w[np-1] *= (alpha + one);
178  }
179 
180  return;
181  }
182 
183 
184  /**
185  \brief Gauss-Lobatto-Jacobi zeros and weights with end point at \a z=-1,\a 1
186 
187 
188  \li Generate \a np Gauss-Lobatto-Jacobi points, \a z, and weights, \a w,
189  associated with polynomial \f$ (1-z)(1+z) P^{\alpha+1,\beta+1}_{np-2}(z) \f$
190  \li Exact for polynomials of order \a 2np-3 or less
191  */
192 
193  void zwglj(double *z, double *w, const int np, const double alpha,
194  const double beta)
195  {
196 
197  if( np == 1 ){
198  z[0] = 0.0;
199  w[0] = 2.0;
200  }
201  else if( np == 2 ){
202  z[0] = -1.0;
203  z[1] = 1.0;
204 
205  w[0] = 1.0;
206  w[1] = 1.0;
207  }
208  else{
209  int i;
210  double fac, one = 1.0, apb = alpha + beta, two = 2.0;
211 
212  z[0] = -one;
213  z[np-1] = one;
214  jacobz (np-2,z + 1,alpha + one,beta + one);
215  jacobfd (np,z,w,NULL,np-1,alpha,beta);
216 
217  fac = pow(two,apb + 1)*gammaF(alpha + np)*gammaF(beta + np);
218  fac /= (np-1)*gammaF(np)*gammaF(alpha + beta + np + one);
219 
220  for(i = 0; i < np; ++i) w[i] = fac/(w[i]*w[i]);
221  w[0] *= (beta + one);
222  w[np-1] *= (alpha + one);
223  }
224 
225  return;
226  }
227 
228  /**
229  \brief Gauss-Kronrod-Jacobi zeros and weights.
230 
231  \li Generate \a npt=2*np+1 Gauss-Kronrod Jacobi zeros, \a z, and weights,\a w,
232  associated with the Jacobi polynomial \f$ P^{\alpha,\beta}_{np}(z)
233  \f$,
234 
235  \li Exact for polynomials of order \a 3np+1 or less
236  */
237  void zwgk(double *z, double *w, const int npt , const double alpha,
238  const double beta)
239  {
240 
241  int np = (npt-1)/2;
242 
243  int i,j;
244 
245  // number of kronrod points associated with the np gauss rule
246  int kpoints = 2*np + 1;
247 
248  // Define the number of required recurrence coefficents
249  int ncoeffs = (int)floor(3.0*(np+1)/2);
250 
251  // Define arrays for the recurrence coefficients
252  // We will use these arrays for the Kronrod results too, hence the
253  // reason for the size of the arrays
254  double *a = new double[kpoints];
255  double *b = new double[kpoints];
256 
257  // Initialize a and b to zero
258  for(i = 0; i < kpoints; i++)
259  {
260  a[i] = 0.0;
261  b[i] = 0.0;
262  }
263 
264  // Call the routine to calculate the recurrence coefficients
265  RecCoeff(ncoeffs,a,b,alpha,beta);
266 
267  // Call the routine to caluclate the jacobi-Kronrod matrix
268  JKMatrix(np,a,b);
269 
270  // Set up the identity matrix
271  double** zmatrix = new double*[kpoints];
272  for(i = 0; i < kpoints; i++)
273  {
274  zmatrix[i] = new double[kpoints];
275  for(j = 0; j < kpoints; j++)
276  {
277  zmatrix[i][j] = 0.0;
278  }
279  }
280  for(i = 0; i < kpoints; i++)
281  {
282  zmatrix[i][i] = 1.0;
283  }
284 
285  // Calculte the points and weights
286  TriQL(kpoints, a, b, zmatrix);
287 
288  for(i = 0; i < kpoints; i++)
289  {
290  z[i] = a[i];
291  w[i] = b[i];
292  }
293  delete[] a;
294  delete[] b;
295  for (i = 0; i < kpoints; i++)
296  {
297  delete[] zmatrix[i];
298  }
299  delete[] zmatrix;
300 
301  }
302 
303  /**
304  \brief Gauss-Radau-Kronrod-Jacobi zeros and weights.
305 
306  \li Generate \a npt=2*np Radau-Kronrod Jacobi zeros, \a z, and weights,\a w,
307  associated with the Jacobi polynomial \f$ P^{\alpha,\beta}_{np}(z)
308  \f$,
309  */
310  void zwrk(double* z, double* w, const int npt ,const double alpha,
311  const double beta)
312  {
313 
314  int np = npt/2;
315 
316  if(np < 2)
317  {
318  fprintf(stderr,"too few points in formula\n");
319  return;
320  }
321 
322  double end0 = -1;
323 
324  int i,j;
325 
326  // number of kronrod points associated with the np gauss rule
327  int kpoints = 2*np;
328 
329  // Define the number of required recurrence coefficents
330  int ncoeffs = (int)ceil(3.0*np/2);
331 
332  // Define arrays for the recurrence coefficients
333  double *a = new double[ncoeffs+1];
334  double *b = new double[ncoeffs+1];
335 
336  // Initialize a and b to zero
337  for(i = 0; i < ncoeffs+1; i++)
338  {
339  a[i] = 0.0;
340  b[i] = 0.0;
341  }
342 
343  // Call the routine to calculate the recurrence coefficients
344  RecCoeff(ncoeffs,a,b,alpha,beta);
345 
346  double* a0 = new double[ncoeffs];
347  double* b0 = new double[ncoeffs];
348 
349  chri1(ncoeffs,a,b,a0,b0,end0);
350 
351  double s = b0[0]/fabs(b0[0]);
352  b0[0] = s*b0[0];
353 
354  // Finding the 2*np-1 gauss-kronrod points
355  double* z1 = new double[2*np-1];
356  double* w1 = new double[2*np-1];
357  for(i = 0; i < ncoeffs; i++)
358  {
359  z1[i] = a0[i];
360  w1[i] = b0[i];
361  }
362  JKMatrix(np-1,z1,w1);
363  // Set up the identity matrix
364  double** zmatrix = new double*[2*np-1];
365  for(i = 0; i < 2*np-1; i++)
366  {
367  zmatrix[i] = new double[2*np-1];
368  for(j = 0; j < 2*np-1; j++)
369  {
370  zmatrix[i][j] = 0.0;
371  }
372  }
373  for(i = 0; i < 2*np-1; i++)
374  {
375  zmatrix[i][i] = 1.0;
376  }
377 
378  // Calculate the points and weights
379  TriQL(2*np-1, z1, w1, zmatrix);
380 
381  double sumW1 = 0.0;
382  for(i = 0; i < 2*np-1; i++)
383  {
384  w1[i] = s*w1[i]/(z1[i]-end0);
385  sumW1 += w1[i];
386  }
387 
388  z[0] = end0;
389  w[0] = b[0]- sumW1;
390  for(i = 1; i < kpoints; i++)
391  {
392  z[i] = z1[i-1];
393  w[i] = w1[i-1];
394  }
395 
396 
397  delete[] a;
398  delete[] b;
399  delete[] a0;
400  delete[] b0;
401  delete[] z1;
402  delete[] w1;
403  for(i = 0; i < 2*np-1; i++)
404  {
405  delete[] zmatrix[i];
406  }
407  delete[] zmatrix;
408  }
409 
410  /**
411  \brief Gauss-Lobatto-Kronrod-Jacobi zeros and weights.
412 
413  \li Generate \a npt=2*np-1 Lobatto-Kronrod Jacobi zeros, \a z, and weights,\a w,
414  associated with the Jacobi polynomial \f$ P^{\alpha,\beta}_{np}(z)
415  \f$,
416  */
417  void zwlk(double* z, double* w, const int npt,
418  const double alpha, const double beta)
419  {
420 
421  int np = (npt+1)/2;
422 
423  if(np < 4)
424  {
425  fprintf (stderr,"too few points in formula\n");
426  return;
427  }
428 
429  double endl = -1;
430  double endr = 1;
431  int i,j;
432 
433  // number of kronrod points associated with the np gauss rule
434  int kpoints = 2*np-1;
435 
436  // Define the number of required recurrence coefficents
437  int ncoeffs = (int)ceil(3.0*np/2)-1;
438 
439  // Define arrays for the recurrence coefficients
440  double *a = new double[ncoeffs+1];
441  double *b = new double[ncoeffs+1];
442 
443  // Initialize a and b to zero
444  for(i = 0; i < ncoeffs+1; i++)
445  {
446  a[i] = 0.0;
447  b[i] = 0.0;
448  }
449 
450  // Call the routine to calculate the recurrence coefficients
451  RecCoeff(ncoeffs,a,b,alpha,beta);
452 
453 
454  double* a0 = new double[ncoeffs];
455  double* b0 = new double[ncoeffs];
456 
457  chri1(ncoeffs,a,b,a0,b0,endl);
458 
459  double* a1 = new double[ncoeffs-1];
460  double* b1 = new double[ncoeffs-1];
461 
462  chri1(ncoeffs-1,a0,b0,a1,b1,endr);
463 
464 
465  double s = b1[0]/fabs(b1[0]);
466  b1[0] = s*b1[0];
467 
468  // Finding the 2*np-1 gauss-kronrod points
469  double* z1 = new double[2*np-3];
470  double* w1 = new double[2*np-3];
471  for(i = 0; i < ncoeffs; i++)
472  {
473  z1[i] = a1[i];
474  w1[i] = b1[i];
475  }
476  JKMatrix(np-2,z1,w1);
477  // Set up the identity matrix
478  double** zmatrix = new double*[2*np-3];
479  for(i = 0; i < 2*np-3; i++)
480  {
481  zmatrix[i] = new double[2*np-3];
482  for(j = 0; j < 2*np-3; j++)
483  {
484  zmatrix[i][j] = 0.0;
485  }
486  }
487  for(i = 0; i < 2*np-3; i++)
488  {
489  zmatrix[i][i] = 1.0;
490  }
491 
492  // Calculate the points and weights
493  TriQL(2*np-3, z1, w1, zmatrix);
494 
495  double sumW1 = 0.0;
496  double sumW1Z1 = 0.0;
497  for(i = 0; i < 2*np-3; i++)
498  {
499  w1[i] = s*w1[i]/(z1[i]-endl)/(z1[i]-endr);
500  sumW1 += w1[i];
501  sumW1Z1 += z1[i]*w1[i];
502  }
503 
504  double c0 = b[0]-sumW1;
505  double c1 = a[0]*b[0]-sumW1Z1;
506 
507  z[0] = endl;
508  z[2*np-2] = endr;
509  w[0] = (c0*endr-c1)/(endr-endl);
510  w[2*np-2] = (c1-c0*endl)/(endr-endl);
511 
512  for(i = 1; i < kpoints-1; i++)
513  {
514  z[i] = z1[i-1];
515  w[i] = w1[i-1];
516  }
517  delete[] a;
518  delete[] b;
519  delete[] a0;
520  delete[] b0;
521  delete[] a1;
522  delete[] b1;
523  delete[] z1;
524  delete[] w1;
525  for(i = 0; i < 2*np-3; i++)
526  {
527  delete[] zmatrix[i];
528  }
529  delete[] zmatrix;
530  }
531 
532  /**
533  \brief Compute the Derivative Matrix and its transpose associated
534  with the Gauss-Jacobi zeros.
535 
536  \li Compute the derivative matrix, \a d, and its transpose, \a dt,
537  associated with the n_th order Lagrangian interpolants through the
538  \a np Gauss-Jacobi points \a z such that \n
539  \f$ \frac{du}{dz}(z[i]) = \sum_{j=0}^{np-1} D[i*np+j] u(z[j]) \f$
540 
541  */
542 
543  void Dgj(double *D, const double *z, const int np, const double alpha,
544  const double beta)
545  {
546 
547  double one = 1.0, two = 2.0;
548 
549  if (np <= 0){
550  D[0] = 0.0;
551  }
552  else{
553  int i,j;
554  double *pd;
555 
556  pd = (double *)malloc(np*sizeof(double));
557  jacobd(np,z,pd,np,alpha,beta);
558 
559  for (i = 0; i < np; i++){
560  for (j = 0; j < np; j++){
561 
562  if (i != j)
563  D[i*np+j] = pd[j]/(pd[i]*(z[j]-z[i]));
564  else
565  D[i*np+j] = (alpha - beta + (alpha + beta + two)*z[j])/
566  (two*(one - z[j]*z[j]));
567  }
568  }
569  free(pd);
570  }
571  return;
572  }
573 
574 
575  /**
576  \brief Compute the Derivative Matrix and its transpose associated
577  with the Gauss-Radau-Jacobi zeros with a zero at \a z=-1.
578 
579  \li Compute the derivative matrix, \a d, associated with the n_th
580  order Lagrangian interpolants through the \a np Gauss-Radau-Jacobi
581  points \a z such that \n \f$ \frac{du}{dz}(z[i]) =
582  \sum_{j=0}^{np-1} D[i*np+j] u(z[j]) \f$
583 
584  */
585 
586  void Dgrjm(double *D, const double *z, const int np, const double alpha,
587  const double beta)
588  {
589 
590  if (np <= 0){
591  D[0] = 0.0;
592  }
593  else{
594  int i, j;
595  double one = 1.0, two = 2.0;
596  double *pd;
597 
598  pd = (double *)malloc(np*sizeof(double));
599 
600  pd[0] = pow(-one,np-1)*gammaF(np+beta+one);
601  pd[0] /= gammaF(np)*gammaF(beta+two);
602  jacobd(np-1,z+1,pd+1,np-1,alpha,beta+1);
603  for(i = 1; i < np; ++i) pd[i] *= (1+z[i]);
604 
605  for (i = 0; i < np; i++) {
606  for (j = 0; j < np; j++){
607  if (i != j)
608  D[i*np+j] = pd[j]/(pd[i]*(z[j]-z[i]));
609  else {
610  if(j == 0)
611  D[i*np+j] = -(np + alpha + beta + one)*(np - one)/
612  (two*(beta + two));
613  else
614  D[i*np+j] = (alpha - beta + one + (alpha + beta + one)*z[j])/
615  (two*(one - z[j]*z[j]));
616  }
617  }
618  }
619  free(pd);
620  }
621 
622  return;
623  }
624 
625 
626  /**
627  \brief Compute the Derivative Matrix associated with the
628  Gauss-Radau-Jacobi zeros with a zero at \a z=1.
629 
630  \li Compute the derivative matrix, \a d, associated with the n_th
631  order Lagrangian interpolants through the \a np Gauss-Radau-Jacobi
632  points \a z such that \n \f$ \frac{du}{dz}(z[i]) =
633  \sum_{j=0}^{np-1} D[i*np+j] u(z[j]) \f$
634  */
635 
636  void Dgrjp(double *D, const double *z, const int np, const double alpha,
637  const double beta)
638  {
639 
640  if (np <= 0){
641  D[0] = 0.0;
642  }
643  else{
644  int i, j;
645  double one = 1.0, two = 2.0;
646  double *pd;
647 
648  pd = (double *)malloc(np*sizeof(double));
649 
650 
651  jacobd(np-1,z,pd,np-1,alpha+1,beta);
652  for(i = 0; i < np-1; ++i) pd[i] *= (1-z[i]);
653  pd[np-1] = -gammaF(np+alpha+one);
654  pd[np-1] /= gammaF(np)*gammaF(alpha+two);
655 
656  for (i = 0; i < np; i++) {
657  for (j = 0; j < np; j++){
658  if (i != j)
659  D[i*np+j] = pd[j]/(pd[i]*(z[j]-z[i]));
660  else {
661  if(j == np-1)
662  D[i*np+j] = (np + alpha + beta + one)*(np - one)/
663  (two*(alpha + two));
664  else
665  D[i*np+j] = (alpha - beta - one + (alpha + beta + one)*z[j])/
666  (two*(one - z[j]*z[j]));
667  }
668  }
669  }
670  free(pd);
671  }
672 
673  return;
674  }
675 
676  /**
677  \brief Compute the Derivative Matrix associated with the
678  Gauss-Lobatto-Jacobi zeros.
679 
680  \li Compute the derivative matrix, \a d, associated with the n_th
681  order Lagrange interpolants through the \a np
682  Gauss-Lobatto-Jacobi points \a z such that \n \f$
683  \frac{du}{dz}(z[i]) = \sum_{j=0}^{np-1} D[i*np+j] u(z[j]) \f$
684 
685  */
686 
687  void Dglj(double *D, const double *z, const int np, const double alpha,
688  const double beta)
689  {
690  if (np <= 1){
691  D[0] = 0.0;
692  }
693  else{
694  int i, j;
695  double one = 1.0, two = 2.0;
696  double *pd;
697 
698  pd = (double *)malloc(np*sizeof(double));
699 
700  pd[0] = two*pow(-one,np)*gammaF(np + beta);
701  pd[0] /= gammaF(np - one)*gammaF(beta + two);
702  jacobd(np-2,z+1,pd+1,np-2,alpha+1,beta+1);
703  for(i = 1; i < np-1; ++i) pd[i] *= (one-z[i]*z[i]);
704  pd[np-1] = -two*gammaF(np + alpha);
705  pd[np-1] /= gammaF(np - one)*gammaF(alpha + two);
706 
707  for (i = 0; i < np; i++) {
708  for (j = 0; j < np; j++){
709  if (i != j)
710  D[i*np+j] = pd[j]/(pd[i]*(z[j]-z[i]));
711  else {
712  if (j == 0)
713  D[i*np+j] = (alpha - (np-1)*(np + alpha + beta))/(two*(beta+ two));
714  else if (j == np-1)
715  D[i*np+j] =-(beta - (np-1)*(np + alpha + beta))/(two*(alpha+ two));
716  else
717  D[i*np+j] = (alpha - beta + (alpha + beta)*z[j])/
718  (two*(one - z[j]*z[j]));
719  }
720  }
721  }
722  free(pd);
723  }
724 
725  return;
726  }
727 
728 
729  /**
730  \brief Compute the value of the \a i th Lagrangian interpolant through
731  the \a np Gauss-Jacobi points \a zgj at the arbitrary location \a z.
732 
733  \li \f$ -1 \leq z \leq 1 \f$
734 
735  \li Uses the defintion of the Lagrangian interpolant:\n
736  %
737  \f$ \begin{array}{rcl}
738  h_j(z) = \left\{ \begin{array}{ll}
739  \displaystyle \frac{P_{np}^{\alpha,\beta}(z)}
740  {[P_{np}^{\alpha,\beta}(z_j)]^\prime
741  (z-z_j)} & \mbox{if $z \ne z_j$}\\
742  & \\
743  1 & \mbox{if $z=z_j$}
744  \end{array}
745  \right.
746  \end{array} \f$
747  */
748 
749  double hgj (const int i, const double z, const double *zgj,
750  const int np, const double alpha, const double beta)
751  {
752  boost::ignore_unused(alpha, beta);
753  double zi, dz;
754 
755  zi = *(zgj+i);
756  dz = z-zi;
757  if (fabs(dz) < EPS) return 1.0;
758 
759  return laginterp(z, i, zgj, np);
760 
761  }
762 
763  /**
764  \brief Compute the value of the \a i th Lagrangian interpolant through the
765  \a np Gauss-Radau-Jacobi points \a zgrj at the arbitrary location
766  \a z. This routine assumes \a zgrj includes the point \a -1.
767 
768  \li \f$ -1 \leq z \leq 1 \f$
769 
770  \li Uses the defintion of the Lagrangian interpolant:\n
771  %
772  \f$ \begin{array}{rcl}
773  h_j(z) = \left\{ \begin{array}{ll}
774  \displaystyle \frac{(1+z) P_{np-1}^{\alpha,\beta+1}(z)}
775  {((1+z_j) [P_{np-1}^{\alpha,\beta+1}(z_j)]^\prime +
776  P_{np-1}^{\alpha,\beta+1}(z_j) ) (z-z_j)} & \mbox{if $z \ne z_j$}\\
777  & \\
778  1 & \mbox{if $z=z_j$}
779  \end{array}
780  \right.
781  \end{array} \f$
782  */
783 
784  double hgrjm (const int i, const double z, const double *zgrj, const int np,
785  const double alpha, const double beta)
786  {
787  boost::ignore_unused(alpha, beta);
788 
789  double zi, dz;
790 
791  zi = *(zgrj+i);
792  dz = z-zi;
793  if (fabs(dz) < EPS) return 1.0;
794 
795  return laginterp(z, i, zgrj, np);
796  }
797 
798 
799  /**
800  \brief Compute the value of the \a i th Lagrangian interpolant through the
801  \a np Gauss-Radau-Jacobi points \a zgrj at the arbitrary location
802  \a z. This routine assumes \a zgrj includes the point \a +1.
803 
804  \li \f$ -1 \leq z \leq 1 \f$
805 
806  \li Uses the defintion of the Lagrangian interpolant:\n
807  %
808  \f$ \begin{array}{rcl}
809  h_j(z) = \left\{ \begin{array}{ll}
810  \displaystyle \frac{(1-z) P_{np-1}^{\alpha+1,\beta}(z)}
811  {((1-z_j) [P_{np-1}^{\alpha+1,\beta}(z_j)]^\prime -
812  P_{np-1}^{\alpha+1,\beta}(z_j) ) (z-z_j)} & \mbox{if $z \ne z_j$}\\
813  & \\
814  1 & \mbox{if $z=z_j$}
815  \end{array}
816  \right.
817  \end{array} \f$
818  */
819 
820  double hgrjp (const int i, const double z, const double *zgrj, const int np,
821  const double alpha, const double beta)
822  {
823  boost::ignore_unused(alpha, beta);
824  double zi, dz;
825 
826  zi = *(zgrj+i);
827  dz = z-zi;
828  if (fabs(dz) < EPS) return 1.0;
829 
830  return laginterp(z, i, zgrj, np);
831  }
832 
833 
834  /**
835  \brief Compute the value of the \a i th Lagrangian interpolant through the
836  \a np Gauss-Lobatto-Jacobi points \a zgrj at the arbitrary location
837  \a z.
838 
839  \li \f$ -1 \leq z \leq 1 \f$
840 
841  \li Uses the defintion of the Lagrangian interpolant:\n
842  %
843  \f$ \begin{array}{rcl}
844  h_j(z) = \left\{ \begin{array}{ll}
845  \displaystyle \frac{(1-z^2) P_{np-2}^{\alpha+1,\beta+1}(z)}
846  {((1-z^2_j) [P_{np-2}^{\alpha+1,\beta+1}(z_j)]^\prime -
847  2 z_j P_{np-2}^{\alpha+1,\beta+1}(z_j) ) (z-z_j)}&\mbox{if $z \ne z_j$}\\
848  & \\
849  1 & \mbox{if $z=z_j$}
850  \end{array}
851  \right.
852  \end{array} \f$
853  */
854 
855  double hglj (const int i, const double z, const double *zglj, const int np,
856  const double alpha, const double beta)
857  {
858  boost::ignore_unused(alpha, beta);
859 
860  double zi, dz;
861 
862  zi = *(zglj+i);
863  dz = z-zi;
864  if (fabs(dz) < EPS) return 1.0;
865 
866  return laginterp(z, i, zglj, np);
867 
868  }
869 
870 
871  /**
872  \brief Interpolation Operator from Gauss-Jacobi points to an
873  arbitrary distribution at points \a zm
874 
875  \li Computes the one-dimensional interpolation matrix, \a im, to
876  interpolate a function from at Gauss-Jacobi distribution of \a nz
877  zeros \a zgrj to an arbitrary distribution of \a mz points \a zm, i.e.\n
878  \f$
879  u(zm[i]) = \sum_{j=0}^{nz-1} im[i*nz+j] \ u(zgj[j])
880  \f$
881 
882  */
883 
884  void Imgj(double *im, const double *zgj, const double *zm, const int nz,
885  const int mz,const double alpha, const double beta){
886  double zp;
887  int i, j;
888 
889  for (i = 0; i < nz; ++i) {
890  for (j = 0; j < mz; ++j)
891  {
892  zp = zm[j];
893  im [i*mz+j] = hgj(i, zp, zgj, nz, alpha, beta);
894  }
895  }
896 
897  return;
898  }
899 
900  /**
901  \brief Interpolation Operator from Gauss-Radau-Jacobi points
902  (including \a z=-1) to an arbitrary distrubtion at points \a zm
903 
904  \li Computes the one-dimensional interpolation matrix, \a im, to
905  interpolate a function from at Gauss-Radau-Jacobi distribution of
906  \a nz zeros \a zgrj (where \a zgrj[0]=-1) to an arbitrary
907  distribution of \a mz points \a zm, i.e.
908  \n
909  \f$ u(zm[i]) = \sum_{j=0}^{nz-1} im[i*nz+j] \ u(zgj[j]) \f$
910 
911  */
912 
913  void Imgrjm(double *im, const double *zgrj, const double *zm, const int nz,
914  const int mz, const double alpha, const double beta)
915  {
916  double zp;
917  int i, j;
918 
919  for (i = 0; i < nz; i++) {
920  for (j = 0; j < mz; j++)
921  {
922  zp = zm[j];
923  im [i*mz+j] = hgrjm(i, zp, zgrj, nz, alpha, beta);
924  }
925  }
926 
927  return;
928  }
929 
930  /**
931  \brief Interpolation Operator from Gauss-Radau-Jacobi points
932  (including \a z=1) to an arbitrary distrubtion at points \a zm
933 
934  \li Computes the one-dimensional interpolation matrix, \a im, to
935  interpolate a function from at Gauss-Radau-Jacobi distribution of
936  \a nz zeros \a zgrj (where \a zgrj[nz-1]=1) to an arbitrary
937  distribution of \a mz points \a zm, i.e.
938  \n
939  \f$ u(zm[i]) = \sum_{j=0}^{nz-1} im[i*nz+j] \ u(zgj[j]) \f$
940 
941  */
942 
943  void Imgrjp(double *im, const double *zgrj, const double *zm, const int nz,
944  const int mz,const double alpha, const double beta)
945  {
946  double zp;
947  int i, j;
948 
949  for (i = 0; i < nz; i++) {
950  for (j = 0; j < mz; j++)
951  {
952  zp = zm[j];
953  im [i*mz+j] = hgrjp(i, zp, zgrj, nz, alpha, beta);
954  }
955  }
956 
957  return;
958  }
959 
960 
961  /**
962  \brief Interpolation Operator from Gauss-Lobatto-Jacobi points
963  to an arbitrary distrubtion at points \a zm
964 
965  \li Computes the one-dimensional interpolation matrix, \a im, to
966  interpolate a function from at Gauss-Lobatto-Jacobi distribution of
967  \a nz zeros \a zgrj (where \a zgrj[0]=-1) to an arbitrary
968  distribution of \a mz points \a zm, i.e.
969  \n
970  \f$ u(zm[i]) = \sum_{j=0}^{nz-1} im[i*nz+j] \ u(zgj[j]) \f$
971 
972  */
973 
974  void Imglj(double *im, const double *zglj, const double *zm, const int nz,
975  const int mz, const double alpha, const double beta)
976  {
977  double zp;
978  int i, j;
979 
980  for (i = 0; i < nz; i++) {
981  for (j = 0; j < mz; j++)
982  {
983  zp = zm[j];
984  im[i*mz+j] = hglj(i, zp, zglj, nz, alpha, beta);
985  }
986  }
987 
988  return;
989  }
990 
991  /**
992  \brief Routine to calculate Jacobi polynomials, \f$
993  P^{\alpha,\beta}_n(z) \f$, and their first derivative, \f$
994  \frac{d}{dz} P^{\alpha,\beta}_n(z) \f$.
995 
996  \li This function returns the vectors \a poly_in and \a poly_d
997  containing the value of the \f$ n^th \f$ order Jacobi polynomial
998  \f$ P^{\alpha,\beta}_n(z) \alpha > -1, \beta > -1 \f$ and its
999  derivative at the \a np points in \a z[i]
1000 
1001  - If \a poly_in = NULL then only calculate derivatice
1002 
1003  - If \a polyd = NULL then only calculate polynomial
1004 
1005  - To calculate the polynomial this routine uses the recursion
1006  relationship (see appendix A ref [4]) :
1007  \f$ \begin{array}{rcl}
1008  P^{\alpha,\beta}_0(z) &=& 1 \\
1009  P^{\alpha,\beta}_1(z) &=& \frac{1}{2} [ \alpha-\beta+(\alpha+\beta+2)z] \\
1010  a^1_n P^{\alpha,\beta}_{n+1}(z) &=& (a^2_n + a^3_n z)
1011  P^{\alpha,\beta}_n(z) - a^4_n P^{\alpha,\beta}_{n-1}(z) \\
1012  a^1_n &=& 2(n+1)(n+\alpha + \beta + 1)(2n + \alpha + \beta) \\
1013  a^2_n &=& (2n + \alpha + \beta + 1)(\alpha^2 - \beta^2) \\
1014  a^3_n &=& (2n + \alpha + \beta)(2n + \alpha + \beta + 1)
1015  (2n + \alpha + \beta + 2) \\
1016  a^4_n &=& 2(n+\alpha)(n+\beta)(2n + \alpha + \beta + 2)
1017  \end{array} \f$
1018 
1019  - To calculate the derivative of the polynomial this routine uses
1020  the relationship (see appendix A ref [4]) :
1021  \f$ \begin{array}{rcl}
1022  b^1_n(z)\frac{d}{dz} P^{\alpha,\beta}_n(z)&=&b^2_n(z)P^{\alpha,\beta}_n(z)
1023  + b^3_n(z) P^{\alpha,\beta}_{n-1}(z) \hspace{2.2cm} \\
1024  b^1_n(z) &=& (2n+\alpha + \beta)(1-z^2) \\
1025  b^2_n(z) &=& n[\alpha - \beta - (2n+\alpha + \beta)z]\\
1026  b^3_n(z) &=& 2(n+\alpha)(n+\beta)
1027  \end{array} \f$
1028 
1029  - Note the derivative from this routine is only valid for -1 < \a z < 1.
1030  */
1031  void jacobfd(const int np, const double *z, double *poly_in, double *polyd,
1032  const int n, const double alpha, const double beta){
1033  int i;
1034  double zero = 0.0, one = 1.0, two = 2.0;
1035 
1036  if(!np)
1037  return;
1038 
1039  if(n == 0){
1040  if(poly_in)
1041  for(i = 0; i < np; ++i)
1042  poly_in[i] = one;
1043  if(polyd)
1044  for(i = 0; i < np; ++i)
1045  polyd[i] = zero;
1046  }
1047  else if (n == 1){
1048  if(poly_in)
1049  for(i = 0; i < np; ++i)
1050  poly_in[i] = 0.5*(alpha - beta + (alpha + beta + two)*z[i]);
1051  if(polyd)
1052  for(i = 0; i < np; ++i)
1053  polyd[i] = 0.5*(alpha + beta + two);
1054  }
1055  else{
1056  int k;
1057  double a1,a2,a3,a4;
1058  double two = 2.0, apb = alpha + beta;
1059  double *poly, *polyn1,*polyn2;
1060 
1061  if(poly_in){ // switch for case of no poynomial function return
1062  polyn1 = (double *)malloc(2*np*sizeof(double));
1063  polyn2 = polyn1+np;
1064  poly = poly_in;
1065  }
1066  else{
1067  polyn1 = (double *)malloc(3*np*sizeof(double));
1068  polyn2 = polyn1+np;
1069  poly = polyn2+np;
1070  }
1071 
1072  for(i = 0; i < np; ++i){
1073  polyn2[i] = one;
1074  polyn1[i] = 0.5*(alpha - beta + (alpha + beta + two)*z[i]);
1075  }
1076 
1077  for(k = 2; k <= n; ++k){
1078  a1 = two*k*(k + apb)*(two*k + apb - two);
1079  a2 = (two*k + apb - one)*(alpha*alpha - beta*beta);
1080  a3 = (two*k + apb - two)*(two*k + apb - one)*(two*k + apb);
1081  a4 = two*(k + alpha - one)*(k + beta - one)*(two*k + apb);
1082 
1083  a2 /= a1;
1084  a3 /= a1;
1085  a4 /= a1;
1086 
1087  for(i = 0; i < np; ++i){
1088  poly [i] = (a2 + a3*z[i])*polyn1[i] - a4*polyn2[i];
1089  polyn2[i] = polyn1[i];
1090  polyn1[i] = poly [i];
1091  }
1092  }
1093 
1094  if(polyd){
1095  a1 = n*(alpha - beta);
1096  a2 = n*(two*n + alpha + beta);
1097  a3 = two*(n + alpha)*(n + beta);
1098  a4 = (two*n + alpha + beta);
1099  a1 /= a4; a2 /= a4; a3 /= a4;
1100 
1101  // note polyn2 points to polyn1 at end of poly iterations
1102  for(i = 0; i < np; ++i){
1103  polyd[i] = (a1- a2*z[i])*poly[i] + a3*polyn2[i];
1104  polyd[i] /= (one - z[i]*z[i]);
1105  }
1106  }
1107 
1108  free(polyn1);
1109  }
1110 
1111  return;
1112  }
1113 
1114 
1115  /**
1116  \brief Calculate the derivative of Jacobi polynomials
1117 
1118  \li Generates a vector \a poly of values of the derivative of the
1119  \a n th order Jacobi polynomial \f$ P^(\alpha,\beta)_n(z)\f$ at the
1120  \a np points \a z.
1121 
1122  \li To do this we have used the relation
1123  \n
1124  \f$ \frac{d}{dz} P^{\alpha,\beta}_n(z)
1125  = \frac{1}{2} (\alpha + \beta + n + 1) P^{\alpha,\beta}_n(z) \f$
1126 
1127  \li This formulation is valid for \f$ -1 \leq z \leq 1 \f$
1128 
1129  */
1130 
1131  void jacobd(const int np, const double *z, double *polyd, const int n,
1132  const double alpha, const double beta)
1133  {
1134  int i;
1135  double one = 1.0;
1136  if(n == 0)
1137  for(i = 0; i < np; ++i) polyd[i] = 0.0;
1138  else{
1139  //jacobf(np,z,polyd,n-1,alpha+one,beta+one);
1140  jacobfd(np,z,polyd,NULL,n-1,alpha+one,beta+one);
1141  for(i = 0; i < np; ++i) polyd[i] *= 0.5*(alpha + beta + (double)n + one);
1142  }
1143  return;
1144  }
1145 
1146 
1147  /**
1148  \brief Calculate the Gamma function , \f$ \Gamma(n)\f$, for integer
1149  values and halves.
1150 
1151  Determine the value of \f$\Gamma(n)\f$ using:
1152 
1153  \f$ \Gamma(n) = (n-1)! \mbox{ or } \Gamma(n+1/2) = (n-1/2)\Gamma(n-1/2)\f$
1154 
1155  where \f$ \Gamma(1/2) = \sqrt(\pi)\f$
1156  */
1157 
1158  double gammaF(const double x){
1159  double gamma = 1.0;
1160 
1161  if (x == -0.5) gamma = -2.0*sqrt(M_PI);
1162  else if (!x) return gamma;
1163  else if ((x-(int)x) == 0.5){
1164  int n = (int) x;
1165  double tmp = x;
1166 
1167  gamma = sqrt(M_PI);
1168  while(n--){
1169  tmp -= 1.0;
1170  gamma *= tmp;
1171  }
1172  }
1173  else if ((x-(int)x) == 0.0){
1174  int n = (int) x;
1175  double tmp = x;
1176 
1177  while(--n){
1178  tmp -= 1.0;
1179  gamma *= tmp;
1180  }
1181  }
1182  else
1183  fprintf(stderr,"%lf is not of integer or half order\n",x);
1184  return gamma;
1185  }
1186 
1187  /**
1188  \brief Calculate the \a n zeros, \a z, of the Jacobi polynomial, i.e.
1189  \f$ P_n^{\alpha,\beta}(z) = 0 \f$
1190 
1191  This routine is only value for \f$( \alpha > -1, \beta > -1)\f$
1192  and uses polynomial deflation in a Newton iteration
1193  */
1194 
1195  static void Jacobz(const int n, double *z, const double alpha,
1196  const double beta){
1197  int i,j,k;
1198  double dth = M_PI/(2.0*(double)n);
1199  double poly,pder,rlast=0.0;
1200  double sum,delr,r;
1201  double one = 1.0, two = 2.0;
1202 
1203  if(!n)
1204  return;
1205 
1206  for(k = 0; k < n; ++k){
1207  r = -cos((two*(double)k + one) * dth);
1208  if(k) r = 0.5*(r + rlast);
1209 
1210  for(j = 1; j < STOP; ++j){
1211  jacobfd(1,&r,&poly, &pder, n, alpha, beta);
1212 
1213  for(i = 0, sum = 0.0; i < k; ++i) sum += one/(r - z[i]);
1214 
1215  delr = -poly / (pder - sum * poly);
1216  r += delr;
1217  if( fabs(delr) < EPS ) break;
1218  }
1219  z[k] = r;
1220  rlast = r;
1221  }
1222  return;
1223  }
1224 
1225 
1226  /**
1227  \brief Zero and Weight determination through the eigenvalues and eigenvectors of a tridiagonal
1228  matrix from the three term recurrence relationship.
1229 
1230  Set up a symmetric tridiagonal matrix
1231 
1232  \f$ \left [ \begin{array}{ccccc}
1233  a[0] & b[0] & & & \\
1234  b[0] & a[1] & b[1] & & \\
1235  0 & \ddots & \ddots & \ddots & \\
1236  & & \ddots & \ddots & b[n-2] \\
1237  & & & b[n-2] & a[n-1] \end{array} \right ] \f$
1238 
1239  Where the coefficients a[n], b[n] come from the recurrence relation
1240 
1241  \f$ b_j p_j(z) = (z - a_j ) p_{j-1}(z) - b_{j-1} p_{j-2}(z) \f$
1242 
1243  where \f$ j=n+1\f$ and \f$p_j(z)\f$ are the Jacobi (normalized)
1244  orthogonal polynomials \f$ \alpha,\beta > -1\f$( integer values and
1245  halves). Since the polynomials are orthonormalized, the tridiagonal
1246  matrix is guaranteed to be symmetric. The eigenvalues of this
1247  matrix are the zeros of the Jacobi polynomial.
1248  */
1249 
1250  void JacZeros(const int n, double *a, double*b, const double alpha,
1251  const double beta){
1252 
1253  int i,j;
1254  RecCoeff(n,a,b,alpha,beta);
1255 
1256  double **z = new double*[n];
1257  for(i = 0; i < n; i++)
1258  {
1259  z[i] = new double[n];
1260  for(j = 0; j < n; j++)
1261  {
1262  z[i][j] = 0.0;
1263  }
1264  }
1265  for(i = 0; i < n; i++)
1266  {
1267  z[i][i] = 1.0;
1268  }
1269 
1270  // find eigenvalues and eigenvectors
1271  TriQL(n, a, b,z);
1272 
1273  delete[] z;
1274  return;
1275  }
1276 
1277  /**
1278  \brief The routine finds the recurrence coefficients \a a and
1279  \a b of the orthogonal polynomials
1280  */
1281  static void RecCoeff(const int n, double *a, double *b,const double alpha,
1282  const double beta){
1283 
1284  int i;
1285  double apb, apbi,a2b2;
1286 
1287  if(!n)
1288  return;
1289 
1290  // generate normalised terms
1291  apb = alpha + beta;
1292  apbi = 2.0 + apb;
1293 
1294  b[0] = pow(2.0,apb+1.0)*gammaF(alpha+1.0)*gammaF(beta+1.0)/gammaF(apbi); //MuZero
1295  a[0] = (beta-alpha)/apbi;
1296  b[1] = (4.0*(1.0+alpha)*(1.0+beta)/((apbi+1.0)*apbi*apbi));
1297 
1298  a2b2 = beta*beta-alpha*alpha;
1299 
1300  for(i = 1; i < n-1; i++){
1301  apbi = 2.0*(i+1) + apb;
1302  a[i] = a2b2/((apbi-2.0)*apbi);
1303  b[i+1] = (4.0*(i+1)*(i+1+alpha)*(i+1+beta)*(i+1+apb)/
1304  ((apbi*apbi-1)*apbi*apbi));
1305  }
1306 
1307  apbi = 2.0*n + apb;
1308  a[n-1] = a2b2/((apbi-2.0)*apbi);
1309 
1310  }
1311 
1312 
1313  /** \brief QL algorithm for symmetric tridiagonal matrix
1314 
1315  This subroutine is a translation of an algol procedure,
1316  num. math. \b 12, 377-383(1968) by martin and wilkinson, as modified
1317  in num. math. \b 15, 450(1970) by dubrulle. Handbook for
1318  auto. comp., vol.ii-linear algebra, 241-248(1971). This is a
1319  modified version from numerical recipes.
1320 
1321  This subroutine finds the eigenvalues and first components of the
1322  eigenvectors of a symmetric tridiagonal matrix by the implicit QL
1323  method.
1324 
1325  on input:
1326  - n is the order of the matrix;
1327  - d contains the diagonal elements of the input matrix;
1328  - e contains the subdiagonal elements of the input matrix
1329  in its first n-2 positions.
1330  - z is the n by n identity matrix
1331 
1332  on output:
1333 
1334  - d contains the eigenvalues in ascending order.
1335  - e contains the weight values - modifications of the first component
1336  of normalised eigenvectors
1337  */
1338 
1339  static void TriQL(const int n, double *d,double *e, double **z){
1340  int m,l,iter,i,k;
1341  double s,r,p,g,f,dd,c,b;
1342 
1343  double MuZero = e[0];
1344 
1345  // Renumber the elements of e
1346  for(i = 0; i < n-1; i++)
1347  {
1348  e[i] = sqrt(e[i+1]);
1349  }
1350  e[n-1] = 0.0;
1351 
1352 
1353  for (l=0;l<n;l++) {
1354  iter=0;
1355  do {
1356  for (m=l;m<n-1;m++) {
1357  dd=fabs(d[m])+fabs(d[m+1]);
1358  if (fabs(e[m])+dd == dd) break;
1359  }
1360  if (m != l) {
1361  if (iter++ == STOP){
1362  fprintf(stderr,"triQL: Too many iterations in TQLI");
1363  exit(1);
1364  }
1365  g=(d[l+1]-d[l])/(2.0*e[l]);
1366  r=sqrt((g*g)+1.0);
1367  g=d[m]-d[l]+e[l]/(g+sign(r,g));
1368  s=c=1.0;
1369  p=0.0;
1370  for (i=m-1;i>=l;i--) {
1371  f=s*e[i];
1372  b=c*e[i];
1373  if (fabs(f) >= fabs(g)) {
1374  c=g/f;
1375  r=sqrt((c*c)+1.0);
1376  e[i+1]=f*r;
1377  c *= (s=1.0/r);
1378  } else {
1379  s=f/g;
1380  r=sqrt((s*s)+1.0);
1381  e[i+1]=g*r;
1382  s *= (c=1.0/r);
1383  }
1384  g=d[i+1]-p;
1385  r=(d[i]-g)*s+2.0*c*b;
1386  p=s*r;
1387  d[i+1]=g+p;
1388  g=c*r-b;
1389 
1390  // Calculate the eigenvectors
1391  for(k = 0; k < n; k++)
1392  {
1393  f = z[k][i+1];
1394  z[k][i+1] = s*z[k][i] + c*f;
1395  z[k][i] = c*z[k][i] - s*f;
1396  }
1397 
1398  }
1399  d[l]=d[l]-p;
1400  e[l]=g;
1401  e[m]=0.0;
1402  }
1403  } while (m != l);
1404  }
1405 
1406  // order eigenvalues
1407  // Since we only need the first component of the eigenvectors
1408  // to calcualte the weight, we only swap the first components
1409  for(i = 0; i < n-1; ++i){
1410  k = i;
1411  p = d[i];
1412  for(l = i+1; l < n; ++l)
1413  if (d[l] < p) {
1414  k = l;
1415  p = d[l];
1416  }
1417  d[k] = d[i];
1418  d[i] = p;
1419 
1420  double temp = z[0][k];
1421  z[0][k] = z[0][i];
1422  z[0][i] = temp;
1423  }
1424 
1425  // Calculate the weights
1426  for(i =0 ; i < n; i++)
1427  {
1428  e[i] = MuZero*z[0][i]*z[0][i];
1429  }
1430  }
1431 
1432  /**
1433  \brief Calcualtes the Jacobi-kronrod matrix by determining the
1434  \a a and \b coefficients.
1435 
1436  The first \a 3n+1 coefficients are already known
1437 
1438  For more information refer to:
1439  "Dirk P. Laurie, Calcualtion of Gauss-Kronrod quadrature rules"
1440  */
1441  void JKMatrix(int n, double *a, double *b)
1442  {
1443  int i,j,k,m;
1444  // Working storage
1445  int size = (int)floor(n/2.0)+2;
1446  double *s = new double[size];
1447  double *t = new double[size];
1448 
1449  // Initialize s and t to zero
1450  for(i = 0; i < size; i++)
1451  {
1452  s[i] = 0.0;
1453  t[i] = 0.0;
1454  }
1455 
1456  t[1] = b[n+1];
1457  for(m = 0; m <= n-2; m++)
1458  {
1459  double u = 0.0;
1460  for(k = (int)floor((m+1)/2.0); k >= 0; k--)
1461  {
1462  int l = m-k;
1463  u = u+(a[k+n+1]-a[l])*t[k+1] + b[k+n+1]*s[k] - b[l]*s[k+1];
1464  s[k+1] = u;
1465  }
1466 
1467  // Swap the contents of s and t
1468  double *hold = s;
1469  s = t;
1470  t = hold;
1471  }
1472 
1473 
1474  for(j = (int)floor(n/2.0); j >= 0; j--)
1475  {
1476  s[j+1] = s[j];
1477  }
1478 
1479  for(m = n-1; m <= 2*n-3; m++)
1480  {
1481  double u = 0;
1482  for(k = m+1-n; k <= floor((m-1)/2.0); k++)
1483  {
1484  int l = m-k;
1485  j = n-1-l;
1486  u = u-(a[k+n+1]-a[l])*t[j+1] - b[k+n+1]*s[j+1] + b[l]*s[j+2];
1487  s[j+1] = u;
1488  }
1489 
1490  if(m%2 == 0)
1491  {
1492  k = m/2;
1493  a[k+n+1] = a[k] + (s[j+1]-b[k+n+1]*s[j+2])/t[j+2];
1494 
1495  }else
1496  {
1497  k = (m+1)/2;
1498  b[k+n+1] = s[j+1]/s[j+2];
1499  }
1500 
1501 
1502  // Swap the contents of s and t
1503  double *hold = s;
1504  s = t;
1505  t = hold;
1506  }
1507 
1508  a[2*n ] = a[n-1]-b[2*n]*s[1]/t[1];
1509 
1510  }
1511 
1512  /**
1513  \brief
1514  Given a weight function \f$w(t)\f$ through the first \a n+1
1515  coefficients \a a and \a b of its orthogonal polynomials
1516  this routine generates the first \a n recurrence coefficients for the orthogonal
1517  polynomials relative to the modified weight function \f$(t-z)w(t)\f$.
1518 
1519  The result will be placed in the array \a a0 and \a b0.
1520  */
1521 
1522  void chri1(int n, double* a, double* b, double* a0,
1523  double* b0,double z)
1524  {
1525 
1526  double q = ceil(3.0*n/2);
1527  int size = (int)q+1;
1528  if(size < n+1)
1529  {
1530  fprintf(stderr,"input arrays a and b are too short\n");
1531  }
1532  double* r = new double[n+1];
1533  r[0] = z - a[0];
1534  r[1] = z - a[1] - b[1]/r[0];
1535  a0[0] = a[1] + r[1] - r[0];
1536  b0[0] = -r[0]*b[0];
1537 
1538  if(n == 1)
1539  {
1540  delete[] r;
1541  return;
1542  }
1543  int k = 0;
1544  for(k = 1; k < n; k++)
1545  {
1546  r[k+1] = z - a[k+1] - b[k+1]/r[k];
1547  a0[k] = a[k+1] + r[k+1] - r[k];
1548  b0[k] = b[k] * r[k]/r[k-1];
1549  }
1550  delete[] r;
1551 
1552  }
1553 
1554  /**
1555 
1556  \brief
1557 
1558  Calcualte the bessel function of the first kind with complex double input y.
1559  Taken from Numerical Recipies in C
1560 
1561  Returns a complex double
1562  */
1563 
1564 
1565  std::complex<Nektar::NekDouble> ImagBesselComp(int n,std::complex<Nektar::NekDouble> y)
1566  {
1567  std::complex<Nektar::NekDouble> z (1.0,0.0);
1568  std::complex<Nektar::NekDouble> zbes (1.0,0.0);
1569  std::complex<Nektar::NekDouble> zarg;
1570  Nektar::NekDouble tol = 1e-15;
1571  int maxit = 10000;
1572  int i = 1;
1573 
1574  zarg = -0.25*y*y;
1575 
1576  while (abs(z) > tol && i <= maxit){
1577  z = z*(1.0/i/(i+n)*zarg);
1578  if (abs(z) <= tol) break;
1579  zbes = zbes + z;
1580  i++;
1581  }
1582  zarg = 0.5*y;
1583  for (i=1;i<=n;i++){
1584  zbes = zbes*zarg;
1585  }
1586  return zbes;
1587 
1588  }
1589 } // end of namespace
1590 
void Dgj(double *D, const double *z, const int np, const double alpha, const double beta)
Compute the Derivative Matrix and its transpose associated with the Gauss-Jacobi zeros.
Definition: Polylib.cpp:543
#define sign(a, b)
return the sign(b)*a
Definition: Polylib.cpp:16
static void RecCoeff(const int, double *, double *, const double, const double)
The routine finds the recurrence coefficients a and b of the orthogonal polynomials.
Definition: Polylib.cpp:1281
void zwgrjp(double *z, double *w, const int np, const double alpha, const double beta)
Gauss-Radau-Jacobi zeros and weights with end point at z=1.
Definition: Polylib.cpp:157
double hgj(const int i, const double z, const double *zgj, const int np, const double alpha, const double beta)
Compute the value of the i th Lagrangian interpolant through the np Gauss-Jacobi points zgj at the ar...
Definition: Polylib.cpp:749
void Imgrjp(double *im, const double *zgrj, const double *zm, const int nz, const int mz, const double alpha, const double beta)
Interpolation Operator from Gauss-Radau-Jacobi points (including z=1) to an arbitrary distrubtion at ...
Definition: Polylib.cpp:943
void zwglj(double *z, double *w, const int np, const double alpha, const double beta)
Gauss-Lobatto-Jacobi zeros and weights with end point at z=-1,1.
Definition: Polylib.cpp:193
double hgrjp(const int i, const double z, const double *zgrj, const int np, const double alpha, const double beta)
Compute the value of the i th Lagrangian interpolant through the np Gauss-Radau-Jacobi points zgrj at...
Definition: Polylib.cpp:820
void zwlk(double *z, double *w, const int npt, const double alpha, const double beta)
Gauss-Lobatto-Kronrod-Jacobi zeros and weights.
Definition: Polylib.cpp:417
void JacZeros(const int n, double *a, double *b, const double alpha, const double beta)
Zero and Weight determination through the eigenvalues and eigenvectors of a tridiagonal matrix from t...
Definition: Polylib.cpp:1250
void chri1(int, double *, double *, double *, double *, double)
Given a weight function through the first n+1 coefficients a and b of its orthogonal polynomials thi...
Definition: Polylib.cpp:1522
void jacobd(const int np, const double *z, double *polyd, const int n, const double alpha, const double beta)
Calculate the derivative of Jacobi polynomials.
Definition: Polylib.cpp:1131
#define jacobz(n, z, alpha, beta)
zero determination using Newton iteration with polynomial deflation
Definition: Polylib.cpp:60
#define STOP
Maximum number of iterations in polynomial defalation routine Jacobz.
Definition: Polylib.cpp:12
void Imglj(double *im, const double *zglj, const double *zm, const int nz, const int mz, const double alpha, const double beta)
Interpolation Operator from Gauss-Lobatto-Jacobi points to an arbitrary distrubtion at points zm...
Definition: Polylib.cpp:974
void JKMatrix(int, double *, double *)
Calcualtes the Jacobi-kronrod matrix by determining the a and coefficients.
Definition: Polylib.cpp:1441
void Dgrjm(double *D, const double *z, const int np, const double alpha, const double beta)
Compute the Derivative Matrix and its transpose associated with the Gauss-Radau-Jacobi zeros with a z...
Definition: Polylib.cpp:586
void zwgk(double *z, double *w, const int npt, const double alpha, const double beta)
Gauss-Kronrod-Jacobi zeros and weights.
Definition: Polylib.cpp:237
void Imgrjm(double *im, const double *zgrj, const double *zm, const int nz, const int mz, const double alpha, const double beta)
Interpolation Operator from Gauss-Radau-Jacobi points (including z=-1) to an arbitrary distrubtion at...
Definition: Polylib.cpp:913
void Dgrjp(double *D, const double *z, const int np, const double alpha, const double beta)
Compute the Derivative Matrix associated with the Gauss-Radau-Jacobi zeros with a zero at z=1...
Definition: Polylib.cpp:636
double NekDouble
void zwgrjm(double *z, double *w, const int np, const double alpha, const double beta)
Gauss-Radau-Jacobi zeros and weights with end point at z=-1.
Definition: Polylib.cpp:119
NekDouble L
The namespace associated with the the Polylib library (Polylib introduction)
Definition: Polylib.cpp:18
double optdiff(double xl, double xr)
The following function is used to circumvent/reduce "Subtractive Cancellation" The expression 1/dz is...
Definition: Polylib.cpp:23
static void TriQL(const int, double *, double *, double **)
QL algorithm for symmetric tridiagonal matrix.
Definition: Polylib.cpp:1339
static void Jacobz(const int n, double *z, const double alpha, const double beta)
Calculate the n zeros, z, of the Jacobi polynomial, i.e. .
Definition: Polylib.cpp:1195
void zwrk(double *z, double *w, const int npt, const double alpha, const double beta)
Gauss-Radau-Kronrod-Jacobi zeros and weights.
Definition: Polylib.cpp:310
double hglj(const int i, const double z, const double *zglj, const int np, const double alpha, const double beta)
Compute the value of the i th Lagrangian interpolant through the np Gauss-Lobatto-Jacobi points zgrj ...
Definition: Polylib.cpp:855
std::complex< Nektar::NekDouble > ImagBesselComp(int n, std::complex< Nektar::NekDouble > y)
Calcualte the bessel function of the first kind with complex double input y. Taken from Numerical Rec...
Definition: Polylib.cpp:1565
double hgrjm(const int i, const double z, const double *zgrj, const int np, const double alpha, const double beta)
Compute the value of the i th Lagrangian interpolant through the np Gauss-Radau-Jacobi points zgrj at...
Definition: Polylib.cpp:784
#define EPS
Precision tolerance for two points to be similar.
Definition: Polylib.cpp:14
void Dglj(double *D, const double *z, const int np, const double alpha, const double beta)
Compute the Derivative Matrix associated with the Gauss-Lobatto-Jacobi zeros.
Definition: Polylib.cpp:687
void Imgj(double *im, const double *zgj, const double *zm, const int nz, const int mz, const double alpha, const double beta)
Interpolation Operator from Gauss-Jacobi points to an arbitrary distribution at points zm...
Definition: Polylib.cpp:884
double laginterp(double z, int j, const double *zj, int np)
Definition: Polylib.cpp:43
void jacobfd(const int np, const double *z, double *poly_in, double *polyd, const int n, const double alpha, const double beta)
Routine to calculate Jacobi polynomials, , and their first derivative, .
Definition: Polylib.cpp:1031
double gammaF(const double)
Calculate the Gamma function , , for integer values and halves.
Definition: Polylib.cpp:1158
void zwgj(double *z, double *w, const int np, const double alpha, const double beta)
Gauss-Jacobi zeros and weights.
Definition: Polylib.cpp:91