function [w,t] = AdamsAdaptPCv(FunFcnIn, Intv, alpha, tol,stepsize) % On input: % FunFcnIn is the name of function to be integrated % interv is the interval to be integrated over % % The problem: y' = f(t,y), y(a) = alpha, a<= t <= b % where Intv = [a b], and a call to FunFcnIn with % argument (t, y) returns f(t,y). % % AdamsAdaptPC uses the Adams Variable Step-size PC method to solve % the above problem, to a given tolerance. % hmin and hmax are the minimum and maximum step sizes. % % This is the vector version of AdamsAdaptPC. % % On output % t contains the (unequi-spaced) mesh points, w the % function values at these points. % % Written by Ming Gu for Math 128A, Fall 2008 % [FunFcn,msg] = fcnchk(FunFcnIn,0); if ~isempty(msg) error('InvalidFUN',msg); end flg = 0; a = Intv(1); b = Intv(2); hmin = stepsize(1); hmax = stepsize(2); h = min(hmax,(b-a)/4); if (h<=0) msg = ['Illegal hmax or interval']; error('InvalidFUN',msg); end p = [-9/24 37/24 -59/24 55/24]'; c = [ 1/24 -5/24 19/24 9/24 ]'; % % RK4v for the first 3 steps % nflg = 1; [f, w, t] = RKv(FunFcnIn, a,h,alpha); % % main loop % flg = 0; i = 4; last= 0; while (flg == 0) wi = w(:,i); ti = t(i); tnew = ti + h; wp = wi + h*(f(:,i-3:i)*p); fp = FunFcn(tnew,wp); wc = wi + h*([f(:,i-2:i),fp]*c); sigma= max(eps,19*norm(wc-wp)/(270*h)); if (sigma <= tol) i = i + 1; t(i) = tnew; w(:,i) = wc; f(:,i) = FunFcn(tnew,wc); if (last == 1) return; end nflg = 0; if (sigma <= 0.1*tol | tnew+h>b) q = (tol/(2*sigma))^(1/4); h = min(hmax,min(q,4)*h); if (tnew + 4 * h > b) h = (b-tnew)/4; last = 1; end nflg = 1; [f1, w1, t1] = RKv(FunFcnIn, t(i), h, w(:,i)); f = [f(:,1:i),f1(:,2:end)]; w = [w(:,1:i),w1(:,2:end)]; t = [t(1:i);t1(2:end)]; i = i + 3; end else q = (tol/(2*sigma))^(1/4); h = max(q,0.1)*h; if (h < hmin) disp(['hmin exceeded']); flg = 1; return; end if (nflg == 1) i = i - 3; end nflg = 1; [f1, w1, t1] = RKv(FunFcnIn, t(i), h, w(:,i)); f = [f(:,1:i),f1(:,2:end)]; w = [w(:,1:i),w1(:,2:end)]; t = [t(1:i);t1(2:end)]; i = i + 3; end end function [f,w, t] = RKv(FunFcnIn, a,h,alpha) % % performs 3 steps of RK4v % [FunFcn,msg] = fcnchk(FunFcnIn,0); if ~isempty(msg) error('InvalidFUN',msg); end m = length(alpha); w = zeros(m,4); f = zeros(m,4); w(:,1) = alpha; h2 = h/2; t = a+(0:3)'*h; for i = 1:3 f(:,i) = FunFcn(t(i),w(:,i)); k1 = h* f(:,i); k2 = h* FunFcn(t(i)+h2,w(:,i)+k1/2); k3 = h* FunFcn(t(i)+h2,w(:,i)+k2/2); k4 = h* FunFcn(t(i)+h,w(:,i)+k3); w(:,i+1) = w(:,i) + (k1+2*k2+2*k3+k4)/6; end f(:,4) = FunFcn(t(4),w(:,4));