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

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')