function [tout,yout,varargout] = ode45(odefile,tspan,y0,options,varargin)
%[tout,yout] = ode45('ypfun', tspan, y0, options)
%这里字符串ypfun是用以表示f(t, y)的M文件名,
%tspan=[t0, tfinal]表示自变量初值t0和终值tf
% y0表示初值向量y0,可选参数options为用odeset设置精度等参数。
% 输出列向量tout表示节点 (t0 , t1 , … , tn)'
% 输出矩阵yout 表示数值解,每一列对应y的一个分量
% 若无输出参数,则作出图形。
%例 解微分方程
% y' = y-2t/y, y(0)=1, 0<t<1
% 先写M函数quadeg5fun.m
% function f=quadeg5fun(t,y)
% f=y-2*t./y;
% f=f(:); %保证f为一个列向量
% 再用
% [t,y]=ode45('quadeg5fun',[0,1],1)
% plot(t,y);
%
%ODE45 Solve non-stiff differential equations, medium order method.
% [T,Y] = ODE45('F',TSPAN,Y0) with TSPAN = [T0 TFINAL] integrates the
% system of differential equations y' = F(t,y) from time T0 to TFINAL with
% initial conditions Y0. 'F' is a string containing the name of an ODE
% file. Function F(T,Y) must return a column vector. Each row in
% solution array Y corresponds to a time returned in column vector T. To
% obtain solutions at specific times T0, T1, ..., TFINAL (all increasing
% or all decreasing), use TSPAN = [T0 T1 ... TFINAL].
%
% [T,Y] = ODE45('F',TSPAN,Y0,OPTIONS) solves as above with default
% integration parameters replaced by values in OPTIONS, an argument
% created with the ODESET function. See ODESET for details. Commonly
% used options are scalar relative error tolerance 'RelTol' (1e-3 by
% default) and vector of absolute error tolerances 'AbsTol' (all
% components 1e-6 by default).
%
% [T,Y] = ODE45('F',TSPAN,Y0,OPTIONS,P1,P2,...) passes the additional
% parameters P1,P2,... to the ODE file as F(T,Y,FLAG,P1,P2,...) (see
% ODEFILE). Use OPTIONS = [] as a place holder if no options are set.
%
% It is possible to specify TSPAN, Y0 and OPTIONS in the ODE file (see
% ODEFILE). If TSPAN or Y0 is empty, then ODE45 calls the ODE file
% [TSPAN,Y0,OPTIONS] = F([],[],'init') to obtain any values not supplied
% in the ODE45 argument list. Empty arguments at the end of the call list
% may be omitted, e.g. ODE45('F').
%
% As an example, the commands
%
% options = odeset('RelTol',1e-4,'AbsTol',[1e-4 1e-4 1e-5]);
% ode45('rigidode',[0 12],[0 1 1],options);
%
% solve the system y' = rigidode(t,y) with relative error tolerance 1e-4
% and absolute tolerances of 1e-4 for the first two components and 1e-5
% for the third. When called with no output arguments, as in this
% example, ODE45 calls the default output function ODEPLOT to plot the
% solution as it is computed.
%
% [T,Y,TE,YE,IE] = ODE45('F',TSPAN,Y0,OPTIONS) with the Events property in
% OPTIONS set to 'on', solves as above while also locating zero crossings
% of an event function defined in the ODE file. The ODE file must be
% coded so that F(T,Y,'events') returns appropriate information. See
% ODEFILE for details. Output TE is a column vector of times at which
% events occur, rows of YE are the corresponding solutions, and indices in
% vector IE specify which event occurred.
%
% See also ODEFILE and
% other ODE solvers: ODE23, ODE113, ODE15S, ODE23S, ODE23T, ODE23TB
% options handling: ODESET, ODEGET
% output functions: ODEPLOT, ODEPHAS2, ODEPHAS3, ODEPRINT
% odefile examples: ORBITODE, ORBT2ODE, RIGIDODE, VDPODE
% ODE45 is an implementation of the explicit Runge-Kutta (4,5) pair of
% Dormand and Prince called variously RK5(4)7FM, DOPRI5, DP(4,5) and DP54.
% It uses a "free" interpolant of order 4 communicated privately by
% Dormand and Prince. Local extrapolation is done.
% Details are to be found in The MATLAB ODE Suite, L. F. Shampine and
% M. W. Reichelt, SIAM Journal on Scientific Computing, 18-1, 1997.
% Mark W. Reichelt and Lawrence F. Shampine, 6-14-94
% Copyright (c) 1984-98 by The MathWorks, Inc.
% $Revision: 5.53 $ $Date: 1997/11/21 23:31:04 $
true = 1;
false = ~true;
nsteps = 0; % stats
nfailed = 0; % stats
nfevals = 0; % stats
npds = 0; % stats
ndecomps = 0; % stats
nsolves = 0; % stats
if nargin == 0
error('Not enough input arguments. See ODE45.');
elseif ~isstr(odefile) & ~isa(odefile, 'inline')
error('First argument must be a single-quoted string. See ODE45.');
end
if nargin == 1
tspan = []; y0 = []; options = [];
elseif nargin == 2
y0 = []; options = [];
elseif nargin == 3
options = [];
elseif ~isempty(options) & ~isa(options,'struct')
if (length(tspan) == 1) & (length(y0) == 1) & (min(size(options)) == 1)
tspan = [tspan; y0];
y0 = options;
options = [];
varargin = {};
msg = sprintf('Use ode45(''%s'',tspan,y0,...) instead.',odefile);
warning(['Obsolete syntax. ' msg]);
else
error('Correct syntax is ode45(''odefile'',tspan,y0,options).');
end
end
% Get default tspan and y0 from odefile if none are specified.
if isempty(tspan) | isempty(y0)
if (nargout(odefile) < 3) & (nargout(odefile) ~= -1)
msg = sprintf('Use ode45(''%s'',tspan,y0,...) instead.',odefile);
error(['No default parameters in ' upper(odefile) '. ' msg]);
end
[def_tspan,def_y0,def_options] = feval(odefile,[],[],'init',varargin{:});
if isempty(tspan)
tspan = def_tspan;
end
if isempty(y0)
y0 = def_y0;
end
if isempty(options)
options = def_options;
else
options = odeset(def_options,options);
end
end
% Test that tspan is internally consistent.
tspan = tspan(:);
ntspan = length(tspan);
if ntspan == 1
t0 = 0;
next = 1;
else
t0 = tspan(1);
next = 2;
end
tfinal = tspan(ntspan);
if t0 == tfinal
error('The last entry in tspan must be different from the first entry.');
end
tdir = sign(tfinal - t0);
if any(tdir * (tspan(2:ntspan) - tspan(1:ntspan-1)) <= 0)
error('The entries in tspan must strictly increase or decrease.');
end
t = t0;
y = y0(:);
neq = length(y);
% Get options, and set defaults.
rtol = odeget(options,'RelTol',1e-3);
if (length(rtol) ~= 1) | (rtol <= 0)
error('RelTol must be a positive scalar.');
end
if rtol < 100 * eps
rtol = 100 * eps;
warning(['RelTol has been increased to ' num2str(rtol) '.']);
end
atol = odeget(options,'AbsTol',1e-6);
if any(atol <= 0)
error('AbsTol must be positive.');
end
normcontrol = strcmp(odeget(options,'NormControl','off'),'on');
if normcontrol
if length(atol) ~= 1
error('Solving with NormControl ''on'' requires a scalar AbsTol.');
end
normy = norm(y);
else
if (length(atol) ~= 1) & (length(atol) ~= neq)
error(sprintf(['Solving %s requires a scalar AbsTol, ' ...
'or a vector AbsTol of length %d'],upper(odefile),neq));
end
atol = atol(:);
end
threshold = atol / rtol;
% By default, hmax is 1/10 of the interval.
hmax = min(abs(tfinal-t), abs(odeget(options,'MaxStep',0.1*(tfinal-t))));
if hmax <= 0
error('Option ''MaxStep'' must be greater than zero.');
end
htry = abs(odeget(options,'InitialStep'));
if htry <= 0
error('Option ''InitialStep'' must be greater than zero.');
end
haveeventfun = strcmp(odeget(options,'Events','off'),'on');
if haveeventfun
valt = feval(odefile,t,y,'events',varargin{:});
teout = [];
yeout = [];
ieout = [];
end
if nargout > 0
outfun = odeget(options,'OutputFcn');
else
outfun = odeget(options,'OutputFcn','odeplot');
end
if isempty(outfun)
haveoutfun = false;
else
haveoutfun = true;
outputs = odeget(options,'OutputSel',1:neq);
end
refine = odeget(options,'Refine',4); % Necessary for smooth plots.
printstats = strcmp(odeget(options,'Stats','off'),'on');
if strcmp(odege