In the previous section, we used built-in ODE solvers to develop numerical solutions. It is important to gain an understanding how a simple ODE solver works. The simplest scheme is called Euler’s method, and this we now explain.
Begin from the system (Equation 6.2). We assume that the solution is represented by a discrete set of points, \(\mathbf{Y}_n = \mathbf{Y}(t_n)\) at the times \(t_0 = 0\), \(t_1 = \Delta t\), \(t_2 = 2\Delta t\), and so on. The time derivative is written as a discrete derivative while we approximate the right hand side by its value at the nth time step: \[
\frac{\mathbf{Y}_{n+1} - \mathbf{Y}_{n}}{\Delta t} = \mathbf{F}(t_n, \mathbf{Y}_n)
\]
Rearranging yields a very simple algorithm for solving the ODE: \[
\mathbf{Y}_{n} = \mathbf{Y}_{n-1} + \mathbf{F}(t_{n-1}, \mathbf{Y}_{n-1}) \Delta t
\] for \(n = 1, 2, 3, \ldots\)
This would be implemented via the following pseudocode:
Euler’s method
1. Input: function f(t, Y)
time step, dt
initial condition, Y0
2. Set initial condition Y = Y0
2. Take one Euler step and overwrite previous value
Y = Y + f(t, Y)
3. Increment t by dt and goto 2
Euler’s method is conceptually simple but quite inaccurate. But in this case, we see that it works fairly well in comparison to the built-in solvers.
import numpy as npimport matplotlib.pyplot as pltfrom scipy.integrate import solve_ivpep =0.2# epsilon valuetmax =2# max timeN =20# number of stepst = np.linspace(0, tmax, N) # mesh used for plottingdt = t[1] - t[0]# Define function for the ODEdef f(t, Y, ep): y, yp = Y ypp =-1/(1+ ep*y)**2return np.array([yp, ypp])# define the initial conditionY = [0.0, 1.0]ti =0# define the solution vectorfor i inrange(1, N): ti = ti + dt # Increment time Y = Y + f(ti, Y, ep)*dt # Euler step plt.plot(ti, Y[0], 'k.')# Asymptotic solutionsy0 =-1/2*t**2+ ty1 =-1/12*t**4+1/3*t**3plt.plot(t, y0, '--')plt.plot(t, y0 + ep*y1, '--')plt.xlabel('t');plt.ylabel('y');