Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Double Gyre — Barotropic QG

Authors
Affiliations
University of Valencia

The wind-driven double gyre is the canonical wind-forced ocean-basin test: a sinusoidal wind-stress curl spins up two counter-rotating gyres, the β\beta-effect concentrates the return flow into a narrow western boundary current, and — at low enough viscosity — that current goes barotropically unstable into a meandering eastward jet that sheds eddies (geostrophic turbulence).

Barotropic quasi-geostrophic is the cheapest model that captures it: a single potential-vorticity field, advected by the energy- and enstrophy-conserving Arakawa Jacobian and inverted to a streamfunction with a spectral Poisson solve. The enstrophy-conserving advection is what lets the run stay stable in the turbulent (eddy-permitting) regime even though the grid-Reynolds number is well above the centred-advection limit.

This page executes a 64² turbulent run (cheap, ~minutes) and then gives ready-to-run, correctly-scaled commands for 128²–1024² that you can launch in your own time (256²+ wants a GPU). It follows the repo’s getting-sims-to-work methodology throughout: observability first, probe cost before committing, and scale forcing/viscosity/dt with the resolution.

Observability + start-small helpers

probe runs a short window and reports the two numbers that decide whether a long run is worth launching: ms/step (so you can extrapolate the cost) and |u|_max (so you can check the advective CFL dt < dx/|u|). run does the full integration, checks finiteness, and saves the arrays to disk before any plotting so a plotting bug can never waste the integration.

Executed run — 64², turbulent (3 yr)

Low viscosity (ν=150) and a moderate wind (2e-11) put this in the eddy-permitting regime; the boundary current destabilises into a meandering jet within the first year or two.

64²  3 yr  KE=1.601e+13  enstrophy=7.932e+02  |u|max=10.57 m/s

Streamfunction, kinetic energy, and the eddy field

ψ\psi (the gyres + boundary current), kinetic energy 12(u2+v2)\tfrac{1}{2}(u^2+v^2) (lights up the jet and eddies), and relative vorticity ζ\zeta (the clearest view of the turbulent eddy field).

<Figure size 1700x520 with 6 Axes>

Scaling up — 128², 256², 512², 1024² (run in your spare time)

The helpers above already encode the scaling, so a higher-resolution sweep is a one-liner. Always probe first, then launch the full run. The finer the grid the more of the turbulent cascade you resolve (sharper jet, more eddies, filaments) — and the more it costs.

nxdxν (=150·64/nx)dt (start)rough cost, 10 yr, CPU*
6415.6 km150600 sminutes
1287.8 km75300 s~1 hr
2563.9 km37.5150 s~8 hr (use a GPU)
5122.0 km18.7575 sdays (GPU)
10241.0 km9.37537.5 s~1 week (GPU)

*Cost grows roughly as nx³ (the grid is nx² and dt ∝ 1/nx); a GPU is strongly recommended at 256² and above. JAX runs the same code on GPU unchanged — just install a CUDA jaxlib.

# 1) Probe every resolution first (ms/step, |u|max, CFL-limited dt):
for nx in (128, 256, 512, 1024):
    probe(nx)

# 2) Launch a full turbulent spin-up at the resolution you want, checkpointing
#    the fields to disk (re-plot from the .npz, never re-integrate):
x, y, psi, ke, zeta = run(nx=256, years=10.0, save="dg_bt_256.npz")

# If probe() reports the suggested CFL-dt is below recommended_dt(nx), pass it
# explicitly, e.g. run(nx=256, years=10.0, dt=120.0, save="dg_bt_256.npz").

Then plot from the saved arrays with the same three-panel code as above:

d = np.load("dg_bt_256.npz")
x, y, psi, ke, zeta = d["x"], d["y"], d["psi"], d["ke"], d["zeta"]
# ... same contourf panels ...

Notes

  • Resolution ↔ forcing ↔ viscosity ↔ dt are coupled. Here the physics (wind, drag, domain, β) is held fixed and only ν and dt scale with the grid: ν shrinks ∝ dx to stay eddy-resolving, and dt shrinks because the sharper jet tightens the advective CFL dt < dx/|u|.

  • QG removes the external gravity-wave CFL (no √(gH) term), so dt is set by advection, not waves.

  • Stability in this high-grid-Reynolds regime comes from the enstrophy-conserving Arakawa Jacobian + bottom drag, not from viscosity.

  • See the getting-sims-to-work skill for the full bring-up checklist.