Skip to content
cfd-lab:~/en/posts/2026-07-21-water-wave-di…online
NOTE #110DAY TUE 유체역학DATE 2026.07.21READ 5 min readWORDS 827#Water-Waves#Dispersion#Group-Velocity#Capillary-Wave#유동현상

A Single Ripple Outruns Its Own Group — Wave Dispersion and Group Velocity

Why every wavelength travels at its own speed, and phase and group part ways

Toss a pebble into a still pond. Ripples spread out in a growing ring. Everyone knows that much.

Look closely at the ring, though, and something is off. Each little ripple is born at the back of the group. It races outward. Then it dies at the leading edge. The group widens slowly, but the ripples inside it run ahead of the group.

This post covers two ideas. Dispersion — every wavelength travels at its own speed. And group velocity — a single wave and a group of waves move at different speeds. By the end you will know exactly why the pebble's ring looks the way it does.

The Ring the Pebble Made#

A surface wave is driven by a restoring force — the force pulling the water back toward flat. There are two of them.

One is gravity. It drags a raised crest back down. The other is surface tension (the force that pulls the water surface taut). It tries to flatten a curved surface.

For long waves, gravity wins. Once the wavelength drops below about 1.7 cm, surface tension takes over. Ocean swells are gravity waves. Pond ripples are capillary waves.

Wavelength Sets the Speed#

The physics of a surface wave boils down to one dispersion relation.

ω2=(gk+σk3ρ)tanh(kh)\omega^2 = \left( g k + \frac{\sigma k^3}{\rho} \right)\tanh(k h)

Here ω\omega is the angular frequency, k=2π/λk = 2\pi/\lambda is the wavenumber (waves per unit length), λ\lambda is the wavelength, gg is gravity, σ\sigma is surface tension, ρ\rho is density, and hh is the water depth.

The speed at which a single wave advances is the phase velocity. Define it as c=ω/kc = \omega/k.

c=(gk+σkρ)tanh(kh)c = \sqrt{\left( \frac{g}{k} + \frac{\sigma k}{\rho} \right)\tanh(k h)}

The key point is that cc depends on kk, hence on wavelength. Different wavelengths travel at different speeds. That is dispersion. Sound, and light in a vacuum, travel at the same speed regardless of wavelength. Water waves do not.

Gravity and Surface Tension Tug of War#

Take deep water. When khkh is large, tanh(kh)1\tanh(kh) \to 1, and the formula simplifies.

c=gk+σkρc = \sqrt{ \frac{g}{k} + \frac{\sigma k}{\rho} }

The first term is gravity's share. It grows as the wavelength grows (as kk shrinks). The second is surface tension's share. It grows as the wavelength shrinks (as kk grows).

The two terms pull in opposite directions. So the speed has a minimum. Solving dc/dk=0dc/dk = 0 gives the wavelength of slowest travel.

λ=2πσρg1.7cm\lambda_\ast = 2\pi\sqrt{\frac{\sigma}{\rho g}} \approx 1.7\,\text{cm}

At this wavelength the phase velocity bottoms out near 0.23 m/s. Check it for yourself in the plot below.

1mm1cm10cm1m10m0.01.02.03.03.9m/swavelength λ (log)gravity ↔ capillaryc_min ≈ 0.23 m/sphase speed cgroup speed c_g

Lower σ toward 0 and the capillary upturn on the left flattens — only gravity is left. Shrink h and the long-wave end levels off at the shallow-water speed √(gh), where waves stop dispersing.

Turn surface tension σ\sigma down toward zero and the capillary branch on the left disappears. With only gravity left, shorter always means slower. Watch how the lowest point of the curve — and the boundary where gravity gives way to surface tension — shifts around.

Deep Water and Shallow Water#

What happens when the depth is far smaller than the wavelength? When khkh is small, tanh(kh)kh\tanh(kh) \approx kh. Drop surface tension and the speed becomes strikingly simple.

c=ghc = \sqrt{g h}

The wavelength is gone. In shallow water every wavelength travels at the same speed. There is no dispersion. This state is called non-dispersive.

That is why a tsunami is so dangerous. Over a 4 km deep ocean, gh\sqrt{gh} reaches 700 km/h. A wave hundreds of kilometers long races along at jet-airliner speed while barely changing shape.

The Group Lags the Waves#

Now back to the opening puzzle. Why does a single ripple outrun its group?

The speed at which a wave group — a wave packet — moves is the group velocity. Define it as cg=dω/dkc_g = d\omega/dk. It is a different quantity from the phase velocity.

Consider pure gravity waves in deep water, where ω=gk\omega = \sqrt{gk}. Differentiate and the result is clean.

cg=dωdk=12gk=c2c_g = \frac{d\omega}{dk} = \frac{1}{2}\sqrt{\frac{g}{k}} = \frac{c}{2}

The group velocity is exactly half the phase velocity. The group crawls at half the speed of its own waves. So each ripple is born at the back of the group, sprints forward, and vanishes at the group's front edge.

Energy travels at the group velocity. Only the shape of the crest travels at the phase velocity. Below, follow one yellow crest.

At c_g/c = 0.5 (deep-water gravity waves) the yellow crest clearly outruns the pink envelope and fades at the front. Set the ratio to 1 and the crest freezes inside the lump — nothing disperses.

Set c_g/c to 0.5 and the yellow crest overtakes the pink envelope (the outline of the group) and fades at the front. Raise the ratio to 1 and the crest locks in place inside the group — the picture of a non-dispersive wave.

Plotting the Dispersion Curve in Python#

With the dispersion relation in hand, phase and group velocity plot straight out. Group velocity comes from differentiating ω(k)\omega(k) numerically.

import numpy as np
 
g, rho = 9.81, 1000.0          # gravity [m/s^2], water density [kg/m^3]
sigma = 0.072                  # water-air surface tension [N/m]
 
def omega(k, h):
    return np.sqrt((g * k + sigma * k**3 / rho) * np.tanh(k * h))
 
def phase_speed(lam, h):
    k = 2.0 * np.pi / lam
    return omega(k, h) / k
 
def group_speed(lam, h):
    k = 2.0 * np.pi / lam
    dk = k * 1e-5                       # central difference for domega/dk
    return (omega(k + dk, h) - omega(k - dk, h)) / (2.0 * dk)
 
lam = np.geomspace(1e-3, 10.0, 400)    # 1mm to 10m, deep-water assumption
c = phase_speed(lam, h=100.0)
i = int(np.argmin(c))
print(f"min phase speed {c[i]:.3f} m/s @ wavelength {lam[i]*100:.2f} cm")
# min phase speed 0.232 m/s @ wavelength 1.73 cm
 
lam_swell = 2.0                        # 2m swell: gravity dominated
cp = phase_speed(lam_swell, 100.0)
cg = group_speed(lam_swell, 100.0)
print(f"phase {cp:.3f} m/s, group {cg:.3f} m/s, ratio {cg/cp:.3f}")
# phase 1.767 m/s, group 0.884 m/s, ratio 0.500

The minimum phase speed matches the hand calculation: 0.232 m/s at 1.73 cm. And the group velocity of a 2 m swell comes out at exactly half the phase velocity. The earlier hand derivation reproduced in code.

What to Remember Skipping Stones#

  • Dispersion: water waves travel at different speeds by wavelength. Long waves speed up from gravity, short waves from surface tension, leaving a minimum speed (about 0.23 m/s) in between.
  • Shallow water: when the depth is less than the wavelength, the speed is just gh\sqrt{gh}. The wavelength drops out, so there is no dispersion.
  • Group velocity: energy and the group move at cgc_g. For deep-water gravity waves cg=c/2c_g = c/2, so a single crest is born ahead of the group, then dies.

Share if you found it helpful.