“Know how to solve every problem that has been solved.” “What I cannot create, I do not understand.” — Richard Feynman

The Dipole Operator & Transition Moments

Quantum Physics

What you need to know first 3 concepts, 2 layers

The requisite-knowledge inventory for this page, bottom-up: the primitives at the base, combined upward until you reach what this page assumes. Skim the layers you already own; start wherever the ground gets unfamiliar.

  1. base
  2. L1
  3. you are here

Point a spectrometer at any gas and the absorption lines are wildly unequal: some transitions blaze, most are invisible. The eigenvalues only tell you where lines can appear. Which ones actually light up is decided by a different matrix entirely — the dipole operator written in the energy eigenbasis. Its off-diagonal elements are the transition moments, and everything downstream — selection rules, bright and dark states, oscillator strengths, the intensities in Casida's equation — is arithmetic on them. Five ways in; read the one that lands.

read it as

Visible light has a wavelength around 5000 Å. A molecule is about 1 Å across. From the molecule's point of view the electric field of the light wave doesn't vary in space at all — it is a uniform field that just oscillates in time, the same at every electron. A uniform field can't grab a molecule by its shape; the only handle it has is the total charge displacement,

That is the electric-dipole approximation: keep the first term in the expansion of the field across the molecule and drop the rest (quadrupole, magnetic dipole, …) as smaller by powers of the size ratio — three or four orders of magnitude each. So when light and matter talk, they talk through . The entire theory of spectra hangs off one operator.

Two solvable cases, checked on a grid

For the harmonic oscillator (in units where ) the whole dipole matrix collapses to one ladder rule:

Smallest case first: . Then , — the ladder gets stronger as you climb, because higher states are spatially fatter and displace more charge. Everything off the ladder is zero: parity kills every even , and the oscillator's special algebra kills too. For the box on the closed form is

with on the diagonal — every state sits at the center on average, so the box has no permanent dipole structure, only transitions. A finite-difference grid knows none of these formulas. It just diagonalizes a tridiagonal matrix (the same setup as the finite-difference oscillator page) and integrates:

import numpy as np
from scipy.linalg import eigh_tridiagonal

def fd_eigs(x, V, nstates):
    """Lowest eigenpairs of -1/2 d^2/dx^2 + V on a grid (Dirichlet walls)."""
    h = x[1] - x[0]
    E, psi = eigh_tridiagonal(1/h**2 + V, -0.5/h**2 * np.ones(len(x)-1),
                              select='i', select_range=(0, nstates-1))
    return E, psi              # columns orthonormal in the discrete inner product

def x_matrix(x, psi):          # <n|x|m> for all pairs at once
    return psi.T @ (x[:, None] * psi)

x = np.linspace(-12, 12, 4001)
E, psi = fd_eigs(x, 0.5 * x**2, 5)      # harmonic oscillator
X = x_matrix(x, psi)

xw = np.linspace(0, 1, 4001)[1:-1]      # infinite square well on [0, 1]
Ew, psiw = fd_eigs(xw, np.zeros_like(xw), 5)
Xw = x_matrix(xw, psiw)
Harmonic oscillator  |<n|x|m>|, grid vs analytic sqrt((n+1)/2) ladder
    0.000000   0.707105   0.000000   0.000002   0.000000
    0.707105   0.000000   0.999995   0.000000   0.000004
    0.000000   0.999995   0.000000   1.224737   0.000000
    0.000002   0.000000   1.224737   0.000000   1.414201
    0.000000   0.000004   0.000000   1.414201   0.000000
  max |grid - analytic| on the ladder : 1.27e-05
  max |<n|x|m>| with Delta n != +-1   : 3.90e-06

Infinite square well  |<n|x|m>|  (n, m = 1..5)
    0.500000   0.180127   0.000000   0.014410   0.000000
    0.180127   0.500000   0.194537   0.000000   0.018380
    0.000000   0.194537   0.500000   0.198507   0.000000
    0.014410   0.000000   0.198507   0.500000   0.200141
    0.000000   0.018380   0.000000   0.200141   0.500000
  max |grid - analytic|               : 5.56e-13
  max same-parity element (n != m)    : 2.79e-13

Read the oscillator matrix like a spectroscopist: the only bright transitions hug the first off-diagonal (0.707105, 0.999995, 1.224737, 1.414201 — the ladder rule to five digits), and the matrix is otherwise empty. The box matrix has more going on: 1↔2 is strong (0.180127, matching exactly), 1↔4 is twelve times weaker, and 1↔3 is a structural zero. Two different potentials, one message — the pattern of zeros is the selection rule.

Two kinds of zero

The output above hides a distinction worth keeping. Refine the grid and watch three numbers for the oscillator:

grid refinement    ladder error   |<0|x|3>| (dynamical)   |<0|x|2>| (parity)
N =   2001         3.31e-05       7.79e-06                2.93e-14
N =   4001         8.27e-06       1.95e-06                3.18e-14
N =   8001         2.07e-06       4.87e-07                8.95e-14
N =  16001         5.17e-07       1.22e-07                1.83e-13

The parity zero sits at on every grid: a symmetric grid inherits the symmetry, so the zero is exact by cancellation, independent of resolution. The zero at is different — parity allows it (0 and 3 have opposite parity), and only the oscillator's ladder algebra forbids it. The discretized oscillator isn't exactly an oscillator, so that element is merely small, and shrinks by 4× per grid halving — clean , the finite-difference signature. Symmetry zeros are properties of the group and survive any approximation that respects the symmetry; dynamical zeros are properties of the specific Hamiltonian and degrade with it. When a "forbidden" line shows up faintly in a real spectrum, the first question is which kind of zero just got broken.

Try First

Each prompt asks a checkable question about the working code or math above — predict an output, derive a sign, state an invariant, find a bug. Commit to an answer before clicking "reveal." That commitment is the whole point: if your answer matched, you understand the piece you were looking at; if it didn't, that's the part worth re-reading.

predict
Without running anything: the grid printed for the oscillator. What is the exact value, and what should be? Then the comparison question: why is twice — what, physically, grows as you climb the ladder?
why does this work
For the box, the grid says vanishes to 13 digits but survives. The box states live on , not a symmetric interval — so where does the parity argument actually bite? And why is the diagonal exactly for every state?
what if
Suppose the coupling operator were instead of (the flavor of a quadrupole or two-photon process). For the harmonic oscillator, which matrix elements are nonzero? Predict the selection rule, then check it against the parity argument.

Where this goes

The transition moment is the raw ingredient; the processed, dimensionless version — one number per line, comparable across any two molecules — is the oscillator strength, which comes with a conservation law (the strengths sum to the number of electrons) that makes a spectrum an audited budget. From there, Casida's equation is the many-electron version of everything on this page: its eigenvalues are the line positions, and its eigenvectors get contracted against exactly these dipole integrals to produce the intensities. The single-particle systems used here have their own pages — the infinite square well and the finite-difference harmonic oscillator — and the validation script is scripts/gen_dipole_transitions.py in the repo.