5.4. Midpoint rule#
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}\). Then,
where \(x_{j}^{*} = (x_{j} + x_{j+1})/2\), for \( 0 \leq j \leq n-1\) are the midpoint of the intervals.
In case these points are equally distanced. i.e. \(\Delta x_{n}= h>0\) for \(n\in \{0,1,\ldots,N\}\), the midpoins \(x_{j}^{*}\) will be in the following form
and
import numpy as np
def Midpoint(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
-------
S : float
DESCRIPTION. Numerical Integration of f(x) on [a,b]
through Midpoint rule
'''
# discretizing [a,b] into N subintervals
x = np.linspace(a, b, N+1)
# midpoints
xmid=(x[0:N]+x[1:N+1])/2
# discretizing function f on [a,b]
fn = f(xmid)
# the increment h
h = (b - a)/N
### Trapezoidal rule
M = h * np.sum(fn)
return M
function [M] = Midpoint(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]
% the increment \delta x
h = (b - a) / N;
xm=(x(1:(n-1))+x(2:n))./2;
fx = f(xm);
M = h*sum(fx);
Example: Use the Midpoint rule and compute \({\displaystyle\int_{0}^{1} x^2\, dx}\) when when
a) \(N = 5\),
b) \(N = 10\).
Solution:
a. \(n = 5\): discretizing \([0,~1]\) using \(h = \dfrac{1-0}{5} = 0.2\), we get the following set of points,
and the midpoints are:
\noindent Now, we have,
a. b \(n = 10\): discretizing \([0,~1]\) using \(h = \dfrac{1-0}{10}=0.1\),
and the midpoints are:
Therefore,
Example: Use the Midpoint rule and compute
when
a) \(N = 5\),
b) \(N = 10\).
Solution:
a. \(n = 5\): discretizing \([0,~\pi/4]\) using \(h = \dfrac{\pi/4}{5} = \dfrac{\pi }{20}\), we get the following set of points,
and the midpoints are:
We have,
b. \(n = 10\): Similarly,
Thus, \hlg{\(n = 10\)}. Now, discretizing \([0,~\pi/4]\) using \(h = \dfrac{\pi}{40}\),
and the midpoints are:
We get,
def MidPointPlots(f, a, b, N, ax = False, CL = 'Tomato', EC = 'Blue'):
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)
# midpoints
xmid=(x[0:N]+x[1:N+1])/2
_ = 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)
_ = ax.scatter(xmid, f(xmid), color= 'red', edgecolor = 'Black')
_ = ax.set_xlim([min(x), max(x)])
_ = ax.set_xticks(x)
_ = ax.set_ylim([0, max(y)])
ax1 = ax.twiny()
_ = ax1.set_xlim(a, b)
_ = ax1.set_xticks(xmid)
_ = ax1.tick_params(axis='x', labelcolor= 'Blue', width=3)
_ = ax1.set_xlabel('Midpoints', color='Blue')
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 Midpoint
f = lambda x : np.cos(x)**2
a = 0
b = np.pi/4
N = [5, 10]
#
fig, ax = plt.subplots(nrows=1, ncols=len(N), figsize=(16, 6))
ax = ax.ravel()
Colors = ['Plum', 'GreenYellow']
font = FontProperties()
font.set_weight('bold')
_ = fig.suptitle("Midpoint rule", fontproperties=font, fontsize = 18)
for i in range(len(ax)):
MidPointPlots(f= f, a = a, b= b, N = N[i], ax = ax[i], CL = Colors[i])
Int_trapz = Midpoint(f= f, a = a, b= b, N = N[i])
txt = 'h\sum _{j=1}^{%i} f\\left(a+j\\frac{h}{2}\\right) = %.4e'
display(Latex(txt % (N[i], Int_trapz)))
del Int_trapz
del i
5.4.1. Error Estimation#
Theorem: Error Estimation for Midpoint rule
The error for the Midpoint rule is bounded (in absolute value) by
for some \(\xi \in [a, b]\). Furthermore, if \(|f^{(2)}(x)|\leq M\)
Proof:
The error for subinterval \([x_{i},~x_{i+1}]\) would be,
Note that in the above, we used the mean value theorem for integrals as \((x - c_{i})^2\) always outputs a positive value (sign does not change) that
Now, if you take the sum over the \(n\) intervals, we have,
For the above, note that since \(f\in C^2\), the term \(\frac 1n \sum f''(\xi_i)\) can be seen as an average of values of \(f''(\xi_i)\) and it is located in between the minimum and maximum of \(f''\). According to the intermediate value theorem, it will correspond to \(f''(\xi)\), for some \(\in(a,b)\).
Example: Assume that we want to use the Midpoint 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 Midpoint rule to verify the results.
Solution: We know that
Also,
From Example \ref{Ex.Trap.02}, we know also know that,
It follows from solving the following inequality \eqref{Midpoint_Error_02} that
To test this the above \(n\), let \(n = 366\) (the smallest integer after 365.1484). We have,
import numpy as np
E = 5e-6
# f'(x)
f = lambda x : 1/(x+1)
# f''(x)
f2 = lambda x : 2/((x+1)**3)
Exact = np.log(3)
a =0; b= 2;
x = np.linspace(a, b)
M = max(abs(f2(x)))
N = int(np.ceil(np.sqrt((M*(b-a)**3)/(24* E))))
print('N = %i' %N)
# Trapezoidal rule
T = Midpoint(f, a, b, N)
Eh = abs(T - Exact)
print('Eh = %.4e' % Eh)
N = 366
Eh = 1.1059e-06
Example: For
use Python/MATLAB show that the order of convergence for the Midpoint rule is indeed 2 numerically!
Solution:
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 = Midpoint(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}"]))))
hd.derivative_ConvergenceOrder(vecs = [Table['Eh'].values], labels = ['Midpoint rule'], xlabel = r"$$i$$",
ylabel = " E_{h_{i}} / E_{h_{i-1}}",
title = 'Order of accuracy: Midpoint rule',
legend_orientation = 'horizontal')
h | N | Eh | |
---|---|---|---|
0 | 1.0000e-01 | 2.0000e+01 | 3.6965e-04 |
1 | 5.0000e-02 | 4.0000e+01 | 9.2548e-05 |
2 | 2.5000e-02 | 8.0000e+01 | 2.3145e-05 |
3 | 1.2500e-02 | 1.6000e+02 | 5.7869e-06 |
4 | 6.2500e-03 | 3.2000e+02 | 1.4467e-06 |
5 | 3.1250e-03 | 6.4000e+02 | 3.6169e-07 |
6 | 1.5625e-03 | 1.2800e+03 | 9.0422e-08 |
7 | 7.8125e-04 | 2.5600e+03 | 2.2606e-08 |
8 | 3.9063e-04 | 5.1200e+03 | 5.6514e-09 |