Waves Hanging in the Sky — The Kelvin-Helmholtz Instability
Why two streams at different speeds roll up into vortices
Every so often the sky wears a row of frozen ocean waves. Hook-shaped crests, curled over and lined up like breakers on a beach. In a photo they look faked, but they are real clouds with a name: Kelvin-Helmholtz clouds. The air is imitating a wave the instant before it breaks.
This post follows how those hooks form. A thin boundary where a fast stream meets a slow one — a shear layer. We will see why that boundary refuses to stay flat and rolls up into vortices instead, when it rolls and when it stays quiet, all packed into a single growth-rate formula. At the end we roll a thin vortex sheet up by hand to make the hooks ourselves.
Waves Hanging in the Sky#
Kelvin-Helmholtz clouds are not the only place this happens. The same thing plays out everywhere. The seams where Jupiter's bands split apart, the internal waves where seawater of different densities slides past itself, the brief spiral when you pour milk into coffee. Even the point where a rising ribbon of cigarette smoke suddenly scatters follows the same rule.
They share one ingredient. Two fluid layers flow side by side at different speeds. The upper layer fast, the lower layer slow. The thin boundary between them slips. That slip — the shear — is the seed.
Intuitively you might expect the two streams to just glide past each other. They do not. Even the tiniest ripple on the boundary grows on its own. This is the Kelvin-Helmholtz instability (a shear-driven instability of the interface).
What Happens When Two Streams Slip#
Say a small bump rises on the boundary. The fast upper stream has to go over it. The passage over the crest narrows. To keep the flow rate the same, the fluid speeds up where the passage is tight.
Faster means lower pressure. That is Bernoulli's principle (where the flow is fast, the pressure is low). Lower pressure above the crest sucks the crest up even more. In the trough the opposite happens: the flow slows, the pressure rises, and the trough gets pushed down harder.
So the crest rises higher and the trough digs deeper. A small ripple feeds itself — a positive feedback. Once it starts, it does not stop. That is the core mechanism of the instability.
One common misconception: "Heavy water below, light air above — isn't that stable?" By gravity alone, yes. But strong enough shear beats gravity's stabilizing effect. Even a stable stratification collapses in front of a strong wind.
The Dispersion Relation — Which Wavelengths Grow#
This tug-of-war compresses into a single equation. An upper layer (density ) and a lower layer (density ) slip past each other at relative speed , with gravity and surface tension acting on the interface. The rate at which a ripple of wavenumber (waves per unit length) grows — its growth rate — is:
is how fast the ripple grows. The first term under the root is shear (it destabilizes), the second is gravity (heavy fluid below stabilizes), and the third is surface tension (it pulls the interface taut and stabilizes).
If the radicand is positive, is real and the ripple grows exponentially. If negative, is imaginary — the ripple only oscillates and never grows. The instability condition is that the radicand is positive, i.e., shear beats the other two.
Look at the purest case. If the two layers have equal density () and there is no gravity or surface tension, the formula collapses to something strikingly simple.
The larger the wavenumber — the shorter the wavelength — the faster it grows. With no brakes at all, arbitrarily short wavelengths blow up. In real flow, viscosity cuts off this runaway at the short-wavelength end.
Gravity and Surface Tension Hit the Brakes#
The two brakes stop different wavelengths. The gravity term scales as , so it suppresses long waves (small ). The surface-tension term scales as , so it suppresses short waves (large ). A band of unstable wavelengths survives in between.
If the shear is weak, that band never opens. Increase the shear and at some point instability breaks through first at one particular wavelength. That threshold is exactly the minimum wind speed at which a breeze starts raising waves on a calm surface.
Plug in air and water and you get , with the first wavelength to break through at about 1.7 cm. Kelvin computed this in the 19th century. (A real water surface ripples at lower wind speeds too, because of viscosity — a limit of the ideal theory.)
For a continuously stratified flow, the verdict comes from the Richardson number (the ratio of buoyancy to shear). , where is the buoyancy frequency. The Miles-Howard theorem says instability is possible somewhere below . It is the working criterion for predicting when turbulence erupts in the atmosphere and ocean.
Try hitting the brakes yourself below. Move the sliders for shear, density ratio, gravity, and surface tension to watch the growth-rate curve reshape.
Lower the shear toward 6 and the curve flattens to the floor and flips to "STABLE." Raise gravity or surface tension and the unstable band (the orange region) narrows from both sides. Push the density ratio toward 1 (the two layers becoming similar) and the curve shoots up under even the faintest shear.
Drawing the Growth-Rate Curve in Python#
Port the formula straight into code and you can read off which wavelength grows first at any wind speed.
import math
def kh_growth_rate(k, dU, rho_u, rho_l, g=9.81, T=0.072):
"""Growth rate sigma(k) of a Kelvin-Helmholtz mode."""
shear = rho_u * rho_l * dU**2 / (rho_u + rho_l)**2 # destabilizing (shear)
gravity = g * (rho_l - rho_u) / ((rho_u + rho_l) * k) # stabilizes long waves
tension = T * k / (rho_u + rho_l) # stabilizes short waves
disc = shear - gravity - tension
return k * math.sqrt(disc) if disc > 0 else 0.0
rho_air, rho_water = 1.225, 1000.0
ks = [1 + 0.2 * i for i in range(4000)]
for dU in (3.0, 6.6, 10.0):
s = [kh_growth_rate(k, dU, rho_air, rho_water) for k in ks]
smax = max(s)
if smax > 0:
kstar = ks[s.index(smax)]
lam = 2 * math.pi / kstar * 100 # cm
print(f"dU={dU:4.1f} m/s -> unstable, lambda*={lam:5.2f} cm, sigma_max={smax:6.2f} /s")
else:
print(f"dU={dU:4.1f} m/s -> stable (no waves)")Running it prints:
dU= 3.0 m/s -> stable (no waves)
dU= 6.6 m/s -> unstable, lambda*= 1.69 cm, sigma_max= 4.89 /s
dU=10.0 m/s -> unstable, lambda*= 0.78 cm, sigma_max=183.30 /sAt 3 m/s of wind the surface stays calm. The moment it crosses 6.6 m/s, a ripple about 1.7 cm long is the first to grow. Push the wind higher and the growth rate climbs steeply while the most dangerous wavelength shrinks.
The Moment It Rolls Up#
Linear theory tracks the early stage well, while the ripple is still growing. But once the bump gets large enough the story changes. The interface does not just undulate — it curls over as a whole. The thin vortex sheet winds up into a regular train of vortices. This is the true identity of the hook clouds, and the pattern theory calls Stuart's cat's eye.
The simulation below actually rolls a slightly perturbed vortex sheet up. Each dot is a marker on the interface, pulling on the others through the induced velocity of an inviscid flow. Use the sliders to change the number of vortices and the strength of the shear.
A line that starts as a gentle wave winds into a cat's eye within a few seconds. Raise the shear and it rolls faster; increase the vortex count and you get a finer train of hooks. Hit Reset to start over from a flat ripple.
It matters to separate the two stages here. The growth-rate formula describes only the linear stage, while the ripple is first growing. The rolled-up cat's eye is the nonlinear stage — a separate picture, born of the interface pulling on itself. Nature shows the two in sequence. The ripple stands up, then it rolls.
What the Phenomenon Tells Us#
Wherever there is shear, there is a seed of instability. When two streams at different speeds meet, that boundary can never stay smooth. A small bump grows itself, and eventually rolls into a vortex. That is the essence of the Kelvin-Helmholtz instability.
The growth rate is the referee of this fight. Shear pushes, gravity and surface tension hold back. The balance of the three decides which wavelength grows and which is put to sleep. From the minimum wind that raises waves on calm water, to the Richardson number that gauges the threshold of atmospheric turbulence — all of it is a reading on the same scale. That hook cloud hanging in the sky is proof that the scale has tipped toward shear.
Share if you found it helpful.