A rotating molecule is a particle on a sphere¶
Lecture 4.4 reduced a rigid dumbbell to one particle of reduced mass on a circle. Let the dumbbell point in any direction and the particle moves on a sphere of radius , the bond length. The potential energy does not change as the molecule turns, so all of its energy is the kinetic energy of rotation, :
Lecture 4.4 already found the eigenfunctions of , the spherical harmonics, so the problem is solved. For rotating molecules, spectroscopists write and in place of and :
Source
# synced: rotor_levels
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from IPython.display import HTML
TEAL, CARDINAL, GRAY, PURPLE, ORANGE = "#107895", "#C8102E", "#6c757d", "#6a3d9a", "#e07b00"
fig, ax = plt.subplots(figsize=(5.6, 4.4))
w, g = 0.3, 0.1 # width of one state's bar, gap between bars
for J in range(6):
E = J * (J + 1)
n = 2 * J + 1
x0 = -0.5 * (n * w + (n - 1) * g)
for k in range(n):
ax.plot([x0 + k * (w + g), x0 + k * (w + g) + w], [E, E], color=PURPLE, lw=3, solid_capstyle="butt")
ax.text(-2.6, E, rf"$J = {J}$", ha="right", va="center", fontsize=19)
ax.text(2.6, E, "0" if J == 0 else rf"${E}\tilde{{B}}$", ha="left", va="center", fontsize=19, color=PURPLE)
ax.set_xlim(-4.6, 4.3); ax.set_ylim(-1.5, 32); ax.axis("off")
fig.subplots_adjust(left=0.01, right=0.99, top=0.99, bottom=0.01)
plt.show()
Fig. The levels of a rigid rotor, in units of the rotational constant (defined below). Level holds states, one bar for each value of .
The gaps grow. : two, four, six, ... times . Each step up in rotation costs more than the last.
No zero-point energy. has . is the same in every direction: the bond axis points anywhere with equal probability, and nothing rotates. As on the ring of Lecture 4.4, no wall and no potential squeezes the wavefunction. A vibrating bond, by contrast, always keeps (Lecture 4.2).
What a state describes. is the probability density for the bond axis to point in the direction .
Spectroscopists count in wavenumbers¶
As for vibrations in Lecture 4.3, divide each energy by :
Rotation is cheap¶
| molecule | (cm) | vibration (cm) | at 300 K |
|---|---|---|---|
| H | 60.9 | 4161 | 3.4 |
| HCl | 10.6 | 2886 | 20 |
| CO | 1.93 | 2143 | 108 |
| I | 0.037 | 213 | 5600 |
Rotational steps are a hundred to ten thousand times smaller than vibrational ones. At room temperature cm is far above , so many levels are occupied (below), while nearly every molecule sits in (Lecture 4.1).
The light hydrides have the largest : the moment of inertia depends on the reduced mass, which a hydrogen atom keeps small.
Which transitions light can drive¶
A rotating dipole is an antenna¶
Light pushes on the dipole moment of a molecule (Lecture 4.3). A polar diatomic such as HCl or CO carries a permanent dipole along its axis. As the molecule turns, the dipole turns with it: seen along any fixed direction it oscillates at the rotation frequency, and it can exchange energy with light at that frequency. A nonpolar molecule (H, N, O, CO, CH) has no permanent dipole, so its rotation is invisible in absorption. (Raman spectroscopy still sees it, through the polarizability.)
One rung at a time: ¶
A field along pushes on the component of the dipole, , where is the angle between the bond axis and . The transition dipole of Lecture 4.3 becomes an integral over orientations:
From : exactly. The function the field produces is a state, so is the only level it reaches.
In general, is a mixture of and (a recursion of the spherical harmonics), so changes by one and stays. Light polarized in the plane couples through and changes by one as well.
Physically, a photon carries one unit of angular momentum. Absorbing it changes the molecule’s angular momentum by exactly one unit.
Source
# synced: rotor_selection
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from IPython.display import HTML
TEAL, CARDINAL, GRAY, PURPLE, ORANGE = "#107895", "#C8102E", "#6c757d", "#6a3d9a", "#e07b00"
plt.rcParams.update({"axes.spines.top": False, "axes.spines.right": False})
th = np.linspace(0, np.pi, 801)
dth = th[1] - th[0]
Y0 = np.full_like(th, 1 / np.sqrt(4 * np.pi))
Y1 = np.sqrt(3 / (4 * np.pi)) * np.cos(th)
Y2 = np.sqrt(5 / (16 * np.pi)) * (3 * np.cos(th) ** 2 - 1)
cases = [(r"$J = 0 \to 1$", Y1, 1, "allowed"), (r"$J = 0 \to 2$", Y2, 2, "lobes cancel, forbidden")]
fig, axes = plt.subplots(2, 2, figsize=(9.6, 3.7), gridspec_kw={"height_ratios": [0.85, 1], "hspace": 0.62, "wspace": 0.12})
for (ax, bx), (title, Yj, n, verdict) in zip(axes.T, cases):
ax.axhline(0, color=GRAY, lw=0.8)
ax.plot(th, Y0, color=GRAY, lw=1.8, ls="--")
ax.plot(th, Yj, color=TEAL, lw=2.2)
ax.plot(th, 0.3 * np.cos(th), color=CARDINAL, lw=2.6)
for xk, lab, col in ((1.0, r"$Y_0^0$", GRAY), (1.55, r"$\cos\theta$", CARDINAL), (2.15, rf"$Y_{n}^0$", TEAL)):
ax.text(xk, 0.5, lab, color=col, fontsize=15, ha="center", va="center")
ax.set_title(title, loc="left", fontsize=16)
f = 2 * np.pi * Yj * np.cos(th) * Y0 * np.sin(th) # the phi integral gives 2 pi
area = np.sum(f) * dth
bx.fill_between(th, f, 0, where=f > 0, color=PURPLE, alpha=0.45, lw=0)
bx.fill_between(th, f, 0, where=f < 0, color=ORANGE, alpha=0.55, lw=0)
bx.plot(th, f, color="k", lw=1.6)
bx.axhline(0, color=GRAY, lw=0.8)
bx.set_title(rf"multiply: $Y_{n}^0\,\cos\theta\;Y_0^0\,\sin\theta$", loc="left", fontsize=15)
bx.set_xlabel(("area = 0" if abs(area) < 1e-3 else f"area = {abs(area):.2f}") + f": {verdict}", fontsize=15,
color=PURPLE if abs(area) > 1e-3 else GRAY, weight="bold")
for a in (ax, bx):
a.set_xlim(0, np.pi); a.set_yticks([]); a.spines["left"].set_visible(False)
ax.set_xticks([]); ax.spines["bottom"].set_visible(False)
bx.set_xticks([0, np.pi / 2, np.pi]); bx.set_xticklabels(["0", r"$\pi/2$", r"$\pi$"]); bx.tick_params(labelsize=12)
ax.set_ylim(-0.62, 0.62); bx.set_ylim(-0.75, 0.75)
fig.subplots_adjust(left=0.02, right=0.99, top=0.9, bottom=0.16)
plt.show()
Fig. Why changes by one. Top: the state (gray dashed), the factor from the dipole along the bond axis (red), and a final state (teal), against the angle between the axis and the field. Bottom: their product times from the surface element; its area is the transition dipole over . It is for and zero for , whose lobes cancel.
The microwave spectrum¶
Absorption from to takes a photon of wavenumber
Source
# synced: microwave_lines
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from IPython.display import HTML
TEAL, CARDINAL, GRAY, PURPLE, ORANGE = "#107895", "#C8102E", "#6c757d", "#6a3d9a", "#e07b00"
plt.rcParams.update({"axes.spines.top": False, "axes.spines.right": False})
fig, (ax, bx) = plt.subplots(1, 2, figsize=(9.6, 4.0), gridspec_kw={"width_ratios": [0.85, 1.3], "wspace": 0.22})
for J in range(6):
E = J * (J + 1)
ax.hlines(E, 0, 6.2, color=PURPLE, lw=2.6)
ax.text(-0.15, E, rf"$J = {J}$", ha="right", va="center", fontsize=12.5)
for J in range(5):
x = 0.9 + 1.05 * J
ax.annotate("", xy=(x, (J + 1) * (J + 2)), xytext=(x, J * (J + 1)),
arrowprops=dict(arrowstyle="-|>", color=ORANGE, lw=2.2, mutation_scale=15, shrinkA=0, shrinkB=0))
ax.text(x + 0.14, 0.5 * (J * (J + 1) + (J + 1) * (J + 2)), rf"${2 * (J + 1)}\tilde{{B}}$", fontsize=12,
color=ORANGE, va="center", bbox=dict(fc="white", ec="none", pad=0.5))
ax.set_xlim(-1.6, 6.4); ax.set_ylim(-1.5, 32); ax.axis("off")
for J in range(5):
bx.vlines(2 * (J + 1), 0, 1, color=ORANGE, lw=3)
bx.text(2 * (J + 1), 1.05, rf"${J}\to{J + 1}$", ha="center", va="bottom", fontsize=12, color=ORANGE)
bx.annotate("", xy=(6, 0.5), xytext=(4, 0.5), arrowprops=dict(arrowstyle="<->", color=GRAY, lw=1.4, shrinkA=2, shrinkB=2))
bx.text(5, 0.55, r"$2\tilde{B}$", ha="center", va="bottom", fontsize=14, color=GRAY)
bx.set_xlim(0, 11.5); bx.set_ylim(0, 1.35); bx.set_yticks([])
bx.spines["left"].set_visible(False)
bx.set_xticks([0, 2, 4, 6, 8, 10]); bx.set_xticklabels(["0", r"$2\tilde{B}$", r"$4\tilde{B}$", r"$6\tilde{B}$",
r"$8\tilde{B}$", r"$10\tilde{B}$"])
bx.tick_params(labelsize=12.5)
bx.set_xlabel(r"wavenumber $\tilde{\nu}$", fontsize=13)
fig.subplots_adjust(left=0.01, right=0.99, top=0.95, bottom=0.14)
plt.show()
Fig. Left: absorptions climb one rung at a time, with gaps , , , .... Right: the lines they make, evenly spaced by .
The gaps grow by the same amount each step, so the lines are evenly spaced: the fingerprint of a rotating molecule. Measure the spacing and you have , then , then the bond length.
Lines between 1 and 100 cm have frequencies from 30 GHz to 3 THz: microwaves and the far infrared.
Swapping C for C leaves the bond length alone but raises , so every line moves (Problem 1). Radio astronomers map the cold gas between the stars through CO’s 115 GHz line.
Line intensities follow the populations¶
How strong a line is depends first on how many molecules start in level . The Boltzmann factor with the degeneracy gives:
Source
# synced: rotor_populations
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from IPython.display import HTML
TEAL, CARDINAL, GRAY, PURPLE, ORANGE = "#107895", "#C8102E", "#6c757d", "#6a3d9a", "#e07b00"
plt.rcParams.update({"axes.spines.top": False, "axes.spines.right": False})
hck, T = 1.438777, 300.0 # hc/k_B in cm K
LIGHT = "#cdb9e3"
fig, axes = plt.subplots(1, 2, figsize=(9.6, 3.6), gridspec_kw={"width_ratios": [1, 1.6], "wspace": 0.12})
for ax, (name, B, Jn) in zip(axes, (("HCl", 10.44, 16), ("CO", 1.9225, 31))):
J = np.arange(Jn)
allJ = np.arange(400)
q = np.sum((2 * allJ + 1) * np.exp(-hck * B * allJ * (allJ + 1) / T))
f = (2 * J + 1) * np.exp(-hck * B * J * (J + 1) / T) / q
top = int(np.argmax(f))
ax.bar(J, f, width=0.75, color=[PURPLE if j == top else LIGHT for j in J])
ax.text(top, f[top] + 0.004, rf"$J = {top}$", ha="center", va="bottom", fontsize=13, color=PURPLE)
ax.set_title(name, fontsize=15, loc="left")
ax.set_xlabel("$J$", fontsize=13)
ax.set_ylim(0, f.max() * 1.22); ax.tick_params(labelsize=11.5)
ax.set_xlim(-0.8, Jn - 0.2)
axes[0].set_ylabel("fraction of molecules", fontsize=12.5)
fig.subplots_adjust(left=0.08, right=0.99, top=0.9, bottom=0.15)
plt.show()
Fig. The fraction of molecules in each rotational level at 300 K, for HCl ( cm) and CO ( cm). The most populated level is darker.
The degeneracy rises and the Boltzmann factor falls, so the populations peak: at for HCl and for CO at room temperature (Problem 3 finds the peak). The heavier molecule spreads over more levels.
Each absorption line inherits the population of its starting level. (For microwave lines the photon energy adds a factor that pushes the strongest line a few higher.)
numpy checks the HCl populations:
import numpy as np
B, T = 10.44, 300.0 # HCl: rotational constant (cm^-1) and temperature (K)
hc_k = 1.4388 # hc/k_B in cm K
J = np.arange(0, 40)
N = (2 * J + 1) * np.exp(-hc_k * B * J * (J + 1) / T)
print("N_J / N_0 for J = 0 to 7:", np.round(N[:8] / N[0], 2))
print("most populated J:", N.argmax(), " fraction of molecules there:", round(N.max() / N.sum(), 3))N_J / N_0 for J = 0 to 7: [1. 2.71 3.7 3.84 3.31 2.45 1.59 0.91]
most populated J: 3 fraction of molecules there: 0.189
Rotation rides on vibration: infrared bands¶
An infrared photon changes (Lecture 4.3), but the molecule is also rotating, and a photon must change by one as well. The energies add (Lecture 4.1):
Starting from , a photon can reach or :
Source
# synced: rovib_branches
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from IPython.display import HTML
TEAL, CARDINAL, GRAY, PURPLE, ORANGE = "#107895", "#C8102E", "#6c757d", "#6a3d9a", "#e07b00"
plt.rcParams.update({"axes.spines.top": False, "axes.spines.right": False})
B, nu0, hck, T = 10.59, 2886.0, 1.438777, 300.0 # HCl as a rigid rotor and harmonic oscillator
Jn = 5
s = 0.5 # drawing units per cm^-1 of rotational energy
y1 = 185.0 # where the v = 1 ladder starts (energy axis broken)
lines = [("R", J, nu0 + 2 * B * (J + 1)) for J in range(Jn - 1)] + [("P", J, nu0 - 2 * B * J) for J in range(1, Jn)]
fig, (ax, bx) = plt.subplots(2, 1, figsize=(9.6, 5.8), sharex=True, gridspec_kw={"height_ratios": [2.6, 1], "hspace": 0.04})
x0, x1 = 2780, 2990
for J in range(Jn):
E = B * J * (J + 1) * s
ax.hlines(E, x0, x1, color=PURPLE, lw=1.8)
ax.hlines(y1 + E, x0, x1, color=PURPLE, lw=1.8)
ax.text(x1 + 2, E, rf"$J = {J}$", va="center", fontsize=11)
ax.text(x1 + 2, y1 + E, rf"$J = {J}$", va="center", fontsize=11)
ax.text(x0 - 3, 0.5 * B * 12 * s, "$v = 0$", ha="right", va="center", fontsize=14, color=TEAL)
ax.text(x0 - 3, y1 + 0.5 * B * 12 * s, "$v = 1$", ha="right", va="center", fontsize=14, color=TEAL)
for br, J, nu in lines:
J2 = J + 1 if br == "R" else J - 1
ax.annotate("", xy=(nu, y1 + B * J2 * (J2 + 1) * s), xytext=(nu, B * J * (J + 1) * s),
arrowprops=dict(arrowstyle="-|>", color=ORANGE if br == "R" else TEAL, lw=1.8, mutation_scale=12,
shrinkA=0, shrinkB=0))
ax.axvline(nu0, color=GRAY, lw=1, ls=(0, (4, 3)))
ax.set_xlim(x0 - 40, x1 + 25); ax.set_ylim(-6, y1 + B * 20 * s + 6); ax.axis("off")
for br, J, nu in lines:
S = J + 1 if br == "R" else J
I = S * np.exp(-hck * B * J * (J + 1) / T)
bx.vlines(nu, 0, I, color=ORANGE if br == "R" else TEAL, lw=3)
bx.text(nu, I + 0.12, f"{br}({J})", ha="center", va="bottom", fontsize=11.5, color=ORANGE if br == "R" else TEAL)
bx.axvline(nu0, color=GRAY, lw=1, ls=(0, (4, 3)))
bx.text(nu0 + 3, 3.2, r"$\tilde{\nu}_0$", ha="left", va="bottom", fontsize=13, color=GRAY)
bx.set_ylim(0, 4.0); bx.set_yticks([]); bx.spines["left"].set_visible(False)
bx.tick_params(labelsize=11.5)
bx.set_xlabel(r"wavenumber (cm$^{-1}$)", fontsize=12.5)
fig.subplots_adjust(left=0.01, right=0.99, top=0.99, bottom=0.1)
plt.show()
Fig. Top: the rotational ladders of and (the gap between them is not to scale). R transitions (orange) end one rung higher, P transitions (teal) one rung lower. Bottom: the lines they make, lined up under the arrows, for HCl at 300 K. The two branches have lines apart, with a gap at the band origin .
The gap. R(0) and P(1) are apart, twice the usual spacing: the missing line at would need . Molecules with extra angular momentum about the axis, such as NO or the bend of CO, do show a central Q branch.
The envelopes. The heights follow the populations of the starting levels, so each branch rises and falls like the curve of the last section.
Try it: pick a molecule and change the temperature. Heat spreads the molecules over higher , so the branches widen; the “real molecule” setting adds the corrections of the next section.
Beyond the rigid rotor¶
The bond is longer in ¶
A real bond stretches more easily than it compresses (the Morse well of Lecture 4.3), so the average bond length grows with , and shrinks:
For HCl, and cm. With in the upper level and in the lower one, the branches are no longer evenly spaced:
Since , the R lines crowd together at high and the P lines spread apart.
Pairs of lines that share an upper or a lower level give and separately (combination differences).
Fast rotation stretches the bond¶
A rapidly spinning molecule stretches, like a mass on a spring swung in a circle. Its moment of inertia grows and its levels fall slightly below :
The centrifugal distortion constant is tiny, about : a stiff bond barely stretches (Problem 7).
| effect | origin | grows with | signature |
|---|---|---|---|
| depends on | the bond is longer on average in higher | vibrational level | R lines crowd, P lines spread |
| centrifugal distortion | fast rotation stretches the bond | rotational level | levels and lines fall slightly at high |
Bigger molecules¶
Linear molecules (OCS, HCN, CO) rotate like diatomics, with one moment of inertia and the same ladder. CO has no dipole, so it has no microwave spectrum.
Nonlinear molecules turn about three axes (Lecture 4.1), with three moments of inertia. In symmetric tops such as NH two of them are equal, and the levels need a second quantum number. Water, with three different moments, has a famously irregular spectrum. These are beyond this course.
Problems¶
Problem 1: Carbon-13¶
The line of CO is at 115.271 GHz. Predict the line of CO, assuming the same bond length, and compare with the measured 110.201 GHz. Why are such isotope lines useful to astronomers?
Solution
The bond length, and so , does not change; only does, and :
The measured line is at 110.201 GHz, within 0.01%; the small difference comes from vibrational averaging, which also differs slightly between the isotopes. Each isotopologue has its own lines, so astronomers can count CO separately from CO. The main CO line is often so strong that it saturates, while the rarer CO line still reports how much gas there is.
Problem 2: Which molecules have microwave spectra?¶
Which of these have a pure rotational spectrum: HBr, Cl, CO, OCS, HO, CH, NO, CHCl? Explain each answer in one line.
Problem 3: The most populated level¶
Treating as continuous, show that is largest at
Evaluate it for HCl ( cm) and CO ( cm) at 300 K, and for HCl at 1000 K.
Solution
Write and differentiate:
which gives . With cm at 300 K:
HCl, 300 K: , so the most populated level is .
CO, 300 K: , so .
HCl, 1000 K: cm, , so .
Heating or a smaller moves the peak up, but only as a square root.
Problem 4: A thermometer in space¶
In a cold interstellar cloud, CO is at 10 K. Find and . Why can the ratio of the and line strengths serve as a thermometer, and why would a hydride like HCl be a poor one at this temperature?
Problem 5: Deuterium chloride¶
From the HCl constants of Lecture 4.3 (band origin 2886 cm, and cm) and cm, predict and the band origin of DCl. The measured values are 5.45 and 2091 cm.
Solution
Deuterium leaves the bond (its potential) unchanged and only raises the reduced mass:
Rotation. : cm, as measured.
Vibration, first try. Scaling the band origin by gives cm, 1% low.
Vibration, with anharmonicity. The band origin is (Lecture 4.3), and the two terms scale differently: and . So
in agreement with the measurement. The heavier isotope sits lower in the same well, where the well is more nearly parabolic.
Problem 6: The microwave oven¶
A microwave oven runs at 2.45 GHz. Convert this to cm and compare with the lowest rotational absorption of water vapor, near 557 GHz. Does the oven drive a rotational transition of water? What do you think heats the food?
Problem 7: Centrifugal distortion in HCl¶
Estimate for HCl (, cm). How much does it lower the level , and the line , compared with the rigid rotor?
Solution
Problem 8: How fast does a molecule spin?¶
Treat HCl in the level classically, with and . How many turns per second does it make? Compare with its vibrational frequency, Hz. Does the bond have time to vibrate during one turn?