forked from kilianv/CoastSat_WRL
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
5.2 KiB
Matlab
214 lines
5.2 KiB
Matlab
function [res,fval,it] = muller (f,Z0,itmax,ztol,ftol,option)
|
|
% MULLER find a zero of a real or complex function Y = F(Z)
|
|
%
|
|
% Syntax:
|
|
%
|
|
% RES = MULLER (F,Z0) find the zero of a complex or real function
|
|
% 'F' (either an anonymous function or .m function) using three initial
|
|
% guesses contained in the vector Z0. Muller takes the function F and
|
|
% evaluetes it at each initial point using feval. F doesn't need to be
|
|
% vectorized.
|
|
% The initial guesses can be real or complex numbers close to the zero,
|
|
% bracketing the zero is not necessary. Parameters ITMAX, ZTOL and
|
|
% FTOL are set by default to 1000, 1e-5 and 1e-5, respectively.
|
|
%
|
|
% RES = MULLER (F,Z0,ITMAX) the maximum number of iterations is set
|
|
% equal to ITMAX. ZTOL and FTOL are set by default with the values mentioned
|
|
% above.
|
|
%
|
|
% RES = MULLER (F,Z0,ITMAX,ZTOL) ZTOL is used as a stopping
|
|
% criterion. If the absolute difference between the values of Z found in
|
|
% the two latest iterations is less than ZTOL, the program is stopped. FTOL
|
|
% is set by default with the value mentioned above.
|
|
%
|
|
% RES = MULLER (F,Z0,ITMAX,ZTOL,FTOL) FTOL is used as a stopping
|
|
% criterion. If the value of the function F at the Z found in the last
|
|
% iteration is less than FTOL, the program is stopped.
|
|
%
|
|
% RES = MULLER (F,Z0,ITMAX,ZTOL,FTOL,'both') indicate that both
|
|
% criteria ZTOL and FTOL must be satisfied simultaneously. By default,
|
|
% MULLER stops if one of the two criteria is fulfilled.
|
|
%
|
|
% [RES,FVAL] = MULLER (F,Z0,...) return the value of the function
|
|
% F at the Z found in the last iteration.
|
|
%
|
|
% [RES,FVAL,IT] = MULLER (F,Z0,...) return the number of iterations
|
|
% used to find the zero.
|
|
%
|
|
% Example 1:
|
|
% myf = @(x) (x-1)^3;
|
|
%
|
|
% muller(myf,[0 0.1 0.2],[],[],[],'both')
|
|
% ans =
|
|
% 1.0000 + 0.0000i
|
|
%
|
|
% Example 2:
|
|
%
|
|
% [res,fval,it] = muller2('cosh',[0 0.1 0.2],[],[],[],'both')
|
|
%
|
|
% res =
|
|
% 0.0000 + 1.5708i
|
|
%
|
|
% fval =
|
|
% 5.5845e-012 + 3.0132e-012i
|
|
%
|
|
% it =
|
|
% 5
|
|
%
|
|
% Method taken from:
|
|
% Numerical Recipes: The art of scientific computing
|
|
% W.H. Press; B.P. Flannery; S.A. Teukolsky; W.T. Vetterling
|
|
% 1986
|
|
%
|
|
% Thanks to John D'Errico for his helpfull review.
|
|
%
|
|
% Written by Daniel H. Cortes
|
|
% MAE Department, West Virginia University
|
|
% March, 2008.
|
|
%
|
|
|
|
|
|
%=================================================
|
|
% Checking proper values of the input parameters
|
|
%=================================================
|
|
|
|
|
|
if nargin > 6
|
|
error ('Too many arguments.')
|
|
elseif nargin < 2
|
|
error('Too few arguments.')
|
|
end
|
|
|
|
if nargin < 6
|
|
opt = 1;
|
|
elseif ischar(option) == 1
|
|
if size(option,2) == 4
|
|
if sum(option == 'both') == 4
|
|
opt = 2;
|
|
else
|
|
error ('Option parameter must be *both*.')
|
|
end
|
|
else
|
|
error ('Option parameter must be *both*.')
|
|
end
|
|
else
|
|
error ('Option parameter must be a character array (string).')
|
|
end
|
|
|
|
|
|
if nargin < 5
|
|
ftol = 1e-5;
|
|
elseif isnumeric(ftol) ~= 1
|
|
error ('FTOL must be a numeric argument.')
|
|
elseif isempty(ftol) == 1
|
|
ftol = 1e-5;
|
|
elseif size(ftol,1) ~= 1 || size(ftol,2) ~= 1
|
|
error ('FTOL cannot be an array')
|
|
end
|
|
|
|
|
|
if nargin < 4
|
|
ztol = 1e-5;
|
|
elseif isnumeric(ztol) ~= 1
|
|
error ('ZTOL must be a numeric argument.')
|
|
elseif isempty(ztol) == 1
|
|
ztol = 1e-5;
|
|
elseif size(ztol,1) ~= 1 || size(ztol,2) ~= 1
|
|
error ('ZTOL cannot be an array.')
|
|
end
|
|
|
|
|
|
if nargin < 3
|
|
itmax = 1000;
|
|
elseif isnumeric(itmax) ~= 1
|
|
error ('ITMAX must be a numeric argument.')
|
|
elseif isempty(itmax) == 1
|
|
itmax = 1000;
|
|
elseif size(itmax,1) ~= 1 || size(itmax,2) ~= 1
|
|
error ('ITMAX cannot be an array.')
|
|
end
|
|
|
|
|
|
if isnumeric(Z0) ~= 1
|
|
error ('Z0 must be a vector of three numeric arguments.')
|
|
elseif isempty(Z0) == 1 || length(Z0) ~= 3 || min(size(Z0)) ~= 1
|
|
error ('Z0 must be a vector of length 3 of either complex or real arguments.')
|
|
end
|
|
|
|
if Z0(1)==Z0(2) || Z0(1)==Z0(3) || Z0(2)==Z0(3)
|
|
error('The initial guesses must be different')
|
|
end
|
|
|
|
%=============================
|
|
% Begining of Muller's method
|
|
%=============================
|
|
|
|
z0 = Z0(1);
|
|
z1 = Z0(2);
|
|
z2 = Z0(3);
|
|
|
|
y0 = feval ( f, z0);
|
|
y1 = feval ( f, z1);
|
|
y2 = feval ( f, z2);
|
|
|
|
for it = 1:itmax
|
|
q = (z2 - z1)/(z1 - z0);
|
|
A = q*y2 - q*(1+q)*y1 + q^2*y0;
|
|
B = (2*q + 1)*y2 - (1 + q)^2*y1 + q^2*y0;
|
|
C = (1 + q)*y2;
|
|
|
|
if ( A ~= 0 )
|
|
|
|
disc = B^2 - 4*A*C;
|
|
|
|
den1 = ( B + sqrt ( disc ) );
|
|
den2 = ( B - sqrt ( disc ) );
|
|
|
|
if ( abs ( den1 ) < abs ( den2 ) )
|
|
z3 = z2 - (z2 - z1)*(2*C/den2);
|
|
else
|
|
z3 = z2 - (z2 - z1)*(2*C/den1);
|
|
end
|
|
|
|
elseif ( B ~= 0 )
|
|
z3 = z2 - (z2 - z1)*(2*C/B);
|
|
else
|
|
warning('Muller Method failed to find a root. Last iteration result used as an output. Result may not be accurate')
|
|
res = z2;
|
|
fval = y2;
|
|
return
|
|
end
|
|
|
|
y3 = feval ( f, z3);
|
|
|
|
if opt == 1
|
|
if ( abs (z3 - z2) < ztol || abs ( y3 ) < ftol )
|
|
res = z3;
|
|
fval = y3;
|
|
return
|
|
end
|
|
else
|
|
if ( abs (z3 - z2) < ztol && abs ( y3 ) < ftol )
|
|
res = z3;
|
|
fval = y3;
|
|
return
|
|
end
|
|
end
|
|
|
|
z0 = z1;
|
|
z1 = z2;
|
|
z2 = z3;
|
|
|
|
y0 = y1;
|
|
y1 = y2;
|
|
y2 = y3;
|
|
|
|
end
|
|
|
|
res = z2;
|
|
fval = y2;
|
|
%warning('Maximum number of iterations reached. Result may not be accurate')
|
|
|
|
|
|
|