Sparse Matrices & Large Systems (scipy.sparse)
In 1D, 2D, and 3D finite-difference or finite-element simulations with unknowns, each node interacts only with a few neighbors. Storing a dense matrix requires of RAM, whereas a sparse matrix uses only a few megabytes.
1. Sparse Matrix Formats in SciPy
| Format | Name | Best For |
|---|---|---|
coo_matrix / coo_array | Coordinate | Building matrices from (row, col, data) triplets |
csr_matrix / csr_array | Compressed Sparse Row | Fast row slicing, matrix-vector products A @ x, arithmetic |
csc_matrix / csc_array | Compressed Sparse Column | Fast column slicing, sparse linear solves (spsolve) |
dia_matrix / dia_array | Diagonal | Banded finite-difference stencils |
Always build matrices in coo_matrix or diags(), and convert to .tocsr() or .tocsc() before performing matrix multiplications or calling solvers.
Constructing and Inspecting Sparse Matrices
Example
Output:
2. Solving Large Sparse Systems (scipy.sparse.linalg)
SciPy provides both direct and iterative solvers for sparse systems A x = b:
Direct Solver (spsolve)
Exact factorization via SuperLU. Highly efficient for 1D and moderate 2D grids:
from scipy.sparse.linalg import spsolve
x = spsolve(A.tocsc(), b)Solving a 1D Poisson Boundary Value System
Let’s discretize with boundary conditions using central differences:
Example
Output:
3. Sparse Eigenvalue Problems (eigsh)
When finding the lowest vibrational modes or buckling loads of huge systems, you rarely need all eigenvalues. scipy.sparse.linalg.eigsh (Lanczos algorithm) extracts the few eigenvalues you specify:
Example
Output:
4. Try It Yourself
Problem: Build and Solve a Sparse Diagonal System
Create a tridiagonal matrix of size with 4 on the main diagonal and -1 on both off-diagonals. Solve using sparse.linalg.spsolve.
Show solution
import numpy as np
from scipy import sparse
from scipy.sparse.linalg import spsolve
N = 5
diags = [-np.ones(N-1), 4.0 * np.ones(N), -np.ones(N-1)]
A = sparse.diags(diags, [-1, 0, 1], format="csc")
b = np.ones(N)
x = spsolve(A, b)
print(f"x: {np.round(x, 4)}")