Solving a 2nd order ODE with the Euler method
Contents
Initial value problem
We consider an initial value problem for a 2nd order ODE:
and we want to find the solution y(t) for t in [0,4].
We first have to rewrite this as a 1st order system: Let and , then we obtain
Now we can define a vector valued function f(t,y) and an initial vector y0.
We use ode45 to find the solution of the initial value problem. At the final time T we obtain the approximation yfin = [y1fin,y2fin] for .
We plot the solution .
function euler_demo2
f = @(t,y) [y(2); t+y(2)-3*y(1)]; % define function f(t,y) t0 = 0; y0 = [1;-2]; % initial condition with vector y0 T = 4; % final t-value [ts,ys] = ode45(f,[t0,T],y0); % solve IVP yfinal = ys(end,:); % approximations for y1(T),y2(T) fprintf('y(T) = %g, y''(T) = %g\n',ys(end,1),ys(end,2)) plot(ts,ys(:,1),'b'); hold on % plot solution y(t) title('Solution y(t) of IVP') xlabel('t'); grid on
y(T) = 3.36902, y'(T) = -21.7257
Use Euler method with N=16,32,...,256
We see that the Euler approximations get closer to the correct value as N increases.
When we double the value of N the error gets divided by about 2. This means that the error is bounded by : The Euler method converges with order .
olderr = NaN; for N = 2.^(4:8) [ts,ys] = Euler(f,[t0,T],y0,N); err = norm(ys(end,:)-yfinal); % norm of error fprintf('N = %3g, y(T) = [%10g,%10g], ||error|| = %10g, quotient = %g\n',N,ys(end,:),err,olderr/err) olderr = err; plot(ts,ys(:,1),'.-') % plot Euler approximaton for y1 (1st column of ys) end hold off title('Euler approximations for N=16,32,...,256')
N = 16, y(T) = [ 32.5946, -8.97401], ||error|| = 31.8864, quotient = NaN N = 32, y(T) = [ 15.0972, -25.55], ||error|| = 12.3359, quotient = 2.58484 N = 64, y(T) = [ 8.0537, -25.45], ||error|| = 5.98469, quotient = 2.06125 N = 128, y(T) = [ 5.40507, -23.898], ||error|| = 2.97735, quotient = 2.01007 N = 256, y(T) = [ 4.31208, -22.8693], ||error|| = 1.48228, quotient = 2.00863
Code of function Euler(f,[t0,T],y0,N)
At each step we evaluate the slope s=f(t,y) and then update y=y+s*h, t=t+h.
function [ts,ys] = Euler(f,tv,y0,N); t0 = tv(1); T = tv(2); h = (T-t0)/N; % stepsize h ts = zeros(N+1,1); ys = zeros(N+1,length(y0)); t = t0; y = y0; % initial point ts(1) = t; ys(1,:) = y'; for i=1:N s = f(t,y); % evaluate direction field at current point y = y + s*h; % follow line with slope s from t to t+h t = t + h; ts(i+1) = t; ys(i+1,:) = y'; % store y(1),y(2) in row of array ys end end
end