9.6 Boundary value problems in software
Software 9.6.1 (Eigenvalues by shooting). For \(-y'' = \lambda (1 + t)y\), \(y(0) = y(1) = 0\), integrate from \(y(0) = 0\), \(y'(0) = 1\) and find the values of \(\lambda \) at which \(y(1) = 0\):
>>> import numpy as np >>> from scipy.integrate import solve_ivp, quad >>> from scipy.optimize import brentq >>> w = lambda t: 1 + t # -y'' = lam w y, y(0) = y(1) = 0 >>> def end(lam): # shoot from y(0) = 0, y'(0) = 1 ... f = lambda t, z: [z[1], -lam * w(t) * z[0]] ... return solve_ivp(f, (0, 1), [0, 1], rtol=1e-11, atol=1e-12).y[0, -1] ... >>> grid = np.linspace(1, 260, 400); vals = [end(l) for l in grid] >>> shoot = [brentq(end, a, b) for a, b, fa, fb ... in zip(grid, grid[1:], vals, vals[1:]) if fa * fb < 0] >>> np.round(shoot[:4], 4) array([ 6.5484, 26.4649, 59.6742, 106.17 ]) >>> S = quad(lambda t: np.sqrt(w(t)), 0, 1)[0] # WKB: (n pi / S)^2 >>> np.round([(n * np.pi / S)**2 for n in range(1, 5)], 2) array([ 6.64, 26.57, 59.78, 106.28])
Reading the output. The first four eigenvalues are \(6.5484\), \(26.4649\), \(59.6742\) and \(106.17\). The last two lines compare them with the large-\(n\) approximation \(\lambda _n \approx (n\pi /S)^2\), \(S = \int _0^1\sqrt {w}\), of the Liouville–Green (WKB) method: \(6.64, 26.57, 59.78, 106.28\). The approximation is too high by about \(0.1\) for every \(n\), so its relative error falls like \(1/n^2\). Shooting turns the boundary value problem into a sequence of initial value problems, using the existence theory of the earlier sections, and the sign changes of \(y(1)\) bracket the eigenvalues.
MATLAB/Octave: bvp4c with an unknown parameter, or fzero on the shooting function as here.
Software 9.6.2 (Finite differences and the Rayleigh bound). Replace \(-y''\) by the second difference on \(399\) interior points, which turns the problem into the generalised matrix eigenvalue problem \(Ky = \lambda Wy\) with \(W = \operatorname {diag}(1 + t_i)\):
>>> from scipy.linalg import eigh >>> N = 400; h = 1 / N; t = np.linspace(h, 1 - h, N - 1) # interior points >>> K = (np.diag(2 * np.ones(N - 1)) - np.diag(np.ones(N - 2), 1) ... - np.diag(np.ones(N - 2), -1)) / h**2 # -y'', y = 0 at ends >>> lam_fd = eigh(K, np.diag(w(t)), eigvals_only=True)[:4] >>> np.round(lam_fd, 4) array([ 6.5484, 26.4644, 59.6713, 106.161 ]) >>> u = lambda t: t * (1 - t) # Rayleigh trial function >>> num = quad(lambda t: (1 - 2 * t)**2, 0, 1)[0] # integral of u'^2 >>> R = num / quad(lambda t: w(t) * u(t)**2, 0, 1)[0] >>> R, shoot[0] (6.666666666666667, 6.548395305999766)
Reading the output. The matrix eigenvalues agree with the shooting values to four or five digits, the error growing with \(n\) like \(h^2\lambda _n^2\), as the second difference has error \(O(h^2y'''')\). The symmetric matrix \(K\) is the discrete form of the self-adjoint operator, and its eigenvectors are the discrete eigenfunctions drawn in Figure 13. The Rayleigh quotient of the trial function \(t(1 - t)\) is \(6.667\), above \(\lambda _1 = 6.548\) by \(1.8\%\), as Theorem 9.4.1 requires.
MATLAB/Octave: eig(K, W) for the generalised eigenvalue problem.
Software 9.6.3 (An eigenfunction expansion). The sine series of \(f(t) = t(1 - t)\) on \([0, 1]\), the expansion in the eigenfunctions of \(-y'' = \lambda y\), \(y(0) = y(1) = 0\):
>>> f = lambda t: t * (1 - t) # sine series on [0, 1] >>> b = [2 * quad(lambda t: f(t) * np.sin(n * np.pi * t), 0, 1)[0] ... for n in range(1, 8)] >>> np.round(b, 6) array([ 0.258012, 0. , 0.009556, -0. , 0.002064, 0. , 0.000752]) >>> [round(8 / (n * np.pi)**3, 6) if n % 2 else 0 for n in range(1, 8)] [0.258012, 0, 0.009556, 0, 0.002064, 0, 0.000752] >>> s3 = lambda t: sum(bn * np.sin((n + 1) * np.pi * t) ... for n, bn in enumerate(b[:3])) >>> max(abs(s3(x) - f(x)) for x in np.linspace(0, 1, 201)) 0.0029594198519884707
Reading the output. The coefficients \(b_n = 2\int _0^1f(t)\sin n\pi t\,dt\) agree with the exact values \(8/(n\pi )^3\) for odd \(n\) and \(0\) for even \(n\). They decay like \(n^{-3}\), fast, because \(f\) satisfies the boundary conditions and is smooth, and three terms already give a maximum error of \(0.003\) against a maximum value of \(f\) of \(0.25\). A function that did not vanish at the ends would have coefficients decaying only like \(1/n\), and its series would converge slowly and show the Gibbs overshoot.
MATLAB/Octave: integral(@(t) 2*t.*(1 - t).*sin(n*pi*t), 0, 1).
Questions on this section
Stuck on something here? Ask below and it stays attached to this topic.