source: MML/trunk/machine/SOLEIL/common/toolbox/quadgr/quadgr.m

Last change on this file was 17, checked in by zhangj, 10 years ago

To have a stable version on the server.

  • Property svn:executable set to *
File size: 4.3 KB
Line 
1function [Q,err] = quadgr(fun,a,b,tol)
2%QUADGR Gauss-Legendre quadrature with Richardson extrapolation.
3%   [Q,ERR] = QUADGR(FUN,A,B,TOL) approximates the integral of a function
4%   FUN from A to B with an absolute error tolerance TOL. FUN is a function
5%   handle and must accept vector arguments. TOL is 1e-6 by default. Q is
6%   the integral approximation and ERR is an estimate of the absolute error.
7%
8%   QUADGR uses a 12-point Gauss-Legendre quadrature. The error estimate is
9%   based on successive interval bisection. Richardson extrapolation
10%   accelerates the convergence for some integrals, especially integrals
11%   with endpoint singularities.
12%
13%   Examples:
14%     Q = quadgr(@(x) log(x),0,1)
15%     [Q,err] = quadgr(@(x) exp(x),0,9999i*pi)
16%     [Q,err] = quadgr(@(x) sqrt(4-x.^2),0,2,1e-12)
17%     [Q,err] = quadgr(@(x) x.^-0.75,0,1)
18%     [Q,err] = quadgr(@(x) 1./sqrt(1-x.^2),-1,1)
19%     [Q,err] = quadgr(@(x) exp(-x.^2),-inf,inf,1e-9) % sqrt(pi)
20%     [Q,err] = quadgr(@(x) cos(x).*exp(-x),0,inf,1e-9)
21%
22%   See also QUAD, QUADGK
23
24%   Author: jonas.lundgren@saabgroup.com, 2009.
25
26if nargin < 3, help quadgr, return, end
27if nargin < 4, tol = 1e-6; end
28
29% Order limits (required if infinite limits)
30if a == b
31    Q = b - a;
32    err = b - a;
33    return
34elseif a > b
35    reverse = true;
36    atmp = a;
37    a = b;
38    b = atmp;
39else
40    reverse = false;
41end
42
43% Infinite limits
44if isinf(a) || isinf(b)
45    % Check real limits
46    if ~isreal(a) || ~isreal(b) || isnan(a) || isnan(b)
47        error('quadgr:inflim','Infinite intervals must be real.')
48    end
49    % Change of variable
50    if isfinite(a) && isinf(b)
51        % a to inf
52        fun1 = @(t) fun(a + t./(1-t))./(1-t).^2;
53        [Q,err] = quadgr(fun1,0,1,tol);
54    elseif isinf(a) && isfinite(b)
55        % -inf to b
56        fun2 = @(t) fun(b + t./(1+t))./(1+t).^2;
57        [Q,err] = quadgr(fun2,-1,0,tol);
58    else % -inf to inf
59        fun1 = @(t) fun(t./(1-t))./(1-t).^2;
60        fun2 = @(t) fun(t./(1+t))./(1+t).^2;
61        [Q1,err1] = quadgr(fun1,0,1,tol/2);
62        [Q2,err2] = quadgr(fun2,-1,0,tol/2);
63        Q = Q1 + Q2;
64        err = err1 + err2;
65    end
66    % Reverse direction
67    if reverse
68        Q = -Q;
69    end
70    return
71end
72
73% Gauss-Legendre quadrature (12-point)
74xq = [0.12523340851146894; 0.36783149899818018; 0.58731795428661748; ...
75      0.76990267419430469; 0.9041172563704748; 0.98156063424671924];
76wq = [0.24914704581340288, 0.23349253653835478, 0.20316742672306584, ...
77      0.16007832854334636, 0.10693932599531818, 0.047175336386511842];
78xq = [xq; -xq];
79wq = [wq, wq];
80nq = length(xq);
81
82% Initiate vectors
83maxit = 17;                 % Max number of iterations
84Q0 = zeros(maxit,1);            % Quadrature
85Q1 = zeros(maxit,1);            % First Richardson extrapolation
86Q2 = zeros(maxit,1);            % Second Richardson extrapolation
87
88% One interval
89hh = (b - a)/2;             % Half interval length
90x = (a + b)/2 + hh*xq;      % Nodes
91% Quadrature
92Q0(1) = hh*wq*fun(x);
93
94% Successive bisection of intervals
95for k = 2:maxit
96   
97    % Interval bisection
98    hh = hh/2;
99    x = [x + a; x + b]/2;
100    % Quadrature
101    Q0(k) = hh*wq*sum(reshape(fun(x),nq,[]),2);
102   
103    % Richardson extrapolation
104    if k >= 5
105        Q1(k) = richardson(Q0,k);
106        Q2(k) = richardson(Q1,k);
107    elseif k >= 3
108        Q1(k) = richardson(Q0,k);
109    end
110   
111    % Estimate absolute error
112    if k >= 6
113        Qv = [Q0(k), Q1(k), Q2(k)];
114        Qw = [Q0(k-1), Q1(k-1), Q2(k-1)];
115    elseif k >= 4
116        Qv = [Q0(k), Q1(k)];
117        Qw = [Q0(k-1), Q1(k-1)];
118    else
119        Qv = Q0(k);
120        Qw = Q0(k-1);
121    end
122    [err,j] = min(abs(Qv - Qw));
123    Q = Qv(j);
124   
125    % Convergence
126    if err < tol || ~isfinite(Q)
127        break;
128    end
129   
130end
131
132% Convergence check
133if ~isfinite(Q)
134    warning('quadgr:infnan','Integral approximation is Infinite or NaN.')
135elseif err > tol
136    warning('quadgr:maxiter','Max number of iterations reached without convergence.')
137end
138
139% The error estimate should not be zero
140err = err + 2*eps(Q);
141% Reverse direction
142if reverse
143        Q = -Q;
144end
145
146% disp([Q0 Q1 Q2])
147
148%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149function R = richardson(Q,k)
150% Richardson extrapolation with parameter estimation
151c = real((Q(k-1)-Q(k-2))/(Q(k)-Q(k-1))) - 1;
152% The lower bound 0.07 admits the singularity x.^-0.9
153c = max(c,0.07);
154R = Q(k) + (Q(k) - Q(k-1))/c;
Note: See TracBrowser for help on using the repository browser.