68. Numerical solution of ordinary differential equations: One step methods#
Anne Kværnø, André Massing
Date: March 22, 2021
If you want to have a nicer theme for your jupyter notebook, download the cascade stylesheet file tma4125.css and execute the next cell:
import matplotlib.pyplot as plt
import numpy as np
from IPython.core.display import HTML
from numpy import pi
from numpy.linalg import norm, solve
def css_styling():
try:
with open("tma4125.css") as f:
styles = f.read()
return HTML(styles)
except FileNotFoundError:
pass # Do nothing
# Comment out next line and execute this cell to restore the default notebook style
css_styling()
As always, we start by importing the necessary modules:
%matplotlib inline
# Use a funny plotting style
plt.xkcd()
newparams = {
"figure.figsize": (6.0, 6.0),
"axes.grid": True,
"lines.markersize": 8,
"lines.linewidth": 2,
"font.size": 14,
}
plt.rcParams.update(newparams)
69. One Step Methods#
In the last lecture, we introduced the explicit Euler method and Heun’s method, motivating the following definition.
69.1. Definition 1: One step methods#
A one step method defines an approximation to the IVP in the form of a discrete function \( {\boldsymbol y}_{\Delta}: \{ t_0, \ldots, t_N \} \to \mathbb{R}^n \) given by
\begin{equation} {\boldsymbol y}{k+1} := {\boldsymbol y}k + \tau_k \Phi(t_k, {\boldsymbol y}{k}, {\boldsymbol y}{k+1}, \tau_{k}) \label{ode:eq:osm-def} \tag{1} \end{equation}
for some increment function
The OSM is called explicit if the increment function \(\Phi\) does not depend on \({\boldsymbol y}_{k+1}\), otherwise it is called implicit.
69.2. Example 1: Increment functions for Euler and Heun#
The increment functions for Euler's and Heun's method are defined by respectively69.3. Local and global truncation error of OSM#
69.4. Definition 2: Local truncation error#
The local truncation error \(\eta(t, \tau)\) is defined by
\(\eta(t, \tau)\) is often also called the local discretization or consistency error.
A one step method is called consistent of order \(p\in \mathbb{N}\) if there is a constant \(C > 0\) such that
A short-hand notation for this is to write \( \eta(t, \tau) = \mathcal{O}(\tau^{p+1})\) for \(\tau \to 0. \)
69.5. Example 2:#
Euler’s method has consistency order \(p=1\).
69.6. Definition 3: Global truncation error#
For a numerical solution \( y_{\Delta}: \{ t_0, \ldots, t_N \} \to \mathbb{R} \) the global truncation error is defined by
A one step method is called convergent with order \(p\in\mathbb{N}\) if
with \(\tau = \max_k \tau_k\).
Discussion. If a one step method has convergence order equal to \(p\), the maximum error \(e(\tau) = \max_k{|e(t_k, \tau)|}\) can be thought as a function of the step size \(\tau\) is of the form
This implies that if we change the time step size from \(\tau\) to \(\tfrac{\tau}{2}\), we can expect that the error decreases from \(C \tau^p\) to \(C (\tfrac{\tau}{2})^p\), that is, the error will be reduced by a factor \(2^{-p}\).
How can we determine the convergence rate by means of numerical experiments? Starting from \( e(\tau) = O(\tau^p) \leqslant C \tau^p \) and taking the logarithm gives
Thus \(\log(e(\tau))\) is a linear function of \(\log(\tau)\) and the slope of this linear function corresponds to the order of convergence \(p\).
So if you have an exact solution at your disposal, you can for an
increasing sequence Nmax_list
defining a descreasing sequence of
maximum time-steps \(\{\tau_0,
\ldots, \tau_M\}\)
and solve your problem numerically and then compute the resulting exact error
\(e(\tau_i)\) and plot it against \(\tau_i\) in a \(\log-\log\) plot to determine
the convergence order.
In addition you can also compute the Experimentally Observed Convergence rate EOC for \(i=1,\ldots M\) defined by
Ideally, \(\mathrm{EOC}(i)\) is close to \(p\).
This is implemented in the following python
function.
def compute_eoc(y0, t0, T, f, Nmax_list, solver, y_ex):
errs = []
for Nmax in Nmax_list:
ts, ys = solver(y0, t0, T, f, Nmax)
ys_ex = y_ex(ts)
errs.append(np.abs(ys - ys_ex).max())
print(f"For Nmax = {Nmax:3}, max ||y(t_i) - y_i||= {errs[-1]:.3e}")
errs = np.array(errs)
Nmax_list = np.array(Nmax_list)
dts = (T - t0) / Nmax_list
eocs = np.log(errs[1:] / errs[:-1]) / np.log(dts[1:] / dts[:-1])
return errs, eocs
69.7. Exercise 1: Convergence order for Euler and Heun#
Use the compute_eoc
function and
any of the examples with a known analytical solution from the previous lecture
to determine convergence order for Euler’s and Heun’s method.
Start from importing our numerical schemes from yesterday’s lecture.
def explicit_euler(y0, t0, T, f, Nmax):
ys = [y0]
ts = [t0]
dt = (T - t0) / Nmax
while ts[-1] < T:
t, y = ts[-1], ys[-1]
ys.append(y + dt * f(t, y))
ts.append(t + dt)
return (np.array(ts), np.array(ys))
def heun(y0, t0, T, f, Nmax):
ys = [y0]
ts = [t0]
dt = (T - t0) / Nmax
while ts[-1] < T:
t, y = ts[-1], ys[-1]
k1 = f(t, y)
k2 = f(t + dt, y + dt * k1)
ys.append(y + 0.5 * dt * (k1 + k2))
ts.append(t + dt)
return (np.array(ts), np.array(ys))
Solution.
t0, T = 0, 1
y0 = 1
lam = 1
# rhs of IVP
f = lambda t, y: lam * y
# Exact solution to compare against
y_ex = lambda t: y0 * np.exp(lam * (t - t0))
Nmax_list = [4, 8, 16, 32, 64, 128]
errs, eocs = compute_eoc(y0, t0, T, f, Nmax_list, explicit_euler, y_ex)
print(eocs)
errs, eocs = compute_eoc(y0, t0, T, f, Nmax_list, heun, y_ex)
print(eocs)
For Nmax = 4, max ||y(t_i) - y_i||= 2.769e-01
For Nmax = 8, max ||y(t_i) - y_i||= 1.525e-01
For Nmax = 16, max ||y(t_i) - y_i||= 8.035e-02
For Nmax = 32, max ||y(t_i) - y_i||= 4.129e-02
For Nmax = 64, max ||y(t_i) - y_i||= 2.094e-02
For Nmax = 128, max ||y(t_i) - y_i||= 1.054e-02
[0.86045397 0.9243541 0.96050605 0.9798056 0.98978691]
For Nmax = 4, max ||y(t_i) - y_i||= 2.343e-02
For Nmax = 8, max ||y(t_i) - y_i||= 6.441e-03
For Nmax = 16, max ||y(t_i) - y_i||= 1.688e-03
For Nmax = 32, max ||y(t_i) - y_i||= 4.322e-04
For Nmax = 64, max ||y(t_i) - y_i||= 1.093e-04
For Nmax = 128, max ||y(t_i) - y_i||= 2.749e-05
[1.86285442 1.93161644 1.96595738 1.98303072 1.99153035]
69.8. A general convergence result for one step methods#
69.9. Theorem 1: Convergence of one-step methods#
Assume that there exist positive constants $M$ and $D$ such that the increment function satisfiesand the local trunctation error satisfies
for all \(t\), \(\mathbf{y}\) and \(\mathbf{z}\) in the neighbourhood of the solution.
In that case, the global error satisfies
where \(\tau = \max_{k \in \{0,1,\ldots,N_t\}} \tau_k\).
Proof. We omit the proof here.
It can be proved that the first of these conditions are satisfied for all the methods that will be considered here.
Summary.
The convergence theorem for one step methods can be summarized as
“local truncation error behaves like \(\mathcal{O}(\tau^{p+1})\)” + “Increment function satisfies a Lipschitz condition” \(\Rightarrow\) “global truncation error behaves like \(\mathcal{O}(\tau^{p})\)”
or equivalently,
“consistency order \(p\)” + “Lipschitz condition for the Increment function” \(\Rightarrow\) “convergence order \(p\)”.
69.10. Convergence properties of Heun’s method#
Thanks to Theorem Theorem 1: Convergence of one-step methods, we need to show two things to prove convergence and find the corresponding convergence of a given one step methods:
determine the local truncation error, expressed as a power series in the step size \(\tau\)
the condition \(\| {\boldsymbol \Phi}(t,{\boldsymbol y}, \tau) - {\boldsymbol \Phi}(t,{\boldsymbol z},\tau) \| \leqslant M \| {\boldsymbol y} - {\boldsymbol z} \|\)
Determining the consistency order. The local truncation error is found by making Taylor expansions of the exact and the numerical solutions starting from the same point, and compare. In practice, this is not trivial. For simplicity, we will here do this for a scalar equation \(y'(t)=f(t,y(t))\). The result is valid for systems as well.
In the following, we will use the notation
Further, we will surpress the arguments of the function \(f\) and its derivatives. So \(f\) is to be understood as \(f(t,y(t))\) although it is not explicitly written.
The Taylor expansion of the exact solution \(y(t+\tau)\) is given by
Higher derivatives of \(y(t)\) can be expressed in terms of the function \(f\) by using the chain rule and the product rule for differentiation.
Find the series of the exact and the numerical solution around \(x_0,y_0\) (any other point will do equally well). From the discussion above, the series for the exact solution becomes
where \(f\) and all its derivatives are evaluated in \((t_0,y_0)\).
For the numerical solution we get
Thus the local truncation error will be
The first nonzero term in the local truncation error series is called the principal error term. For \(\tau \) sufficiently small this is the term dominating the error, and this fact will be used later.
Although the series has been developed around the initial point, series around \(t_n, y(t_n)\) will give similar results, and it is possible to conclude that, given sufficient differentiability of \(f\) there is a constant \(D\) such that
Consequently, Heun’s method is of consistency order \(2\).
Lipschitz condition for \(\Phi\). Further, we have to prove the condition on the increment function \(\Phi(t,y)\). For \(f\) differentiable, there is for all \(y,z\) some \(\xi\) between \(x\) and \(y\) such that \(f(t,y)-f(t,z) = f_y(t,\xi)(y-z)\). Let L be a constant such that \(|f_y|<L\), and for all \(x,y,z\) of interest we get
The increment function for Heun’s method is given by
By repeated use of the condition above and the triangle inequalitiy for absolute values we get
Assuming that the step size \(\tau\) is bounded upward by some \(\tau_0\), we can conclude that
Thanks to Theorem Theorem 1: Convergence of one-step methods, we can conclude that Heun’s method is convergent of order 2.