Blow the wind along a coast and follow the chain: stress, Ekman transport, rising cold water, nutrients, bloom, tuna.
Each button runs 80 model days headless from the current settings and lists transport, upwelling, thermocline depth and phytoplankton at day 80 and at the peak.
The science
Wind stress. τ = ρa CD U² with ρa = 1.22 kg/m³ and a constant CD = 1.3×10⁻³ (real drag grows slightly with wind speed).
Ekman layer. Balancing Coriolis force and vertical friction (eddy viscosity Az) gives a spiral: u = V₀ ez/D cos(π/4 + z/D), v = V₀ ez/D sin(π/4 + z/D), depth scale D = √(2Az/f), V₀ = √2 τ/(ρ f D), f = 2Ω sin φ. In the northern hemisphere the surface current is 45° to the right of the wind and turns further right with depth. The depth-integrated transport is exactly M = τ/(ρ f), 90° to the right of the wind, and does not depend on Az.
Coastal upwelling. Equatorward wind along an eastern-ocean coast pushes surface water offshore; mass must be replaced from below inside about one internal Rossby radius LR = √(g′H₀)/f (g′ = 0.02 m/s²). Upwelling speed w = M/LR. The thermocline depth at the coast obeys dH/dt = −w + (H₀ − H)/τr, so the steady value is H₀ − w τr; when H reaches 0 cold water outcrops. Away from the coast the thermocline relaxes back as H₀ − (H₀ − H) e−d/LR (the drawn isotherms).
Plankton box. A mixed-layer box of depth 20 m: dN/dt = λ(Nin − N) − μ P N/(K+N) + (1 − β)G + mZ Z + mP P, dP/dt = μ P N/(K+N) − G − mPP − λP, dZ/dt = βG − mZZ − λZ, with grazing G = gmax Z P/(P + kg), flushing rate λ = w/Hm (water leaves offshore as fast as it upwells) and supply Nin rising to 22 mmol/m³ once the thermocline is shallower than about 30 m. μ = 1.6/day × light. N + P + Z is conserved without flushing.
Simplifications: steady 2D cross-section, a single wind-driven thermocline layer, constant eddy viscosity, no alongshore variation, no wind-curl upwelling, no light limitation by depth or self-shading, nutrient and plankton constants typical rather than fitted, and the vertical scale of the picture exaggerated. Fish positions are decorative. Assets built with Blender; scene by Three.js.