Solution to the first MATLAB assignment
First we set some parameters that will be used over and over:
First, let's look with a small number of points
We compare the three different methods with a big stepsize . t=linspace(tStart,tEnd,N+1);
yEuler(k+1)=eulerStep(@f,t(k),yEuler(k),h);
yEulerImproved(k+1)=eulerImprovedStep(@f,t(k),yEulerImproved(k),h);
yRunge(k+1)=RKStep(@f,t(k),yRunge(k),h);
plot(t,yEuler,t,yEulerImproved,t,yRunge,t,yX,'k--')
legend('Euler','Improved','Runke-Kutta','Exact','Location',"eastoutside")
Plot the errors of the three methods
plot(t,yX-yEuler,t,yX-yEulerImproved,t,yX-yRunge)
legend('Euler','Improved Euler','Runge-Kutta','location','northwest')
errorEuler=abs(yX(end)-yEuler(end));
errorImproved=abs(yX(end)-yEulerImproved(end));
errorRunge=abs(yX(end)-yRunge(end));
fprintf('With 40 points, the final-time error is:\n')
With 40 points, the final-time error is:
fprintf('Euler method: %0.2d',errorEuler)
fprintf('Improved Euler method: %0.2d',errorImproved)
Improved Euler method: 6.34e-03
fprintf('Runge-Kutta method: %0.2d',errorRunge)
Runge-Kutta method: 3.27e-05
Experimentally find h small enough to make error below
We just keep cuttingh in half (doubling N) until we get below the threshold.
t=linspace(tStart,tEnd,N+1);
y(k+1)=eulerStep(@f,t(k),y(k),h);
errorEuler=abs(yX(end)-y(end));
fprintf('N = %i, error=%0.3f\n',N,errorEuler)
end
N = 80, error=0.189
N = 160, error=0.110
N = 320, error=0.058
N = 640, error=0.030
N = 1280, error=0.015
N = 2560, error=0.007
plot(t,y,t,yExact(t),'--')
xlabel('$t$');ylabel('$y$')
That's good enough. Somewhere between 1280 and 2560 points, Euler's method returns an error below 0.01.
For the improved Euler method, I found points to be enough
Here I notice that was good enough in the initial experiment, so I just reduced it a bit at a time by hand until it failed. t=linspace(tStart,tEnd,N+1);
y(k+1)=eulerImprovedStep(@f,t(k),y(k),h);
plot(t,y,t,yExact(t),'--')
xlabel('$t$');ylabel('$y$')
error=abs(yX(end)-y(end));
fprintf('N = %i, error=%0.3f\n',N,error)
Runge Kutta can get away with points
Clearly this is not enough points to generate a nice smooth curve but the numbers it gives are very accurate.
t=linspace(tStart,tEnd,N+1);
y(k+1)=RKStep(@f,t(k),y(k),h);
plot(t,y,t,yExact(t),'--')
xlabel('$t$');ylabel('$y$')
error=abs(yX(end)-y(end));
fprintf('N = %i, error=%0.3f\n',N,error)
Show the Euler method is first order
t=linspace(tStart,tEnd,N+1);
y(k+1)=eulerStep(@f,t(k),y(k),h);
error1 = abs(yExact(tEnd)-y(end));
fprintf('N = %i, error=%0.3f\n',N,error1)
t=linspace(tStart,tEnd,N+1);
y(k+1)=eulerStep(@f,t(k),y(k),h);
error2=abs(yExact(tEnd)-y(end));
fprintf('N = %i, error=%0.3f\n',N,error2)
fprintf('The error went down by a factor of %0.2f.\n',errRatio)
The error went down by a factor of 1.99.
Show the Improved Euler method is second order
t=linspace(tStart,tEnd,N+1);
y(k+1)=eulerImprovedStep(@f,t(k),y(k),h);
error1 = abs(yExact(tEnd)-y(end));
fprintf('N = %i, error=%0.d\n',N,error1)
t=linspace(tStart,tEnd,N+1);
y(k+1)=eulerImprovedStep(@f,t(k),y(k),h);
error2=abs(yExact(tEnd)-y(end));
fprintf('N = %i, error=%0.3d\n',N,error2)
N = 2000, error=2.208e-06
fprintf('The error went down by a factor of %0.2f.\n',errRatio)
The error went down by a factor of 3.87.
Show the Runge-Kutta method is fourth order
t=linspace(tStart,tEnd,N+1);
y(k+1)=RKStep(@f,t(k),y(k),h);
error1 = abs(yExact(tEnd)-y(end));
fprintf('N = %i, error=%0.d\n',N,error1)
t=linspace(tStart,tEnd,N+1);
y(k+1)=RKStep(@f,t(k),y(k),h);
error2=abs(yExact(tEnd)-y(end));
fprintf('N = %i, error=%0.3d\n',N,error2)
N = 2000, error=6.707e-12
fprintf('The error went down by a factor of %0.2f.\n',errRatio)
The error went down by a factor of 15.58.
Functions used
y=exp(cos(t))./sqrt(3*exp(2)+exp(2*cos(t)));
function yNew=eulerStep(f,t,y,h)
function yNew=eulerImprovedStep(f,t,y,h)
function yNew=RKStep(f,t,y,h)
yNew=y+h*(k1+2*k2+2*k3+k4)/6;