Consider the stiff ODE $$ y' = -100(y - \sin(t)), \qquad t \ge 0 $$ $$ y(0) = 1 $$
import numpy as np
from matplotlib import pyplot as plt
def f(t,y):
return -100.0*(y - np.sin(t))
def ForwardEuler(t0,y0,T,h):
N = int((T-t0)/h)
y = np.zeros(N)
t = np.zeros(N)
t[0] = t0
y[0] = y0
for n in range(1,N):
y[n] = y[n-1] + h*f(t[n-1],y[n-1])
t[n] = t[n-1] + h
return t,y
t0 = 0
y0 = 1
T = np.pi
h = 1.0/52.0
t,y = ForwardEuler(t0,y0,T,h)
plt.plot(t,y)
plt.xlim([-0.1,4])
plt.title("Forward Euler, h ="+str(h))
<matplotlib.text.Text at 0x10d5f5f50>
h = 0.01
t,y = ForwardEuler(t0,y0,T,h)
plt.plot(t,y)
plt.xlim([-0.1,4])
plt.title("Forward Euler, h ="+str(h))
<matplotlib.text.Text at 0x10c409450>
or $$ y_n = \frac{ y_{n-1} + 100 h \sin(t_n)}{1 + 100 h} $$
def BackwardEuler(t0,y0,T,h):
N = int((T-t0)/h)
y = np.zeros(N)
t = np.zeros(N)
t[0] = t0
y[0] = y0
for n in range(1,N):
t[n] = t[n-1] + h
y[n] = (y[n-1] + 100.0*h*np.sin(t[n]))/(1.0 + 100.0*h)
return t,y
or $$ y_n = \frac{(1-50h)y_{n-1} + 50h(\sin(t_{n-1}) + \sin(t_n))}{1 + 50 h} $$
def Trapezoidal(t0,y0,T,h):
N = int((T-t0)/h)
y = np.zeros(N)
t = np.zeros(N)
t[0] = t0
y[0] = y0
for n in range(1,N):
t[n] = t[n-1] + h
y[n] = ((1.0-50.0*h)*y[n-1] + 50.0*h*(np.sin(t[n-1])+np.sin(t[n])))/(1.0 + 50.0*h)
return t,y
h = 0.1
t,y = BackwardEuler(t0,y0,T,h)
plt.plot(t,y)
t,y = Trapezoidal(t0,y0,T,h)
plt.plot(t,y)
plt.xlim([-0.1,4])
plt.title("Step size h ="+str(h))
plt.legend(("Backward Euler","Trapezoid"))
<matplotlib.legend.Legend at 0x10d583bd0>