📄 adaptivelobatto.m
字号:
function [Q fcnEvals iter] = adaptiveLobatto(fcn, a, b, varargin)% adaptiveLobatto - Numerically evaluate integral, adaptive Lobatto quadrature. %% function [Q fcnEvals iter] = adaptiveLobatto(fcn, a, b, varargin)%% (c) Matthias Conrad and Nils Papenberg (2007-08-03)% % Authors: % Matthias Conrad (e-mail: conrad@tiaco.de)% Nils Papenberg (e-mail: papenber@math.uni-luebeck.de)%% Version:% Release date: 2008-08-12 Version: 1.2% MATLAB Version 7.5.0.338 (R2007b)%% Description:% The adaptive Lobatto algorithm programmed in an iterative not recursive% manner%% Input arguments:% fcn - function to be integrated % a - first point of interval% b - final point of interval% #varargin - further options of algorithm% tol - tolerance accuracy of quadrature [ 1e-6 ]% parts - initial number of partitions [ 2 ]% maxFcnEvals - maximal number of function evaluations allowed [ 20000 ]% maxParts - maximal number of partitions allowed [ 8000 ]%% Output arguments:% Q - numerical integral of function fcn on [a,b]% fcnEvals - number of function evaluations% iter - number of iterations%% Details:% This function behavior is similar to of Matlab integrated function "quadv".% % Example:% Q = adaptiveLobatto(@(x) [-cos(50*x); sin(x)], 0, pi, 'tol', 1e-6)%% References:% [1] Gander, W. & Gautschi, W. Adaptive Quadrature - Revisited% Eidgenoessische technische Hochschule Zuerich, 2000.% [2] Conrad, M. Iterative Adaptive Simpson and Lobatto Quadrature in Matlab,% Mathematics and Computer Science, Emory University, TR-2008-012, 2008.% check scalar limits of intervalif ~isscalar(a) || ~isscalar(b) error('Matlab:adaptiveLobatto:Limits',... 'The limits of integration must be scalars.');end% default valuestol = 1e-6; parts = 2; maxFcnEvals = 20000; maxParts = 8000;% rewrite default options if neededfor j = 1 : length(varargin) / 2 eval([varargin{2 * j - 1},'=varargin{',int2str(2 * j),'};']);end% initial values, termination constant, parts of interval and integral valuem = parts; parts = 4 * parts + 1; Q = 0;minH = eps(b - a) / 1024; maxResolution = 0; iter = 0; poleWarning = 0;% width constantsalpha = sqrt(2/3); beta = sqrt(1/5);% check if interval has infinite boundaries, in case substitute functionif ~isfinite(a) || ~isfinite(b) warning('Matlab:adaptiveLobatto:infiniteInterval',... 'The integral has an infinite interval; proceed with a substitution of function on finite interval.') if ~isfinite(a) && isfinite(b) [Q fcnEvals iter] = adaptiveLobatto(fcn, 0, b, varargin); fcn = @(t) infiniteLeft(t, fcn); a = 0; b = 1; elseif isfinite(a) && ~isfinite(b) [Q fcnEvals iter] = adaptiveLobatto(fcn, a, 0, varargin); fcn = @(t) infiniteRight(t, fcn); a = 0; b = 1; else fcn = @(t) infiniteBoth(t, fcn); a = - pi / 2; b = pi / 2; endend% initialize gridt = linspace(a, b, m + 1);A = t(1:end-1); B = t(2:end);% widths and midpoints of intervalsH = diff(t)/2; J = (A + B) / 2;% grid pointsF = -alpha * H + J; D = -beta * H + J; C = J;E = beta * H + J; G = alpha * H + J;t = [A; F; D; C; E; G; B]; t = t(:);% function evaluationsy = fcn([A, F, D, C, E, G, B]); fcnEvals = 7 * m;% avoid infinities at start point of intervalif any(~isfinite(y(:,1))) y(:,1) = fcn(a + eps(superiorfloat(a,b)) * (b - a)); fcnEvals = fcnEvals + 1; poleWarning = 1;end% avoid infinities at end point of intervalif any(~isfinite(y(:, end))) y(:, end) = fcn(b - eps(superiorfloat(a,b)) * (b - a)); fcnEvals = fcnEvals + 1; poleWarning = 1;end% poles at initial pointsif ~isempty(find(~isfinite(max(abs(y))))), poleWarning = 1; end% hand over function valuesyA = y(:, 1 : m); yF = y(:, m+1 : 2*m); yD = y(:, 2*m+1 : 3*m);yC = y(:, 3*m+1 : 4*m); yE = y(:, 4*m+1 : 5*m); yG = y(:, 5*m+1 : 6*m);yB = y(:, 6*m+1 : end);% dimension of parallel integrationn = size(yA,1);% adaptive Lobatto iterationwhile 1 % number of iteration iter = iter + 1; % four point Lobatto formula Q1 = kron(H, ones(n,1)) / 6 .* (yA + 5 * (yD + yE) + yB); % seven point Kronrod formula Q2 = kron(H, ones(n,1)) / 1470 .* (77 * (yA + yB) + 432 * (yF + yG) + 625 * (yD + yE) + 672 * yC); % difference of Lobatto formulas diffQ = Q2 - Q1; diffQ(find(isnan(diffQ))) = 0; % intervals which do not fulfill termination criterion idx = find(max(abs(diffQ), [], 1) > tol); % intervals fulfill termination criterion idxQ = setdiff(1:length(A), idx); % check stop criterions STOP1 = isempty(idx); % check regular termination STOP2 = fcnEvals > maxFcnEvals; % check maximal function evaluations STOP3 = 5 * length(idx) > maxParts; % check maximal partition % regular termination if STOP1 Q = Q + sum(Q2, 2); break end % check if maximal resolution reached idxH = find(abs(H) < minH); if ~isempty(idxH) Q = Q + sum(Q2(idxH), 2); idx = setdiff(idx, idxH); idxQ = setdiff(idxQ, idxH); maxResolution = 1; % termination criterion if isempty(idx), break, end end % maximal function evaluations reached if STOP2 warning('Matlab:adaptiveLobatto:MaxEvaluations',... 'The maximal number of function evaluations reached; singularity likely.') Q = Q + sum(Q2, 2); break end % maximal partition reached if STOP3 warning('Matlab:adaptiveLobatto:parts',... 'The maximal number of parts reached.') Q = Q + sum(Q2, 2); break end % update quadrature value Q = Q + sum(Q2(:,idxQ) + diffQ(:,idxQ) / 15, 2); % number of intervals m = 6 * length(idx); % initialize t t = zeros(1, 6 * length(idx)); % hand over new start points A t(1:6:end) = A(idx); t(2:6:end) = F(idx); t(3:6:end) = D(idx); t(4:6:end) = C(idx); t(5:6:end) = E(idx); t(6:6:end) = G(idx); A = t; % hand over new end points B t(1:6:end) = F(idx); t(2:6:end) = D(idx); t(3:6:end) = C(idx); t(4:6:end) = E(idx); t(5:6:end) = G(idx); t(6:6:end) = B(idx); B = t; y = zeros(n, 6 * length(idx)); % hand over new start values A y(:,1:6:end) = yA(:,idx); y(:,2:6:end) = yF(:,idx); y(:,3:6:end) = yD(:,idx); y(:,4:6:end) = yC(:,idx); y(:,5:6:end) = yE(:,idx); y(:,6:6:end) = yG(:,idx); yA = y; % hand over new end values B y(:,1:6:end) = yF(:,idx); y(:,2:6:end) = yD(:,idx); y(:,3:6:end) = yC(:,idx); y(:,4:6:end) = yE(:,idx); y(:,5:6:end) = yG(:,idx); y(:,6:6:end) = yB(:,idx); yB = y; % widths and midpoints of intervals H = (B - A) / 2; J = (A + B) / 2; % calculate new mid points F = -alpha * H + J; D = -beta * H + J; C = J; E = beta * H + J; G = alpha * H + J; % function evaluations y = fcn([F, D, C, E, G]); fcnEvals = fcnEvals + 5 * m; % poles at new points if ~isempty(find(~isfinite(max(abs(y))))), poleWarning = 1; end % hand over new midpoint values of F D C E and G yF = y(:, 1 : m); yD = y(:, m+1 : 2*m); yC = y(:, 2*m+1 : 3*m); yE = y(:, 3*m+1 : 4*m); yG = y(:, 4*m+1 : 5*m);end% display warningsif any(~isfinite(Q)) warning('Matlab:adaptiveLobatto:Infinite',... 'The Quadrature of the function reached infinity or is Not-a-Number.')endif maxResolution warning('Matlab:adaptiveLobatto:MaxResolution',... 'The maximal resolution of partial interval reached; singularity likely.')endif poleWarning warning('Matlab:adaptiveLobatto:PoleDetection',... 'A detection of a pole; singularity likely.')endreturn% substitute function interval [-inf, 0] on [0, 1]function f = infiniteLeft(t, fcn)f = fcn(log(t));f = f ./ kron(ones(size(f,1),1), t);return% substitute function interval [0, inf] on [0, 1]function f = infiniteRight(t, fcn)f = fcn(-log(t));f = f ./ kron(ones(size(f,1),1), t);return% substitute function interval [-inf, inf] on [-pi / 2, pi / 2]function f = infiniteBoth(t, fcn)f = fcn(tan(t));f = f ./ kron(ones(size(f,1),1), cos(t).^2);return
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -