%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Forward Euler method %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% for MTH 452-552 %%% this is a simple example how to use error estimates %%% for simple explicit one-step methods for ODEs %%% using Richardson's extrapolation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% M. Peszynska, 2005/1 %% Copyright Department of Mathematics, Oregon State University %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% INSTRUCTIONS: calling sequence % error_estimate_demo (flag,h) % where flag is 1, 2, 4 (sample methods of order 1, 2, 4 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function error_estimate_demo (flag,h) if nargin < 2 flag = 1; h= .1; end; %% set up the function f = inline('3.*exp(-3*t).*y','t','y'); phi = inline('exp(1-exp(-3*t))','t'); %f = inline('-2.*t.*y.^2','t','y'); %phi = inline('1./(1+t.^2)','t'); %f = inline('-y','t','y'); %phi = inline('exp(-t)','t'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% compute the solution and plot %h = .05; flag = 2; %% the numerical solution will be in y1 and y2 (double step) [t2,y2,p] = explicit_method (f,1,0,1,2*h,flag); n = size(t2,2); [te,ye,p] = explicit_method (f,1,0,1,h, flag); t1 = zeros(n,1); y1 = zeros(n,1); for i=1:n t1(i)=te(2*i-1);y1(i)=ye(2*i-1); end; plot(t1,phi(t1),'k',t1,y1,'r',t2,y2,'g'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% error and estimate %p = 1; %% Euler explicit %p = 2; %% any second order: modified Euler, trapezoid etc. %p = 4; %% Runge-Kutta: classical %% show error and its estimate for i=1:n fprintf('ex_error=%g err_estimate (Richardson)=%g \n',... y1(i) - phi(t1(i)), ... (y1(i) - y2(i))./(1 - 2^p) ... ); end; %%%%%%%%%%%%%%%%%%%%%%% function [t,sol,p] = explicit_method (f,y0,T0,T,h,flag) switch flag case 1, [t,sol] = euler_explicit (f,y0,T0,T,h); p=1; case 2, [t,sol] = euler_modified (f,y0,T0,T,h); p=2; case 4, [t,sol] = rk_classic (f,y0,T0,T,h); p=4; end; %%%%%%%%%%%%%%%%%%%%%%% function [t,sol] = euler_explicit (f,y0,T0,T,h) % % % %% set up the time interval and its discretization n = floor(T-T0) / h; %% time steps are stored in t t = T0:h:T; %% the numerical solution will be in yh sol = zeros(n+1,1); sol (1) = y0; %% Euler method for i=1:n sol(i+1) = sol(i) + h * feval (f, t(i), sol(i) ); end; %%%%%%%%%%%%%%%%%%%%%%% function [t,sol] = euler_modified (f,y0,T0,T,h) % % % %% set up the time interval and its discretization n = floor(T-T0) / h; %% time steps are stored in t t = T0:h:T; %% the numerical solution will be in yh sol = zeros(n+1,1); sol (1) = y0; %% Euler modified method for i=1:n soli = feval (f, t(i), sol(i) ); sol(i+1) = sol(i) + h * feval (f, t(i)+h/2, sol(i)+h/2*soli ); end; %%%%%%%%%%%%%%%%%%%%%%% function [t,sol] = rk_classic (f,y0,T0,T,h) % % % %% set up the time interval and its discretization n = floor(T-T0) / h; %% time steps are stored in t t = T0:h:T; %% the numerical solution will be in yh sol = zeros(n+1,1); sol (1) = y0; %% classic Runge-Kutta for i=1:n soli = sol(i); sol1 = feval (f, t(i), soli); sol2 = feval (f, t(i) + h/2, soli + h/2 * sol1); sol3 = feval (f, t(i) + h/2, soli + h/2 * sol2); sol4 = feval (f, t(i) + h, soli + h * sol3); sol(i+1) = soli + h/6 * (sol1 + 2 * sol2 + 2 * sol3 + sol4); end;