From differential equation to matrix problem¶
We want the bound states of the time-independent Schrödinger equation on with hard walls, the same boundary conditions as the particle in a box:
Instead of guessing a functional form for , we store its values at evenly spaced grid points, as sketched in Figure 1. On the grid, the second derivative at point is approximated by the classic three-point formula Press et al., 2007:

Figure 1:A wavefunction sampled on a uniform grid between hard walls. The curvature at point is built from the point and its two neighbors (red circles), which turns the differential equation into a matrix problem.
Substituting (2) into (1) gives one linear equation per grid point. Collecting them produces a matrix eigenvalue problem with a tridiagonal Hamiltonian: kinetic energy couples each point only to its two neighbors, and the potential sits on the diagonal.
Diagonalizing hands us energies and wavefunctions in one shot. The LAPACK routines that do this are the same machinery running inside every modern quantum chemistry package.
A box with a barrier inside¶
As a test system we take the unit box and drop a rectangular barrier of height and width into the middle. With , the natural energy unit is the ground-state energy of the empty box from the particle in a box lecture:
For the solver must reproduce exactly, which is a good sanity check. As grows, the box splits into two weakly coupled half-boxes, and pairs of levels squeeze together into doublets: a symmetric state with no node at the center and an antisymmetric partner with one. Their tiny energy difference is the tunneling splitting, the standard textbook route to double-well physics Griffiths & Schroeter, 2018.
The live solver¶
We need only the course’s standard scientific stack: NumPy for arrays, SciPy for the tridiagonal eigensolver, and Matplotlib for plots.
The solver builds the two diagonals of and asks SciPy for the lowest few eigenpairs. Dividing the eigenvectors by normalizes them so that .
Drag the slider to raise or lower the barrier. Everything below it reacts.
With the barrier at zero you should read off , the exact particle in a box ladder. Raise the barrier and watch collapse onto each other while keeping opposite symmetry about the center.
Tunneling doublets across all barrier heights¶
A single click of the slider solves one Hamiltonian. The cell below instead sweeps the full range of barrier heights, a moderately expensive computation: 51 diagonalizations of a matrix, tracking the six lowest states. Because it does not read the slider, marimo executes it once and reuses the cached result no matter how much you play with the plots.
The correlation diagram replots instantly when you move the slider, because only the cheap plotting cell reruns, not the sweep.
How this page works
This demo pilots marimo cells inside the course website. The cells are executed while the site is built, so the page loads with correct static output. The first time you touch the slider, a Python runtime (Pyodide, Python compiled to WebAssembly) downloads in the background along with NumPy, SciPy, and Matplotlib, and from then on all cells rerun locally in your browser. Unlike the ipywidgets demos, nothing needs to run on a server, and unlike static pages, every plot stays live.
- Press, W. H., Teukolsky, S. A., Vetterling, W. T., & Flannery, B. P. (2007). Numerical Recipes: The Art of Scientific Computing (3rd ed.). Cambridge University Press.
- Griffiths, D. J., & Schroeter, D. F. (2018). Introduction to Quantum Mechanics (3rd ed.). Cambridge University Press. 10.1017/9781316995433