The Laplacian in Polar Coordinates and the Fourier-Bessel Series
The Laplacian is a differential operator often given the symbol \(\nabla^2\) or \(\Delta\), equivalent to the divergence of the gradient. In Cartesian coordinates, the Laplacian is given by \[ \nabla^2 u = \frac{\partial^2 u}{\partial x^2} + \frac{\partial^2 u}{\partial y^2} + \frac{\partial^2 u}{\partial z^2} \] where \(u\) is a scalar function of the coordinates \(x\), \(y\), and \(z\). In cylindrical coordinates, the Laplacian is given by \[ \nabla^2 u = \frac{1}{r} \frac{\partial}{\partial r} \left( r \frac{\partial u}{\partial r} \right) + \frac{1}{r^2} \frac{\partial^2 u}{\partial \theta^2} + \frac{\partial^2 u}{\partial z^2} \] where \(u\) is a scalar function of the coordinates \(r\), \(\theta\), and \(z\).
The Laplacian models many physical phenomena, such as heat conduction, mechanical vibration, and electrostatics. In this section, we will use the Laplacian to model the vibration of a circular membrane, such as a drumhead. The Laplacian can be shown to be an effective model for membranes that are thin compared to their radius and that do not resist bending (Kreyszig 2011, sec. 12.10). For a circular membrane, the two-dimensional wave equation in polar coordinates is \[ \frac{\partial^2 u}{\partial t^2} = c^2 \nabla^2 u = c^2 \left( \frac{1}{r} \frac{\partial}{\partial r} \left( r \frac{\partial u}{\partial r} \right) + \frac{1}{r^2} \frac{\partial^2 u}{\partial \theta^2} \right) \] where \(u(r,\theta,t)\) is the displacement of the membrane at radius \(r\), angle \(\theta\), and time \(t\), and \(c\) is the wave speed.
Following kreyszig2011, we will explore solutions with radial symmetry, where the displacement \(u\) depends only on the radius \(r\) and time \(t\). In this case, the wave equation simplifies to \[ \frac{\partial^2 u}{\partial t^2} = c^2 \frac{1}{r} \frac{\partial}{\partial r} \left( r \frac{\partial u}{\partial r} \right). \] Expanding the derivatives gives \[ \frac{\partial^2 u}{\partial t^2} = c^2 \left( \frac{\partial^2 u}{\partial r^2} + \frac{1}{r} \frac{\partial u}{\partial r} \right). \qquad{(1)}\]
Consider the radially symmetric wave equation in polar coordinates, given by [@eq:wave-eq-polar-symmetric], for a circular membrane with radius R = 1 and wave speed c = 2π rad/s. The displacement of the membrane is u(r,t), where r is the radius and t is time. The boundary conditions are
- At the edge of the membrane, r = R, the membrane is fixed, so u = 0.
- At the center of the membrane, r = 0, the membrane is free to move, but the displacement is finite, so |u| < ∞.
The initial conditions are
- The membrane is at rest at t = 0, so ∂u/∂t = 0.
- The membrane is displaced at t = 0, so u = f(r), where f(r) = 1 − (r/R)3.
Develop a series solution for the displacement of the membrane, u(r,t).
We will assume a product solution of the form up(r,t) = W(r)G(t). Substituting this into the wave equation [@eq:wave-eq-polar-symmetric] gives $$\begin{align} \frac{\partial^2}{\partial t^2} (W G) &= c^2 \left( \frac{\partial^2}{\partial r^2} (W G) + \frac{1}{r} \frac{\partial}{\partial r} (W G) \right) \implies \\ W \frac{\partial^2 G}{\partial t^2} &= c^2 \left( G \frac{\partial^2 W}{\partial r^2} + \frac{1}{r} G \frac{\partial W}{\partial r} \right). \end{align}$$ Using Ġ = ∂G/∂t and W′ = ∂W/∂r, we rewrite this as $$ W \ddot{G} = c^2 \left( G W'' + \frac{1}{r} G W' \right), $$ which can be separated into two ordinary differential equations by dividing by c2WG: $$ \frac{\ddot{G}}{c^2 G} = \frac{W''}{W} + \frac{1}{r} \frac{W'}{W}. $$
The left-hand side depends only on t, and the right-hand side depends only on r. Therefore, both sides must be equal to a constant, which we will call − k2. This gives two ordinary differential equations, one for time and one for radius. The time equation is, letting λ ≡ ck, $$ \ddot{G} + \lambda^2 G = 0, $$ which is the familiar harmonic oscillator equation with solutions G(t) = Acos (λt) + Bsin (λt).
The radial equation is $$ W'' + \frac{1}{r} W' + k^2 W = 0, $$ which can be transformed into the Bessel equation (see example) by changing variables to s = kr. Apply the chain rule to find $$ W' = \frac{d W}{d r} = \frac{d W}{d s} \frac{d s}{d r} = k \frac{d W}{d s}, $$ and therefore W″ = k2d2W/ds2. Substitute these into the radial equation to get $$ k^2 \frac{d^2 W}{d s^2} + \frac{1}{r} k \frac{d W}{d s} + k^2 W = 0 \implies \frac{d^2 W}{d s^2} + \frac{1}{s} \frac{d W}{d s} + W = 0, $$ which is the Bessel equation with ν = 0. From example, we know that the general solution to the Bessel equation is W(s) = aJ0(s) + bY0(s), where J0(s) and Y0(s) are order-0 Bessel functions of the first and second kind, respectively. The boundary condition |u| < ∞ at r = 0 requires b = 0, so the general solution for W(s) is W(s) = aJ0(s). The boundary condition u = 0 at r = R requires J0(kR) = 0. Zeros of the Bessel function J0(s) are denoted by α0, m, so the values of k are $$ k_m = \frac{\alpha_{0,m}}{R} $$ and the eigenfunctions are um(r,t) = (Amcos(λmt)+Bmsin(λmt))J0(kmr), where the eigenvalues are λm = ckm.
Applying the initial condition u′(r,0) = 0 gives $$\begin{align} \left.\frac{\partial u}{\partial t}\right|_{t=0} &= -A_m \lambda_m \sin\left(\lambda_m 0\right) + B_m \lambda_m \cos\left(\lambda_m 0\right) J_0(k_m r) \implies \\ 0 &= B_m \lambda_m J_0(k_m r) \implies \\ B_m &= 0. \end{align}$$ Applying the initial condition u(r,0) = f(r) gives $$\begin{align} u(r,0) &= A_m \cos\left(\lambda_m 0\right) J_0(k_m r) \implies \\ &= A_m J_0(k_m r). \end{align}$$ We can choose Am such that u(r,0) = f(r) in the rare cases where f(r) is a Bessel function. Instead, we will use the orthogonality of the Bessel functions to find a series representation of f(r) in terms of the eigenfunctions um(r,t); that is, we will find Am such that $$ f(r) = \sum_{m=1}^\infty A_m J_0(k_m r). $$ So Am are the Fourier-Bessel coefficients of f(r), $$ A_m = \frac{\langle f, f_m \rangle_{w=r}}{\langle f_m, f_m \rangle_{w=r}}, $$ with weight function w = r, interval [0,R], and fm(r) = J0(kmr). The inner products are given from the definition of the inner product, $$\begin{align} \langle f, f_m \rangle_{w=r} &= \int_0^R f(r) f_m(r) r \, dr, \\ \langle f_m, f_m \rangle_{w=r} &= \int_0^R f_m(r)^2 r \, dr. \end{align}$$
We proceed in Python. First, load packages.
import numpy as np
import sympy as sp
import scipy
from scipy.special import jn_zeros
import matplotlib.pyplot as plt
The inner products are computed as follows:
= sp.symbols("r", real=True, nonnegative=True)
r = sp.symbols("k_m, R", real=True, positive=True)
k_m, R = 1 - (r/R)**3 # Initial condition
f = sp.besselj(0, k_m * r) # Eigenfunction
f_m = r # Weight function of the inner product
w = sp.integrate(f * f_m * w, (r, 0, R)) # $\langle f, f_m \rangle$
inner_f_fm = sp.integrate(f_m**2 * w, (r, 0, R)) # $\langle f_m, f_m \rangle$
inner_fm_fm = (inner_f_fm / inner_fm_fm).simplify() A_m
The values of km, eigenvalues λm = ckm, and the series components Am can be computed from the zeros of the Bessel function zeros α0, m, where m = 1, 2, 3, … as follows:
= sp.symbols("c", real=True, positive=True)
c = 5 # Number of Bessel function zeros
n_zeros = {R: 1, c: 2*np.pi} params
The partial sum of the series can be defined as the sum of the first n terms of the series:
def f_partial_sum_t(r, t, n, A_m, params):
= jn_zeros(0, n) # Bessel function zeros
alphas = alphas / params[R]
ks = params[c] * ks
lambdas = np.zeros(n) # Numerical vals of the series comp.
A_m_ = np.zeros((len(r), len(t)))
f_partial for i in range(n):
= A_m.subs(k_m, ks[i]).subs(params).evalf()
A_m_[i] = scipy.special.jn(0, ks[i] * r[:, None])
f_m += A_m_[i] * f_m * np.cos(lambdas[i] * t)
f_partial return f_partial
Plot the partial sum of the series and compare it to the initial condition.
= np.linspace(-params[R], params[R], 101)
r_plt = np.array([0])
t_plt = 1 - (np.abs(r_plt)/params[R])**3
f_num = f_partial_sum_t(r_plt, t_plt, n_zeros, A_m, params)
f_partial = plt.subplots()
fig, ax ="$f$")
ax.plot(r_plt, f_num, label="$f_{\mathrm{partial}}$")
ax.plot(r_plt, f_partial, label'$r$')
ax.set_xlabel(
ax.legend() plt.draw()
The result is quite good, even with only five terms in the series.
We can now plot the partial sum over one period.
= plt.get_cmap('viridis')
cmap = 101
n_snapshots = np.linspace(0, 1, n_snapshots)
t_plt = np.linspace(-params[R], params[R], 201)
r_plt = f_partial_sum_t(r_plt, t_plt, n_zeros, A_m, params)
f_partial = plt.subplots()
fig, ax for i in range(n_snapshots):
# Label 5 snapshots
= None
label if i % 20 == 0:
= f"$t = {t_plt[i]:.2f}$"
label =label,
ax.plot(r_plt, f_partial[:, i], label=cmap(i / n_snapshots), alpha=1)
color'$r$')
ax.set_xlabel('Displacement u(r, t)')
ax.set_ylabel(='upper right')
ax.legend(loc plt.show()
Online Resources for Section 7.5
No online resources.