Chebyshev Collocation Method
Spectral Methods
import numpy as np
import scipy.linalg
import scipy.integrate
import matplotlib.pyplot as plt
def set_publication_style():
"""Set publication-quality matplotlib style."""
plt.rcParams.update({
'font.family': 'serif',
'font.size': 12,
'axes.labelsize': 14,
'axes.titlesize': 16,
'axes.linewidth': 1.2,
'axes.labelpad': 8,
'axes.titlepad': 10,
'xtick.labelsize': 12,
'ytick.labelsize': 12,
'xtick.direction': 'in',
'ytick.direction': 'in',
'xtick.top': True,
'ytick.right': True,
'xtick.major.size': 6,
'ytick.major.size': 6,
'xtick.major.width': 1.2,
'ytick.major.width': 1.2,
'legend.fontsize': 12,
'legend.frameon': False,
'lines.linewidth': 2,
'lines.markersize': 6,
'figure.dpi': 100,
'savefig.dpi': 300,
'savefig.bbox': 'tight'
})
set_publication_style()
# Compute Chebyshev-Lobatto points
def chebyshev_points(N):
return np.cos(np.pi * np.arange(N) / (N - 1))
# Compute Chebyshev differentiation matrix
def chebyshev_diff_matrix(N, x):
D = np.zeros((N, N))
c = np.array([2] + [1] * (N - 2) + [2]) * (-1) ** np.arange(N)
for i in range(N):
for j in range(N):
if i != j:
D[i, j] = c[i] / (c[j] * (x[i] - x[j]))
D[i, i] = -np.sum(D[i, :])
return D
# Gaussian elimination with partial pivoting
def gaussian_elimination(A, b):
N = len(b)
for k in range(N):
# Pivot
max_row = np.argmax(np.abs(A[k:, k])) + k
A[[k, max_row]] = A[[max_row, k]]
b[[k, max_row]] = b[[max_row, k]]
# Eliminate
for i in range(k + 1, N):
factor = A[i, k] / A[k, k]
A[i, k:] -= factor * A[k, k:]
b[i] -= factor * b[k]
# Back-substitution
x = np.zeros(N)
for i in range(N - 1, -1, -1):
x[i] = (b[i] - np.dot(A[i, i+1:], x[i+1:])) / A[i, i]
return x
# Solve BVP using Chebyshev collocation method
def solve_bvp(N):
x = chebyshev_points(N)
D = chebyshev_diff_matrix(N, x)
D2 = np.dot(D, D) # Second derivative matrix
# Construct the system: D2 * y - y = f
A = D2 - np.eye(N)
f = np.sin(np.pi * x)
# Apply boundary conditions: y(-1) = 0, y(1) = 0
A = A[1:-1, 1:-1] # Remove first and last rows/columns
f = f[1:-1] # Remove first and last values
# Solve using Gaussian elimination
y_inner = gaussian_elimination(A, f)
# Construct the full solution with boundary conditions
y = np.zeros(N)
y[1:-1] = y_inner
return x, y
# Solve BVP using scipy solver
def solve_bvp_scipy():
def ode_fun(x, y):
return [y[1], y[0] + np.sin(np.pi * x)]
def bc(ya, yb):
return [ya[0], yb[0]]
x_mesh = np.linspace(-1, 1, 100)
y_guess = np.zeros((2, x_mesh.size))
sol = scipy.integrate.solve_bvp(ode_fun, bc, x_mesh, y_guess)
return sol.x, sol.y[0]
# Run for N=16 points
N = 16
x, y = solve_bvp(N)
x_scipy, y_scipy = solve_bvp_scipy()
# Plot result
plt.title(r"Solution of $\frac{d^2 y}{dx^2} - y = \sin(\pi x), \quad y(-1) = 0, \quad y(1) = 0$")
plt.plot(x, y, 'o-', label='Chebyshev collocation')
plt.plot(x_scipy, y_scipy, '-', label='solve_bvp')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.tight_layout() # Automatically adjusts layout
plt.savefig('figures/chebyshev_collocation_solution.png', dpi=300, bbox_inches='tight')
plt.show() Visualization
The following plot shows the solution obtained using the Chebyshev collocation method: