5.2. Trapezoidal rule#
When only two measurements of the system are accessible, the trapezoid rule is the easiest way to estimate an integral. It then approximates the area of the resulting trapezoid shape by interpolating a polynomial between the two points (i.e., a single straight diagonal line).
Area of Trapezoid
Assume \(\{x_{0},~x_{1}\} \in [a,b]\), for some values of \(a\) and \(b\), are known and we are interested in calculating the area under the curve for a function of \(f(x)\) which is unknown, but we have access to the value of \(f(x_{0})\) and \(f(x_{1})\). Then,
Moreover, in case, we use \(\{x_{0},~x_{1},~x_{2}\}\) and \(\{f(x_{0}),f(x_{1}), f(x_{2})\}\),
Assume that \(\{x_{0},~x_{1},\ldots,~x_{n}\}\) are \(n+1\) in \([a,b]\) such that
and \(\Delta x_{j}\) is defined as \(\Delta x_{j}=x_{j+1}-x_{j}\) with \(0 \leq j \leq n-1\). Then,
Now if \(\{x_{0},x_{1},\ldots, x_{n}\}\) are equally distanced. i.e. \(\Delta x_{j}= h = \dfrac{b-a}{n}>0\) for \(j\in \{0,1,\ldots,n-1\}\),
Observe that,
Remark
The above numerical quadrature \eqref{trap.equal.eq02} can be written as follows as well (why!?):
Example: Use the Trapezoid rule and compute \({\displaystyle\int_{0}^{1} x^2\, dx}\) when
a. \(n = 5\).
b. \(n = 10\).
Solution:
a. discretizing \([0,~1]\) using
we get the following set of points,
\noindent We have,
b. \([0,~1]\) can be discretized using
as follows,
We have,
import numpy as np
def Trapz(f, a, b, N):
'''
Parameters
----------
f : function
DESCRIPTION. A function. Here we use lambda functions
a : float
DESCRIPTION. a is the left side of interval [a, b]
b : float
DESCRIPTION. b is the right side of interval [a, b]
N : int
DESCRIPTION. Number of xn points
Returns
-------
T : float
DESCRIPTION. Numerical Integration of f(x) on [a,b]
through Trapezoidal rule
'''
# discretizing [a,b] into N subintervals
x = np.linspace(a, b, N+1)
# discretizing function f on [a,b]
fn = f(x)
# the increment \delta x
h = (b - a) / N
# Trapezoidal rule
T = (h/2) * np.sum(fn[1:] + fn[:-1])
return T
function [T] = Trapz(f, a, b, N)
%{
Parameters
----------
f : function
DESCRIPTION. A function. Here we use lambda functions
a : float
DESCRIPTION. a is the left side of interval [a, b]
b : float
DESCRIPTION. b is the right side of interval [a, b]
N : int
DESCRIPTION. Number of xn points
Returns
-------
T : float
DESCRIPTION. Numerical Integration of f(x) on [a,b]
through Trapezoidal rule
%}
% discretizing [a,b] into N subintervals
x = linspace(a, b, N+1);
% discretizing function f on [a,b]
fn = f(x);
% the increment \delta x
h = (b - a) / N;
% Trapezoidal rule
T = (h/2) * np.sum(fn(1:N) + fn(1:N-1));
Example: Use the Trapezoid rule and compute
a. \({\displaystyle\int_{0}^{2} \cosh(x)\, dx}\) with \(n = 10\).
b. \({\displaystyle\int_{0}^{2} (1 + \tanh^2(x))\, dx}\) with \(n = 20\).
For each part, calculate the absolute error.
Solution: We have,
a. Here \(n = 10\) and it follows from discretizing \([0,~2]\) using \(h = \dfrac{2}{10} = 0.2\) that
\noindent Now we have,
On the other hand, analytically, this can be calculated easily:
Therefore, the absolute error:
b. Here \(h = \dfrac{2 - 0}{20} = 0.1\) and
and we get,
The exact value here is:
Thus,
\end{enumerate}
# This function would be useful for demonstrating Trapz method
def TrapzPlots(f, a, b, N, ax = False, CL = 'Tomato', EC = 'Blue', Font = False):
fontsize = 14
Fig_Params = ['legend.fontsize','axes.labelsize','axes.titlesize','xtick.labelsize','ytick.labelsize']
Fig_Params = dict(zip(Fig_Params, len(Fig_Params)*[fontsize]))
plt.rcParams.update(Fig_Params)
if not ax:
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(8, 6))
x = np.linspace(a, b, N+1)
y = f(x)
X = np.linspace(a, b, (N**2)+1)
Y = f(X)
_ = ax.plot(X,Y)
for i in range(N):
ax.fill([x[i], x[i], x[i+1], x[i+1]], [0, f(x[i]), f(x[i+1]), 0], facecolor = CL,
edgecolor= EC,alpha=0.3, hatch='', linewidth=1.5)
if Font:
_ = ax.set_title('Trapezoid Rule (N = %i)' % N, fontproperties = Font, fontsize = 14)
else:
_ = ax.set_title('Trapezoid Rule (N = %i)' % N, fontsize = 14)
_ = ax.set_xlim([min(x), max(x)])
_ = ax.set_ylim([0, max(y)])
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
from IPython.display import display, Latex
from hd_Numerical_Integration_Algorithms import Trapz
fig, ax = plt.subplots(nrows=1, ncols= 2, figsize=(15, 6))
ax = ax.ravel()
Colors = ['Tomato', 'Lime']
font = FontProperties()
font.set_weight('bold')
_ = fig.suptitle('Trapezoid rule', fontproperties=font, fontsize = 18)
# a
i = 0
f = lambda x : np.cos(x)**2
a = 0
b = 2
N = 10
int_text = '\\int_{0}^{2} \\cos^2(x)\\, dx ='
TrapzPlots(f= f, a = a, b= b, N = N, ax = ax[i], CL = Colors[i])
Int_trapz = Trapz(f= f, a = a, b= b, N = N)
display(Latex(int_text + '''\\frac {h}{2}\\sum _{n=1}^{%i} \\left(f(x_{n-1})+f(x_{n})\\right) = %.4e''' % (N, Int_trapz)))
del Int_trapz
# b
i = 1
f = lambda x : 1 + np.tan(x)**2
a = 0
b = 2
N = 20
int_text = '\\int_{0}^{2} 1 + \\tanh^2(x)\\, dx ='
TrapzPlots(f= f, a = a, b= b, N = N, ax = ax[i], CL = Colors[i])
Int_trapz = Trapz(f= f, a = a, b= b, N = N)
display(Latex(int_text + '''\\frac {h}{2}\\sum _{n=1}^{%i} \\left(f(x_{n-1})+f(x_{n})\\right) = %.4e''' % (N, Int_trapz)))
del Int_trapz
The following theorem is Theorem 4.5 from [Burden and Faires, 2005].
For the Trapezoid quadrature, if $f$ is twice differentiable, $f''$ is continuous, and $f''(x)\leq M$, then
\begin{equation}\label{Trapezoidal_Error_eq}
E_{h} = \left|\int _{a}^{b}f(x)\,dx - \frac {h}{2}\sum _{j=0}^{n-1} \left(f(x_{j})+f(x_{j+1})\right)\right|
\leq M\,\frac{(b-a)^3}{12n^2} = M\,\frac{(b-a)}{12}h^{2}.
\end{equation}
\begin{proof} Here, we follow the proof provided by [].
Assume that the interval \([a,b]\) is equidistantly spaced as follows,
and let \(h = \Delta x = x_{j+1} - x_{j} = (b-a)/n\) for \(0\leq j \leq n-1\). Then,
Now, define the following for \(1 \leq j \leq n\)
On the other hand, the midpoint of each interval can be denoted as \(c_{j} = (x_{j-1} + x_{j})/2\). Thus,
We also have the observation by the integration by parts:
We can use the integration by parts again and the Fundamental Theorem of Calculus,
It follows that,
Using the above theorem, we have,
Thus, we have,
However, it is easy to show that
Therefore,
Example: Assume that we want to use the Trapezoidal rule to approximate \({\displaystyle\int_{0}^{2} \frac{1}{1+x}\, dx}\). Find the smallest \(n\) for this estimation that produces an absolute error of less than \(5 \times 10^{-6}\). Then, evaluate \({\displaystyle\int_{0}^{2} \frac{1}{1+x}\, dx}\) using the Trapezoidal rule to verify the results.
Solution:
Note that the exact integration can be done as follows,
Now, in order to estimate the minimum \(n\) using Theorem \ref{Trapezoidal_Error}, we need
There are various approaches to determining the maximum of \(f''(x)\) on \([0,~2]\), as we have previously discussed. Here, we can see that the (continuous) function \(f''(x)\) on the interval \([0,~2]\) is decreasing.
Thus,
It follows that
Since \(a = 0\), \(b= 2\), and \(M = 2\), we have,
To test this the above \(n\), let \(n = 517\) (the smallest integer after 516.398).We have,
E = 5e-6
f = lambda x : 1/(x+1) # f(x)
f2 = lambda x : 2/((x+1)**3) # f''(x)
Exact = np.log(3) # Exact Int
a =0; b= 2; x = np.linspace(a, b)
M = max(abs(f2(x)))
N = int(np.ceil(np.sqrt((M*(b-a)**3)/(12* E))))
print('N = %i' % N)
T = Trapz(f, a, b, N) # Trapezoidal rule
Eh = abs(T - Exact)
print('Eh = %.4e' % Eh)
N = 517
Eh = 1.1085e-06
Thus,
Therefore,
On the other hand, the exact value can be obtained using \(\displaystyle \int_{0}^{2} \frac{1}{1+x}\, dx = \ln(3)\). Thus, the absolute error here,
Proposition
For the Trapezoid quadrature from \eqref{trap.equal.eq02}, if \(f\) is twice differentiable and \(f''\) is continuous, then
for some \(\xi \in [a, b]\).
Example: Example: For
use Python/MATLAB show that the order of convergence for the Trapezoid rule is indeed 2 numerically!
To see the order of convergence of this method, we have,
import pandas as pd
a = 0; b = 2; f = lambda x : 1/(x+1); Exact = np.log(3)
N = [10*(2**i) for i in range(1, 10)]
Error_list = [];
for n in N:
T = Trapz(f = f, a = a, b = b, N = n)
Error_list.append(abs(Exact - T))
Table = pd.DataFrame(data = {'h':[(b-a)/n for n in N], 'n':N, 'Eh': Error_list})
display(Table.style.set_properties(subset=['h', 'n'], **{'background-color': 'PaleGreen', 'color': 'Black',
'border-color': 'DarkGreen'}).format(dict(zip(Table.columns.tolist()[-3:], 3*["{:.4e}"]))))
h | n | Eh | |
---|---|---|---|
0 | 1.0000e-01 | 2.0000e+01 | 7.3992e-04 |
1 | 5.0000e-02 | 4.0000e+01 | 1.8513e-04 |
2 | 2.5000e-02 | 8.0000e+01 | 4.6293e-05 |
3 | 1.2500e-02 | 1.6000e+02 | 1.1574e-05 |
4 | 6.2500e-03 | 3.2000e+02 | 2.8935e-06 |
5 | 3.1250e-03 | 6.4000e+02 | 7.2338e-07 |
6 | 1.5625e-03 | 1.2800e+03 | 1.8084e-07 |
7 | 7.8125e-04 | 2.5600e+03 | 4.5211e-08 |
8 | 3.9063e-04 | 5.1200e+03 | 1.1303e-08 |
hd.derivative_ConvergenceOrder(vecs = [Table['Eh'].values], labels = ['Trapezoidal rule'], xlabel = r"$$i$$",
ylabel = "r$E_{h_{i}} / E_{h_{i-1}}$",
title = 'Order of accuracy: Trapezoidal rule',
legend_orientation = 'horizontal')