3.2 Geostrophic Balance
In the free atmosphere, the pressure gradient force and Coriolis force are approximately in balance, producing geostrophic wind that flows parallel to isobars.
Coriolis Force
$$\vec{F}_{Cor} = -2\vec{\Omega} \times \vec{v} = -f\hat{k} \times \vec{v}$$
where f = 2Ω sin φ is the Coriolis parameter
Equator
f = 0
45°N/S
f ≈ 10⁻⁴ s⁻¹
Poles
f = ±1.46×10⁻⁴ s⁻¹
Geostrophic Wind
$$u_g = -\frac{1}{\rho f}\frac{\partial p}{\partial y}, \quad v_g = \frac{1}{\rho f}\frac{\partial p}{\partial x}$$
Wind flows parallel to isobars with low pressure to the left (NH)
Key Features
- • Wind speed proportional to pressure gradient
- • Tightly packed isobars → strong winds
- • NH: low pressure to left of wind direction
- • SH: low pressure to right of wind direction
Thermal Wind
$$\vec{v}_T = \vec{v}_g(p_1) - \vec{v}_g(p_0) = \frac{R}{f}\ln\left(\frac{p_0}{p_1}\right)\hat{k} \times \nabla_p \bar{T}$$
Wind shear related to horizontal temperature gradient
The thermal wind blows parallel to isotherms with cold air to the left (NH). Strong temperature gradients (like the polar front) produce jet streams.
Python: Geostrophic Wind
#!/usr/bin/env python3
"""
geostrophic_balance.py - Calculate and visualize geostrophic wind
Run: python3 geostrophic_balance.py
Requires: pip install numpy matplotlib
"""
import numpy as np
import matplotlib.pyplot as plt
# Constants
Omega = 7.292e-5 # Earth's rotation rate (rad/s)
rho = 1.2 # air density (kg/m³)
def coriolis_parameter(lat):
"""Coriolis parameter f = 2Ω sin(φ)"""
return 2 * Omega * np.sin(np.radians(lat))
# Create a grid
nx, ny = 50, 50
x = np.linspace(-1000, 1000, nx) # km
y = np.linspace(-1000, 1000, ny) # km
X, Y = np.meshgrid(x, y)
dx = (x[1] - x[0]) * 1000 # convert to m
dy = (y[1] - y[0]) * 1000
# Latitude for this example (45°N)
lat = 45
f = coriolis_parameter(lat)
# Create a pressure field (cyclone)
# Low pressure center at origin
p = 1013 - 20 * np.exp(-(X**2 + Y**2) / (400**2)) # hPa
# Calculate pressure gradients
dp_dx = np.gradient(p * 100, dx, axis=1) # Pa/m
dp_dy = np.gradient(p * 100, dy, axis=0) # Pa/m
# Geostrophic wind components
u_g = -1 / (rho * f) * dp_dy # m/s
v_g = 1 / (rho * f) * dp_dx # m/s
wind_speed = np.sqrt(u_g**2 + v_g**2)
# Plot
fig, axes = plt.subplots(1, 2, figsize=(14, 6))
# Pressure field with geostrophic wind vectors
ax1 = axes[0]
cf = ax1.contourf(X, Y, p, levels=20, cmap='RdBu_r')
plt.colorbar(cf, ax=ax1, label='Pressure (hPa)')
cs = ax1.contour(X, Y, p, levels=np.arange(994, 1014, 2), colors='black')
ax1.clabel(cs, inline=True, fontsize=8)
# Wind vectors
skip = 3
ax1.quiver(X[::skip, ::skip], Y[::skip, ::skip],
u_g[::skip, ::skip], v_g[::skip, ::skip],
color='green', scale=300)
ax1.set_xlabel('x (km)')
ax1.set_ylabel('y (km)')
ax1.set_title(f'Geostrophic Wind around Low (lat = {lat}°N)')
ax1.set_aspect('equal')
ax1.annotate('L', (0, 0), fontsize=24, fontweight='bold', color='red', ha='center')
# Wind speed and streamlines
ax2 = axes[1]
cf2 = ax2.contourf(X, Y, wind_speed, levels=20, cmap='viridis')
plt.colorbar(cf2, ax=ax2, label='Wind Speed (m/s)')
ax2.streamplot(X, Y, u_g, v_g, color='white', density=1.5, linewidth=0.5)
ax2.set_xlabel('x (km)')
ax2.set_ylabel('y (km)')
ax2.set_title('Geostrophic Wind Speed and Streamlines')
ax2.set_aspect('equal')
plt.tight_layout()
plt.savefig('geostrophic_balance.png', dpi=150, bbox_inches='tight')
plt.show()
# Print Coriolis parameter at different latitudes
print("Coriolis parameter f at different latitudes:")
for lat in [0, 30, 45, 60, 90]:
f = coriolis_parameter(lat)
print(f" {lat}°: f = {f:.2e} s⁻¹")
# Typical geostrophic wind calculation
dp_dn = 1 # hPa per 100 km = 0.01 Pa/m
f_45 = coriolis_parameter(45)
v_g_typical = (0.01) / (rho * f_45)
print(f"\nTypical geostrophic wind (1 hPa/100km at 45°N): {v_g_typical:.1f} m/s")