SDDSlib
Loading...
Searching...
No Matches
gaussQuad.c
Go to the documentation of this file.
1/**
2 * @file gaussQuad.c
3 * @brief Implements recursive Gaussian quadrature for numerical integration.
4 *
5 * This file contains the implementation of the recursive Gaussian quadrature
6 * technique for integrating functions numerically. The primary function
7 * `gaussianQuadrature` divides the integration interval into panels and
8 * recursively refines the estimate to achieve the desired error tolerance.
9 *
10 * @copyright
11 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
12 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
13 *
14 * @license
15 * This file is distributed under the terms of the Software License Agreement
16 * found in the file LICENSE included with this distribution.
17 *
18 * @author M. Borland, R. Soliday
19 */
20
21#include <math.h>
22#include "mdb.h"
23
24#define _CGQ .57735026918962576451
25#define gauss_quad(fn, z, a, w) (((*fn)(z + a) + (*fn)(a - z)) * w)
26
27#define MAXSTACK 16384
28
29/**
30 * @brief Integrate a function using recursive Gaussian quadrature.
31 *
32 * Performs numerical integration of the specified function over the interval [a, b]
33 * using a recursive Gaussian quadrature technique. The interval is initially divided
34 * into `n` panels, and each panel is recursively subdivided until the desired
35 * fractional error `err` is achieved.
36 *
37 * @param fn Pointer to the function to be integrated.
38 * @param a Lower limit of integration.
39 * @param b Upper limit of integration.
40 * @param n Initial number of panels to divide the interval into.
41 * @param err Fractional error permissible on any quadrature.
42 * @param result Pointer to a double where the result of the integration will be stored.
43 * @return The total number of function evaluations performed, or -1 if an error occurs.
44 */
46 double (*fn)(), /* pointer to function to be integrated */
47 double a, double b, /* upper, lower limits of integration */
48 long n, /* number of panels to start with */
49 double err, /* fractional error permissible on any quadrature */
50 double *result) {
51 register long s; /* stack pointer for panel limits */
52 double ave, i0, i1, i2, i3, idiv;
53 long totalEvals;
54 double d_ab, i_tot, d_ab2;
55 double ab, z, width;
56 /* stacks of upper,lower limits, and integral values from two
57 * point quadratures on each interval */
58 double a_stack[MAXSTACK];
59 double b_stack[MAXSTACK];
60 double i_stack[MAXSTACK];
61
62 if (n > MAXSTACK)
63 return -1;
64
65 d_ab = (b - a) / n;
66 d_ab2 = d_ab / 2;
67 totalEvals = 0;
68 for (s = 0; s < n; s++) {
69 b = b_stack[s] = (a_stack[s] = a) + d_ab;
70 ave = a + d_ab2;
71 z = d_ab2 * _CGQ;
72 i_stack[s] = gauss_quad(fn, z, ave, d_ab2);
73 totalEvals += 2;
74 a = b;
75 }
76
77 s = n - 1;
78 i_tot = 0;
79 while (s >= 0) {
80 if (s == MAXSTACK)
81 return -1;
82 a = a_stack[s];
83 b = b_stack[s];
84 ab = (a + b) / 2;
85 i0 = i_stack[s];
86
87 ave = (a + ab) / 2;
88 z = (width = (ab - a) / 2) * _CGQ;
89 i1 = gauss_quad(fn, z, ave, width);
90 totalEvals += 2;
91
92 ave = (ab + b) / 2;
93 z = (width = (b - ab) / 2) * _CGQ;
94 i2 = gauss_quad(fn, z, ave, width);
95 totalEvals += 2;
96
97 i3 = idiv = i1 + i2;
98 if (i3 == 0)
99 idiv = i0;
100 if (idiv != 0) {
101 if (fabs((i3 - i0) / idiv) > err) {
102 b_stack[s] = ab;
103 i_stack[s] = i1;
104 a_stack[++s] = ab;
105 b_stack[s] = b;
106 i_stack[s] = i2;
107 } else {
108 i_tot += i3;
109 s--;
110 }
111 } else {
112 i_tot += i3;
113 s--;
114 }
115 }
116 *result = i_tot;
117 return totalEvals;
118}
long gaussianQuadrature(double(*fn)(), double a, double b, long n, double err, double *result)
Integrate a function using recursive Gaussian quadrature.
Definition gaussQuad.c:45