Exercise 2


In [1]:
import numpy
import re
from matplotlib import pyplot
from IPython.display import Latex, Math, display
% matplotlib inline

In [2]:
import os, sys
sys.path.append(os.path.split(os.path.split(os.getcwd())[0])[0])

In [3]:
import utils.quadrature as quad
import utils.poly as poly

(a)

Let $f(x)=x^7$. Evaluate the derivative matrix and the derivatives at quadrature points using Gauss-Lobatto-Legendre quadrature with $Q=7,\ 8,\ 9$.


In [4]:
def f_ex2a(x):
    """f = x^7"""
    
    return x**7

def df_ex2a(x):
    """df/dx = 7 * (x**6)"""
    
    return 7 * (x**6)

In [5]:
def ex2a(Qi, f, df):
    """a wrapper for generating solutions"""
    
    numpy.set_printoptions(
        formatter={'float': "{:5.2e}".format}, linewidth=120)
    
    qd = quad.GaussLobattoJacobi(Qi)
    p = poly.LagrangeBasis(qd.nodes)
    D = p.derivative(qd.nodes)
    ans = D.dot(f(qd.nodes))
    exact = df(qd.nodes)
    err = numpy.abs(ans - exact)
    
    def generateLatex(A):
        return "{\\scriptsize \\left[\\begin{array}{r}" + \
                re.sub(r"[ ]+", "&", re.sub(r"\n[ ]*", "\\\\\\\\", 
                re.sub(r"\][ ]*", "", re.sub(r"\[[ ]*", "", str(A))))) + \
               "\\end{array}\\right]}"
            
    display(Latex("For " + "$Q={0}$".format(Qi) + ":"))
    display(Latex("$\qquad$The derivative matrix is: "))
    display(Math("\\qquad" + generateLatex(D)))
    display(Latex("$\\qquad$The derivatives at quadrature points are: "))
    display(Math("\\qquad" + generateLatex(ans)))
    display(Latex("$\\qquad$The exact derivatives at quadrature points are: "))
    display(Math("\\qquad" + generateLatex(exact)))
    display(Latex("$\\qquad$The absolute errors are: "))
    display(Math("\\qquad" + generateLatex(err)))

In [6]:
for Qi in [7, 8, 9]:
    ex2a(Qi, f_ex2a, df_ex2a)


For $Q=7$:
$\qquad$The derivative matrix is:
$$\qquad{\scriptsize \left[\begin{array}{r}-1.05e+01&1.42e+01&-5.67e+00&3.20e+00&-2.05e+00&1.32e+00&-5.00e-01\\-2.44e+00&-7.33e-15&3.46e+00&-1.60e+00&9.61e-01&-6.02e-01&2.27e-01\\6.25e-01&-2.22e+00&1.29e-15&2.27e+00&-1.07e+00&6.16e-01&-2.26e-01\\-3.12e-01&9.08e-01&-2.01e+00&-0.00e+00&2.01e+00&-9.08e-01&3.12e-01\\2.26e-01&-6.16e-01&1.07e+00&-2.27e+00&-1.29e-15&2.22e+00&-6.25e-01\\-2.27e-01&6.02e-01&-9.61e-01&1.60e+00&-3.46e+00&7.33e-15&2.44e+00\\5.00e-01&-1.32e+00&2.05e+00&-3.20e+00&5.67e+00&-1.42e+01&1.05e+01\end{array}\right]}$$
$\qquad$The derivatives at quadrature points are:
$$\qquad{\scriptsize \left[\begin{array}{r}6.52e+00&2.49e+00&-8.67e-02&1.52e-01&-8.67e-02&2.49e+00&6.52e+00\end{array}\right]}$$
$\qquad$The exact derivatives at quadrature points are:
$$\qquad{\scriptsize \left[\begin{array}{r}7.00e+00&2.29e+00&7.44e-02&0.00e+00&7.44e-02&2.29e+00&7.00e+00\end{array}\right]}$$
$\qquad$The absolute errors are:
$$\qquad{\scriptsize \left[\begin{array}{r}4.85e-01&2.01e-01&1.61e-01&1.52e-01&1.61e-01&2.01e-01&4.85e-01\end{array}\right]}$$
For $Q=8$:
$\qquad$The derivative matrix is:
$$\qquad{\scriptsize \left[\begin{array}{r}-1.40e+01&1.89e+01&-7.57e+00&4.30e+00&-2.81e+00&1.94e+00&-1.30e+00&5.00e-01\\-3.21e+00&-6.10e-14&4.54e+00&-2.11e+00&1.29e+00&-8.69e-01&5.74e-01&-2.20e-01\\7.92e-01&-2.81e+00&2.01e-14&2.88e+00&-1.37e+00&8.45e-01&-5.37e-01&2.03e-01\\-3.72e-01&1.08e+00&-2.38e+00&-6.32e-16&2.39e+00&-1.14e+00&6.61e-01&-2.43e-01\\2.43e-01&-6.61e-01&1.14e+00&-2.39e+00&6.32e-16&2.38e+00&-1.08e+00&3.72e-01\\-2.03e-01&5.37e-01&-8.45e-01&1.37e+00&-2.88e+00&-2.01e-14&2.81e+00&-7.92e-01\\2.20e-01&-5.74e-01&8.69e-01&-1.29e+00&2.11e+00&-4.54e+00&6.10e-14&3.21e+00\\-5.00e-01&1.30e+00&-1.94e+00&2.81e+00&-4.30e+00&7.57e+00&-1.89e+01&1.40e+01\end{array}\right]}$$
$\qquad$The derivatives at quadrature points are:
$$\qquad{\scriptsize \left[\begin{array}{r}7.00e+00&3.07e+00&3.00e-01&5.88e-04&5.88e-04&3.00e-01&3.07e+00&7.00e+00\end{array}\right]}$$
$\qquad$The exact derivatives at quadrature points are:
$$\qquad{\scriptsize \left[\begin{array}{r}7.00e+00&3.07e+00&3.00e-01&5.88e-04&5.88e-04&3.00e-01&3.07e+00&7.00e+00\end{array}\right]}$$
$\qquad$The absolute errors are:
$$\qquad{\scriptsize \left[\begin{array}{r}3.04e-13&8.84e-14&1.92e-14&3.41e-15&3.41e-15&1.92e-14&8.79e-14&3.04e-13\end{array}\right]}$$
For $Q=9$:
$\qquad$The derivative matrix is:
$$\qquad{\scriptsize \left[\begin{array}{r}-1.80e+01&2.43e+01&-9.74e+00&5.54e+00&-3.66e+00&2.59e+00&-1.87e+00&1.28e+00&-5.00e-01\\-4.09e+00&-1.93e-13&5.79e+00&-2.70e+00&1.67e+00&-1.15e+00&8.17e-01&-5.56e-01&2.16e-01\\9.85e-01&-3.49e+00&6.87e-14&3.58e+00&-1.72e+00&1.08e+00&-7.38e-01&4.92e-01&-1.90e-01\\-4.45e-01&1.29e+00&-2.83e+00&-1.43e-14&2.85e+00&-1.38e+00&8.56e-01&-5.47e-01&2.08e-01\\2.73e-01&-7.42e-01&1.27e+00&-2.66e+00&0.00e+00&2.66e+00&-1.27e+00&7.42e-01&-2.73e-01\\-2.08e-01&5.47e-01&-8.56e-01&1.38e+00&-2.85e+00&1.43e-14&2.83e+00&-1.29e+00&4.45e-01\\1.90e-01&-4.92e-01&7.38e-01&-1.08e+00&1.72e+00&-3.58e+00&-4.75e-14&3.49e+00&-9.85e-01\\-2.16e-01&5.56e-01&-8.17e-01&1.15e+00&-1.67e+00&2.70e+00&-5.79e+00&5.99e-14&4.09e+00\\5.00e-01&-1.28e+00&1.87e+00&-2.59e+00&3.66e+00&-5.54e+00&9.74e+00&-2.43e+01&1.80e+01\end{array}\right]}$$
$\qquad$The derivatives at quadrature points are:
$$\qquad{\scriptsize \left[\begin{array}{r}7.00e+00&3.71e+00&6.75e-01&1.60e-02&-7.52e-14&1.60e-02&6.75e-01&3.71e+00&7.00e+00\end{array}\right]}$$
$\qquad$The exact derivatives at quadrature points are:
$$\qquad{\scriptsize \left[\begin{array}{r}7.00e+00&3.71e+00&6.75e-01&1.60e-02&0.00e+00&1.60e-02&6.75e-01&3.71e+00&7.00e+00\end{array}\right]}$$
$\qquad$The absolute errors are:
$$\qquad{\scriptsize \left[\begin{array}{r}2.01e-12&5.80e-13&2.05e-13&9.42e-14&7.52e-14&9.10e-14&1.92e-13&5.12e-13&1.81e-12\end{array}\right]}$$

(b)

The same problem with exercise 2a, except that now the interval on which we apply quadrature is $x \in [2,\ 10]$. Use chain rule to evaluate the derivative at mapped quadrature points.


In [7]:
def ex2b(Qi, f, df):
    """a wrapper for generating solutions"""
    
    numpy.set_printoptions(
        formatter={'float': "{:5.2e}".format}, linewidth=120)
    
    x = lambda xi: (xi + 1) * (10 - 2) / 2. + 2
    dxi_dx = 2. / (10 - 2)
    qd = quad.GaussLobattoJacobi(Qi)
    p = poly.LagrangeBasis(qd.nodes)
    D = p.derivative(qd.nodes)
    ans = D.dot(f(x(qd.nodes))) * dxi_dx
    exact = df(x(qd.nodes))
    err = numpy.abs(ans - exact)
    
    def generateLatex(A):
        return "{\\scriptsize \\left[\\begin{array}{r}" + \
                re.sub(r"[ ]+", "&", re.sub(r"\n[ ]*", "\\\\\\\\", 
                re.sub(r"\][ ]*", "", re.sub(r"\[[ ]*", "", str(A))))) + \
               "\\end{array}\\right]}"
            
    display(Latex("For " + "$Q={0}$".format(Qi) + ":"))
    display(Latex("$\\qquad$The derivatives at quadrature points are: "))
    display(Math("\\qquad" + generateLatex(ans)))
    display(Latex("$\\qquad$The exact derivatives at quadrature points are: "))
    display(Math("\\qquad" + generateLatex(exact)))
    display(Latex("$\\qquad$The absolute errors are: "))
    display(Math("\\qquad" + generateLatex(err)))

In [8]:
for Qi in [7, 8, 9]:
    ex2b(Qi, f_ex2a, df_ex2a)


For $Q=7$:
$\qquad$The derivatives at quadrature points are:
$$\qquad{\scriptsize \left[\begin{array}{r}-1.54e+03&3.41e+03&3.38e+04&3.27e+05&1.67e+06&4.59e+06&7.00e+06\end{array}\right]}$$
$\qquad$The exact derivatives at quadrature points are:
$$\qquad{\scriptsize \left[\begin{array}{r}4.48e+02&2.59e+03&3.45e+04&3.27e+05&1.67e+06&4.59e+06&7.00e+06\end{array}\right]}$$
$\qquad$The absolute errors are:
$$\qquad{\scriptsize \left[\begin{array}{r}1.99e+03&8.24e+02&6.60e+02&6.21e+02&6.60e+02&8.24e+02&1.99e+03\end{array}\right]}$$
For $Q=8$:
$\qquad$The derivatives at quadrature points are:
$$\qquad{\scriptsize \left[\begin{array}{r}4.48e+02&1.76e+03&1.61e+04&1.33e+05&7.15e+05&2.40e+06&5.10e+06&7.00e+06\end{array}\right]}$$
$\qquad$The exact derivatives at quadrature points are:
$$\qquad{\scriptsize \left[\begin{array}{r}4.48e+02&1.76e+03&1.61e+04&1.33e+05&7.15e+05&2.40e+06&5.10e+06&7.00e+06\end{array}\right]}$$
$\qquad$The absolute errors are:
$$\qquad{\scriptsize \left[\begin{array}{r}4.94e-08&2.16e-08&2.03e-08&2.55e-08&4.26e-08&1.07e-07&2.24e-07&1.07e-06\end{array}\right]}$$
For $Q=9$:
$\qquad$The derivatives at quadrature points are:
$$\qquad{\scriptsize \left[\begin{array}{r}4.48e+02&1.34e+03&8.90e+03&6.19e+04&3.27e+05&1.20e+06&3.05e+06&5.48e+06&7.00e+06\end{array}\right]}$$
$\qquad$The exact derivatives at quadrature points are:
$$\qquad{\scriptsize \left[\begin{array}{r}4.48e+02&1.34e+03&8.90e+03&6.19e+04&3.27e+05&1.20e+06&3.05e+06&5.48e+06&7.00e+06\end{array}\right]}$$
$\qquad$The absolute errors are:
$$\qquad{\scriptsize \left[\begin{array}{r}2.45e-07&1.07e-07&9.40e-08&1.05e-07&1.44e-07&2.63e-07&6.46e-07&9.74e-07&6.36e-06\end{array}\right]}$$

(c)

Use the differentiation techniques to numerically integrate $-\int_{0}^{\pi/2}\frac{d}{dx}\cos{(x)}dx$. Plot the error with respect to number of quadrature points, $Q$. Use $2 \le Q \le 8$.


In [9]:
def f_ex2c(x):
    """integrand of exercise 1c"""
    
    return - numpy.cos(x)

In [10]:
def ex2c(Qi, f):
    """a wrapper for generating solutions"""
    
    x = lambda xi: (xi + 1) * (numpy.pi / 2. - 0.) / 2. + 0.
    dxi_dx = 2. / (numpy.pi / 2. - 0.)
    dx_dxi = (numpy.pi / 2. - 0.) / 2.
    qd = quad.GaussLobattoJacobi(Qi)
    p = poly.LagrangeBasis(qd.nodes)
    d = p.derivative(qd.nodes).dot(f(x(qd.nodes))) * dxi_dx
    ans = numpy.sum(d * qd.weights * dx_dxi)
    err = numpy.abs(ans - 1.)
    
    print("The numerical solution is: " +
          "{0}; the absolute error is: {1}".format(ans, err))
    
    return err

In [11]:
Q = numpy.arange(2, 9)
err = numpy.zeros_like(Q, dtype=numpy.float64)
for i, Qi in enumerate(range(2, 9)):
    err[i] = ex2c(Qi, f_ex2c)


The numerical solution is: 0.9999999999999999; the absolute error is: 1.1102230246251565e-16
The numerical solution is: 0.9999999999999998; the absolute error is: 2.220446049250313e-16
The numerical solution is: 0.9999999999999998; the absolute error is: 2.220446049250313e-16
The numerical solution is: 0.999999999999999; the absolute error is: 9.992007221626409e-16
The numerical solution is: 0.9999999999999994; the absolute error is: 5.551115123125783e-16
The numerical solution is: 1.0000000000000018; the absolute error is: 1.7763568394002505e-15
The numerical solution is: 1.0000000000000195; the absolute error is: 1.9539925233402755e-14

In [12]:
pyplot.semilogy(Q, err, 'k.-', lw=2, markersize=15)
pyplot.title("Absolute error of numerical integration of " +
             r"$-\int_{0}^{\pi/2}\frac{d}{dx}\cos{(x)} dx$" + 
             "\n with Gauss-Lobatto-Legendre quadrature", y=1.08)
pyplot.xlabel(r"$Q$" + ", number of quadratiure points")
pyplot.ylabel("absolute error")
pyplot.grid();



In [13]:
def df_ex2c(x):
    """derivative of f"""
    
    return numpy.sin(x)

In [14]:
def ex2c_mod(Qi, f, df):
    """a wrapper for generating solutions"""
    
    x = lambda xi: (xi + 1) * (numpy.pi / 2. - 0.) / 2. + 0.
    dxi_dx = 2. / (numpy.pi / 2. - 0.)
    dx_dxi = (numpy.pi / 2. - 0.) / 2.
    
    qd = quad.GaussLobattoJacobi(Qi)
    p = poly.LagrangeBasis(qd.nodes)
    d = p.derivative(qd.nodes).dot(f(x(qd.nodes))) * dxi_dx - df(x(qd.nodes))
    d *= d
    err = numpy.sqrt(numpy.sum(d * qd.weights * dx_dxi) / (numpy.pi / 2. - 0.))
    
    print("The H1-norm is: {0}: ".format(err))
    
    return err

In [15]:
for i, Qi in enumerate(range(2, 9)):
    err[i] = ex2c_mod(Qi, f_ex2c, df_ex2c)


The H1-norm is: 0.5183290096085398: 
The H1-norm is: 0.09891440790463447: 
The H1-norm is: 0.012800413182384441: 
The H1-norm is: 0.001250205356252559: 
The H1-norm is: 9.79256567059248e-05: 
The H1-norm is: 6.399212463676948e-06: 
The H1-norm is: 3.586485057021394e-07: 

In [16]:
pyplot.semilogy(Q, err, 'k.-', lw=2, markersize=15)
pyplot.title("H1-norm of numerical integration of " +
             r"$-\int_{0}^{\pi/2}\frac{d}{dx}\cos{(x)} dx$" + 
             "\n with Gauss-Lobatto-Legendre quadrature", y=1.08)
pyplot.xlabel(r"$Q$" + ", number of quadratiure points")
pyplot.ylabel("H1-norm")
pyplot.grid();