OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
integrate.cpp
Go to the documentation of this file.
1 /* integration.C
2  integration routines using Rombergs method
3 
4  NUMERICAL RECIPES IN C: THE ART OF SCIENTIFIC COMPUTING (ISBN 0-521-43108-5)
5 
6  Revision history
7  Date Description Programmer
8  ------------ -------------------------------------------- ------------
9  10/03/2006 Copied from "numerical recipies" Rene Bakker
10 
11 */
12 
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <math.h>
16 
19 
20 /* internal functions
21  ====================================================================== */
22 
23 /* vector
24  allocate an array of doubles [0..n-1] and check memory */
25 static double *vector(int n) {
26  double *b;
27 
28  b = (double *) malloc(sizeof(double) * n);
29  if(!b) {
30  writeBetError("Insufficient memory malloc bytes (rk.C)"); //,sizeof(double)*n);
31  }
32  return b;
33 } /* vector */
34 
35 #define FUNC(x) ((*func)(x))
36 
37 /* tranzd()
38  This routine computes the nth stage of refinement of an extended
39  trapezoidal rule. func is input as a pointer to the function to
40  be integrated between limits a and b, also input. When called with
41  n=1, the routine returns the crudest estimate of integral a->b f(x)dx.
42  Subsequent calls with n=2,3,... (in that sequential order) will improve
43  the accuracy by adding 2n-2 additional interior points.
44 */
45 static double trapzd(double(*func)(double), double a, double b, int n) {
46  double x, tnm, sum, del;
47  static double s;
48  int it, j;
49 
50  if(n == 1) {
51  return (s = 0.5 * (b - a) * (FUNC(a) + FUNC(b)));
52  } else {
53  for(it = 1, j = 1; j < n - 1; j++) it <<= 1;
54  tnm = it;
55  del = (b - a) / tnm;
56  x = a + 0.5 * del;
57  for(sum = 0.0, j = 1; j <= it; j++, x += del) sum += FUNC(x);
58  s = 0.5 * (s + (b - a) * sum / tnm);
59  return s;
60  }
61 } /* trapzd() */
62 
63 #undef FUNC
64 
65 /* polint
66  Given arrays xa[1..n] and ya[1..n], and given a value x,
67  this routine returns a value y, and an error estimate dy.
68  If P(x) is the polynomial of degree N - 1 such that
69  P(xa[i]) = ya[i], i = 1,..n, then the returned value y = P(x).
70  */
71 static void polint
72 (
73  double xa[], double ya[], int n,
74  double x, double *y, double *dy) {
75  int i, m, ns = 1;
76  double den, dif, dift, ho, hp, w;
77  double *c, *d;
78 
79  dif = fabs(x - xa[1]);
80  c = vector(n + 1);
81  d = vector(n + 1);
82  for(i = 1; i <= n; i++) {
83  if((dift = fabs(x - xa[i])) < dif) {
84  ns = i;
85  dif = dift;
86  }
87  c[i] = ya[i];
88  d[i] = ya[i];
89  }
90  *y = ya[ns--];
91  for(m = 1; m < n; m++) {
92  for(i = 1; i <= n - m; i++) {
93  ho = xa[i] - x;
94  hp = xa[i+m] - x;
95  w = c[i+1] - d[i];
96  if((den = ho - hp) == 0.0) {
97  int j;
98 
99  fprintf(stderr, "Polint: n=%d, i=%d\n", n, i);
100  for(j = 0; j < n; j++) fprintf(stderr, "%5d %20.12e %20.12e\n", j, xa[j], ya[j]);
101  writeBetError("Error in routine polint (singular point)");
102  }
103  den = w / den;
104  d[i] = hp * den;
105  c[i] = ho * den;
106  }
107  *y += (*dy = (2 * ns < (n - m) ? c[ns+1] : d[ns--]));
108  }
109  free(d);
110  free(c);
111 } /* polint() */
112 
113 /* external functions
114  ======================================================================= */
115 
116 #define JMAX 30
117 #define JMAXP (JMAX+1)
118 #define K 5
119 
120 /* qromb()
121  Returns the integral of the function func from a to b.
122  Integration is performed by Romberg's method of order 2K,
123  where, e.g., K=2 is Simpson's rule.
124 */
125 double qromb
126 (
127  double(*func)(double),
128  double a, double b,
129  double eps) {
130  double aeps, ss, dss;
131  double s[JMAXP+1], h[JMAXP+1];
132  int j;
133 
134  aeps = fabs(eps);
135  h[1] = 1.0;
136  for(j = 1; j <= JMAX; j++) {
137  s[j] = trapzd(func, a, b, j);
138  if(j >= K) {
139  polint(&h[j-K], &s[j-K], K, 0.0, &ss, &dss);
140  if(fabs(dss) < aeps * fabs(ss)) return ss;
141  }
142  s[j+1] = s[j];
143  h[j+1] = 0.25 * h[j];
144  }
145  //writeBetError(errModeAll,errFatal,"Too many steps in routine qromb (%d) [%le/%le]",
146  // JMAX,fabs(dss),fabs(ss));
147  writeBetError("Too many steps in routine gromb");
148  return 0.0;
149 }
150 #undef JMAX
151 #undef JMAXP
152 #undef K
double qromb(double(*func)(double), double a, double b, double eps)
Definition: integrate.cpp:126
void writeBetError(std::string err)
Definition: BetError.cpp:36
PETE_TUTree< FnFabs, typename T::PETE_Expr_t > fabs(const PETE_Expr< T > &l)
Definition: PETE.h:815
T::PETE_Expr_t::PETE_Return_t sum(const PETE_Expr< T > &expr)
Definition: PETE.h:1213
#define JMAX
Definition: integrate.cpp:116
#define FUNC(x)
Definition: integrate.cpp:35
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:52
#define K
Definition: integrate.cpp:118
#define JMAXP
Definition: integrate.cpp:117