Energy contours, enclosed phase-space volume, and finite-width energy shells for a harmonic oscillator in canonical coordinates (q,p), followed by rational and irrational angle trajectories on a two-oscillator fixed-action torus. The guide distinguishes ergodicity on that torus from ergodicity on the full energy surface. See ergodic theory and statistical mechanics.
The interior counts states below E; the annulus counts a finite energy interval; exact-energy dynamics stays on the contour. Opposite edges of each angle plot are identified. An irrational frequency ratio produces a dense trajectory over infinite time, while the drawing shows only a finite segment. Uniform-angle ergodicity applies to the fixed-action torus: uncoupled oscillators conserve their individual actions, so this does not establish microcanonical ergodicity on the full energy surface.
#import "@preview/cetz:0.5.3": canvas, draw
#import draw: circle, content, line, rect
#set page(width: 660pt, height: auto, margin: 20pt, fill: none)
#set text(font: "Avenir Next", size: 14pt, fill: rgb("#19324f"))
#set par(leading: 0.55em)
#let (blue, green, ink, gray) = (rgb("#0b5fa5"), rgb("#286744"), rgb("#19324f"), rgb("#cdd3da"))
#let panel = block.with(
width: 100%,
inset: 12pt,
radius: 7pt,
fill: gray,
breakable: false,
)
// A one-degree-of-freedom oscillator H = p^2/(2m) + k q^2/2 uses canonical coordinates (q,p),
// not two positions. Shell axes are the q and p intercepts of the H = energy ellipse.
#let shell_energy = 1
#let shell_width = .25
#let shell_axes(energy, mass: 1, stiffness: 1) = (
calc.sqrt(2 * energy / stiffness),
calc.sqrt(2 * mass * energy),
)
#let angle_point(time, ratio) = (calc.rem(time, 1), calc.rem(time * ratio, 1))
#let orbit(ratio, turns: 1) = canvas(length: 1pt, {
let (width, height) = (210, 125)
rect((0, 0), (width, height), fill: gray, stroke: rgb("#78828c") + .6pt)
let previous = angle_point(0, ratio)
for step in range(1, turns * 120 + 1) {
let point = angle_point(step / 120, ratio)
// Break at identified edges: never draw a spurious chord across a wrap.
if calc.abs(point.at(0) - previous.at(0)) < .1 and calc.abs(point.at(1) - previous.at(1)) < .1 {
let scaled = (previous, point).map(((x, y)) => (width * x, height * y))
line(..scaled, stroke: blue + .65pt)
}
previous = point
}
content((width / 2, -15), $theta_1: 0 arrow.r 2pi$)
content((-12, 62), rotate(-90deg, reflow: true)[$theta_2: 0 arrow.r 2pi$])
})
#panel[
#text(size: 16pt, weight: "bold")[1 One oscillator: volume, contour, shell]
#v(9pt)
#grid(
columns: (280pt, 1fr),
gutter: 14pt,
align: horizon,
align(center, canvas(length: 1pt, {
let (scale_q, scale_p) = (70, 45)
// Outer edge of the green shell, then the blue H = E contour filling the interior
for (energy, fill, stroke) in (
(shell_energy + shell_width, rgb("#c6d8d2"), green + 1pt),
(shell_energy, gray, blue + 1.5pt),
) {
let (q_max, p_max) = shell_axes(energy)
circle((0, 0), radius: (scale_q * q_max, scale_p * p_max), fill: fill, stroke: stroke)
}
for (tip, label, label-offset) in (((125, 0), $q$, (5, 0)), ((0, 83), $p$, (0, 23))) {
line(tip.map(coord => -coord), tip, stroke: ink + .7pt, mark: (end: "stealth"))
content((rel: label-offset, to: tip), label)
}
content((52, 20), $H < E$)
// leader from just above the H=E label to its point on the contour
let contour-label = (45, -84)
content(contour-label, text(fill: blue)[$H=E$])
line((rel: (0, 9), to: contour-label), (55, -53), stroke: blue + .7pt)
content((-60, 90), text(fill: green)[$E < H < E+Delta E$])
})),
[
$H(q,p) = p^2/(2m) + k q^2/2$
#v(6pt)
$q_(max)=sqrt(2E/k), quad p_(max)=sqrt(2 m E)$
#v(6pt)
Interior: $H < E$\ Blue contour: $H=E$\ Green shell: $E < H < E+Delta E$
#v(6pt)
Axes scaled independently; shell exaggerated.
],
)
]
#v(12pt)
#grid(
columns: (1fr, 1fr),
gutter: 12pt,
..(
([2 Rational: closed orbit], 2, 1, [$omega_2 \/ omega_1=2$ · Opposite edges identified.]),
(
[3 Irrational: dense orbit],
calc.sqrt(2),
24,
[$omega_2 \/ omega_1=sqrt(2)$ · Finite segment shown.],
),
).map(((title, ratio, turns, caption)) => panel[
#text(size: 16pt, weight: "bold", title)
#v(8pt)
#align(center, orbit(ratio, turns: turns))
#v(8pt)
#align(center, caption)
]),
)
#v(12pt)
#block(
width: 100%,
inset: 10pt,
radius: 5pt,
fill: rgb("#c6d8d2"),
breakable: false,
)[Irrational flow is ergodic on its *fixed-action torus* with uniform angle measure, not generally on the full energy surface.]