Skip to main content

Chapter 42 Numerical Integration

Numerical integration is a very important component of scientific computation. In tradition calculus classes, the integrals presented were ones that had antidervatives that could be found relatively easily. However, this is generally not true. For example, if trying to determine
\begin{equation*} \int_0^{2} e^{-x^2} \, dx \end{equation*}
the function \(f(x)=e^{-x^2}\) does not have an antidervative in terms of standard functions. This however it a very important antidervative in that it is related to the normal probability distribution. Because of its importance, we define
\begin{equation*} \text{erf}(x) = \frac{2}{\sqrt{\pi}} \int_0^x e^{-t^2} \, dt \end{equation*}
as the error function it is important to calculate values for it for any value of \(x\text{.}\)

Section 42.1 Trapezoid Rule

The trapezoid rule is one of the most basic numerical integration techniques. A geometric interpretation of numerical integration is to approximate the area under the curve with simpler known areas. In this case, we approximate the curve with a sequence of line segments which make trapezoids. A plot of the approximate integral of \(e^{-x^2}\) on the interval \([0,2]\) is given by
Figure 42.1.
where 4 trapezoids have been used. The area of the a trapezoid like:
Figure 42.2.
can be thought of as the rectangular area \(hy_2\) and the top triangle or
\begin{equation*} A = h y_2 + \frac{1}{2}h (y_1-y_2) = \frac{h}{2}(y_1+y_2) \end{equation*}
and note that if \(y_2 > y_1\) that the area is still the same. The area of the four trapezoids above are:
\begin{align*} A \amp = \frac{0.5}{2} \bigl(e^0 + e^{-0.5^2} \bigr) + \frac{0.5}{2} \bigl(e^{-0.5^2} + e^{-1} \bigr) + \frac{0.5}{2} \bigl(e^{-1} + e^{-1.5^2} \bigr) + \frac{0.5}{2} \bigl(e^{-1.5^2}+ e^{-2^2} \bigr) \\ \amp \approx 0.8806186341245393 \end{align*}
The basic part of the trapezoid method is to use the area of a trapezoid on an interval with width \(h\text{.}\) The area of one of the trapezoids is
\begin{equation*} A_i = \frac{h}{2}(f(x_i)+f(x_{i+1})) \end{equation*}
and then a full approximation will be the sum of these:
\begin{align} A\amp ={\sum_{i=1}^{n-1}} \frac{h}{2}(f(x_i)+f(x_{i+1})) \notag \notag\\ \amp =\frac{h}{2}\left(f(x_0)+f(x_1)+f(x_1)+f(x_2)+ \cdots + f(x_{n-1})+f(x_n)\right)\tag{42.1}\\ \amp =\frac{h}{2}\left( f(x_0) + \biggl(2\sum_{i=1}^{n-1} f(x_i) \biggr) + f(x_n)\right) \tag{42.2} \end{align}
Let’s take a look at doing this in julia. To calculate the value we need a few things: 1) a function, 2) the interval we’re doing the approximation on and 3) the number of trapezoids or subintervals. We presented the following in Chapter 11 as
function trapRule(f::Function, a::Real, b::Real; num::Int=10)
  local h = (b-a)/num
  0.5*h*sum(map(f,a:h:b-h)+map(f,a+h:h:b))
end
  1. The parameter \(h\) is \((b-a)/n\text{.}\)
  2. Line (42.1) can be written as the map of two arrays. And then summed.
This is short and (maybe) sweet, but note that there are two separate arrays created. We have learned throughout this text, that the creation of arrays is often the most expensive part of a calculation. So instead, we will do the following:
function trapRule(f::Function, a::Real, b::Real; num::Int = 10)
  num > 0 || throw(ArgumentError("The number of trapezoids, num, must positive."))
  a < b || throw(ArgumentError("The left endpoint must be less than the right endpoint."))
  local h = (b-a)/num
  (h/2)*(f(a)+f(b)+2*sum(f,LinRange(a+h,b-h,num-1)))
end
Although this looks to be nearly the same, we haven’t created arrays. The LinRange function creates a range, but julia is savvy enough to not create the array to sum over it. See the exercise below. Let’s first redo the example above:
trapRule(x -> exp(-x^2), 0, 2; num=4)
which returns 0.8806186341245393

Check Your Understanding 42.3.

(a)
Find \(\int_0^{1} \sin(x^2)\,dx\) using the trapezoid method for \(4, 10\) and \(20\) points.
(b)
Use the BenchmarkTools and the @btime macro to compare the time of the trapezoid rule using the two functions shown here. Try integrating \(\sin(x^2)\) on \([0,1]\) for \(N=10,000\) subintervals.

Section 42.2 Simpson’s Rule

The trapezoid rule uses straight lines to approximate the function and then integrates the line (or finds the area of the trapezoid). To find a better approximation if we use a quadratic function (parabola) to estimate the function. If we do this, then integrate the resulting parabola, this is called Simpson’s Rule. There are numerous places to find the derivation of this, but the result is
\begin{align*} I \amp = \frac{h}{3} \bigl( f(x_0) + 4 f(x_1) + 2 f(x_2) + 4 f(x_3) + 2 f(x_4) + \cdots + 2 f(x_{n-1}) + f(x_n) \bigr)\\ \amp = \frac{h}{3} \left(f(x_0)+ f(x_{2n}) + 4 \sum_{k=1}^{n} f(x_{2k-1}) + 2\sum_{k=1}^{n+1} x_{2k} \right) \end{align*}
where \(h=(b-a)/n\text{,}\) \(x_k = a + kh\) and it is important that \(n\) is an even number. Similar to the trapezoid rule, we can write Simpson’s rule in julia as
function simpsonsRule(f::Function, a::Real, b::Real, n::Integer = 10)
  n > 0 || throw(ArgumentError("The number of subintervals, n, must be positive."))
  n % 2 == 0 || throw(ArgumentError("The number of subintervals, n, must be even."))
  a < b || throw(ArgumentError("The left endpoint must be less than the right endpoint."))
  local h = (b-a)/n
  xpts = LinRange(a,b,n+1)
  (h/3)*(f(a)+f(b) + 4*sum(f,xpts[2:2:end-1]) + 2*sum(f,xpts[3:2:end-2]))
end
Applying Simpson’s Rule to \(\int_0^3 x^2 \, dx\) as
simpsonsRule(x->x^2,0,3,10)
results in 9.0
It’s interesting to note that this reports the exact value. In fact, Simpson’s rule will numerically integrate any cubic (and lines and quadratics) exactly. If we return to trying to find \(\int_0^2 e^{-x^2} \, dx\) and use Simpson’s Rule, then
simpsonsRule(x -> exp(-x^2), 0, 2, 10)
returns 0.882074876854494.
which is within 5 digits of the true answer.

Subsection 42.2.1 Plotting the Error Function

We can use numerical integration to evaluate the error function at any value, so let’s go ahead and plot it. First, let’s make a function that defines the error function.
function erf(x::Real)
  local area = simpsonsRule(t -> exp(-t^2),0,abs(x),100)
  x > 0 ? area : -1*area
end
where we have used the symmetry of the error function to evaluate it if x is positive or negative. If we don’t check for this, we will get an error because simpsonsRule has a check that the interval needs to be put in as \(a < b\text{.}\) Now, we can plot it with:
fig = lines(-3..3, erf, axis = (title="Plot of the error function",))
which results in
(for accessibility)
Figure 42.4.

Section 42.3 Using the NumericalIntegration package

This package does some basic integration using both Trapezoid and Simpson’s rule discussed above.
using NumericalIntegration
x = LinRange(0,2,101)
y = map(x -> exp(-x^2),x) ## compute an array of y based on each x
v = integrate(x,y)
and the result is 0.8820789488400429.