[Example] Tropical cyclone with stationary stratiform rainband (YD19)#657
[Example] Tropical cyclone with stationary stratiform rainband (YD19)#657bischtob wants to merge 18 commits into
Conversation
…nband (YD19)
Reproduction of the Yu and Didlake (2019, J. Atmos. Sci. 76, 3169–3189)
idealized tropical-cyclone rainband experiment as a self-contained Breeze
example. The simulation asks: given a mature hurricane, what happens when
you paint a steady stationary heating pattern in one of its stratiform
rainbands? YD19's answer — obtained from a full-physics WRF run — is a
quadrupole of secondary-circulation anomalies and a few-m/s dipole in the
tangential wind. We get the same pattern here with the Breeze anelastic
core.
## Simulation
Single hardwired configuration, 214² × 75 cells on a 642 km × 642 km × 25 km
periodic-in-x-y box at 3 km horizontal resolution (Δz ≈ 333 m). Three
back-to-back 24 h stages run end-to-end in one script:
1. Spinup — balanced vortex IC relaxes under the upper-level sponge only.
2. Control — 24 h continuation from the post-spinup state, no heating.
3. Heated — 24 h continuation from the same post-spinup state with the
MN10 stratiform heating switched on.
The response is (heated − control) in the hour 5-7 analysis window (per
F06 diagnostic; response saturation past that window reflects the absence
of explicit horizontal diffusivity — documented known limitation).
## Physics
- Environment: Jordan (1958) West Indies mean hurricane-season sounding
(tabulated inline; interpolated onto z_centers).
- Vortex: modified-Rankine (YD19 Eq. 2) with Stern–Nolan (2009) Eq. 4.4
RMW(z) slope, tapered outside 250 km for periodic-box compatibility.
- Initial condition: Picard iteration of the gradient-wind + hydrostatic +
ideal-gas fixed point (Nolan 2001 / WRF `em_tropical_cyclone`). Converges
in ~15 iterations to gradient-wind residual ~10⁻³ Pa/m and hydrostatic
residual ~10⁻⁵ Pa/m — a 10⁴× collapse over a one-shot linearized baseline.
- Rainband heating: YD19 Eq. 3 — spiral radial centerline
r_bs(λ,z) = [60 − 10(λ/(π/4))] km + z, Gaussian radial shape with
σ_r = 6 km, sinusoidal vertical shape with σ_zs = 2 km centered at
z_bs = 4 km, super-Gaussian azimuthal window at λ = −π/4, and a 1-h
linear ramp from zero to full strength.
- Upper-level sponge: WRF `damp_opt=2` analog. Rayleigh damping of ρu/ρv/ρw
toward zero and ρe toward the reference dry-static-energy-density profile,
sin² ramp from z = 20 km to max at z = 25 km.
## Scientific outcome
End-of-spinup surface v̄ peak = 37.94 m/s at r = 31.5 km (YD19 target ≈ 40);
warm-core θ' peak = 7.63 K at (r, z) = (1.5, 9.8) km (YD19 ~12 K at 10-12 km);
hour 5-7 axisymmetric response range = [-1.00, +1.61] m/s (YD19 peak ≈ ±1.5);
per-panel |w'| peaks [0.213, 0.183, 0.217] m/s at z = 6 / 3.6 / 2 km. The
quadrupole pattern and dipole in v̄ are reproduced; the θ' magnitude shortfall
is a known formulation caveat (mass-coord vs z-coord Picard closure) that
survives spinup roughly unchanged.
## What the example teaches
- Building a balanced-vortex IC via Picard iteration.
- Wiring a spatially structured, time-varying heat source into the energy
equation with `Forcing`.
- Running three related stages in one script with in-memory state handoff.
- Isolating a forced response via a control experiment.
## Figures produced
- `F01_preflight.png` vortex IC sanity check
- `F02ab_vortex.png` basic-state vortex (YD19 Fig 2a,b)
- `F02cd_heating.png` analytic heating (YD19 Fig 2c,d)
- `F03a_axisym_response.png` axisymmetric response (YD19 Fig 3a)
- `F04_plan_response.png` plan-view response (YD19 Fig 4a-c)
- `F05_cross_sections.png` cross sections (YD19 Fig 5)
- `F06_response_timeseries.png` response amplitude vs time
- `response_w_z3km.mp4` w' evolution animation at z ≈ 3 km
## Implementation notes
- Self-contained: all physics (Jordan sounding, YD19 constants, kinematics,
Picard solver, residuals) inlined into the single example file. No
external `include`s.
- Simulation default is `Float64`. `Float32` attempted and deferred —
the anelastic pressure solve NaN's in ρu within 100-300 spinup steps
at 3 km on GPU with the YD19 vortex intensity. Smoke (12 km) worked.
A separate Breeze-level stability investigation is warranted.
- Analysis block uses `FieldTimeSeries(...; backend=OnDisk())` for
streaming reads and Float32 preallocated scratch buffers for centered
interpolation. Peak analysis RSS ≈ 50 MB regardless of snapshot count.
- LaTeX math blocks, @cite / @citet / @ref markers throughout.
- Six new bib entries (YuDidlake2019, MoonNolan2010, SternNolan2009,
Nolan2001, Jordan1958, Emanuel1986) in `docs/src/breeze.bib`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
response_w_z3km.mp4 |
| example_dir = @__DIR__ | ||
|
|
There was a problem hiding this comment.
I don't think we need this, right?
| example_dir = @__DIR__ |
Co-authored-by: Navid C. Constantinou <navidcy@users.noreply.github.com>
Unfortunately the L4 really struggles with intensive Float64 workloads. This example alone (I disabled all the other GPU ones) took 80 minutes (before erroring during the plotting part due to a literate syntax error) |
|
https://github.com/NumericalEarth/Breeze.jl/actions/runs/24929552701/job/73004993549#step:7:82 Half a GB for a webpage is indeed quite a lot 😳 |
|
Ok. I think I found the issue. I'm testing it on my end before I push anything up. |
|
Docs building finally works: https://numericalearth.github.io/BreezeDocumentation/previews/PR657/literated/tropical_cyclone_with_rainband/ 🥳 only problem now is that the new example takes over one hour to run (and it'll be a lot worse when we restore all other examples), because fp64 performance is pretty bad on this GPU 🫠 |
What if we run on Float32? |
|
Apparently it wasn't stable: #657 (comment) |







Summary
Self-contained literate example that reproduces the idealized tropical-cyclone rainband experiment of Yu & Didlake (2019, J. Atmos. Sci. 76, 3169–3189) — modeled on the form of our mature examples (
bomex.jl,splitting_supercell.jl,dry_thermal_bubble.jl).The simulation asks YD19's question: given a mature hurricane, what happens when you paint a steady stationary heating pattern in one of its stratiform rainbands? The answer — both in YD19's full-physics WRF run and in the Breeze anelastic reproduction here — is a quadrupole of secondary-circulation anomalies and a few-m/s dipole in the tangential wind.
Buidls on earlier WIP #440 by @nrb171. Closes #439.
@nrb171 feel free to do whatever you want with this.
What's in the PR (4 files, +1465 / −0)
examples/tropical_cyclone_with_rainband.jldocs/src/breeze.bibexamples/.gitignoreoutput_tc_*/,*.jld2,*.mp4,*.pngout of git (the example writes ~5 GB of output)docs/make.jlbuild_always=false, gpu=true, consistent with the other heavy GPU examples)Simulation
Single hardwired configuration, 214² × 75 cells on a 642 km × 642 km × 25 km periodic-in-x-y box at 3 km horizontal resolution (Δz ≈ 333 m). Three back-to-back 24 h stages run end-to-end in one script:
The response is (heated − control) in the hour 5–7 analysis window. An F06 diagnostic tracks the response amplitude vs time; saturation past ~7 h reflects the absence of explicit horizontal diffusivity (documented known limitation).
Physics
z_centers.em_tropical_cycloneinitializer — the procedure YD19 §3a2 prescribe). Converges in ~15 iterations to gradient-wind residual ~10⁻³ Pa/m and hydrostatic residual ~10⁻⁵ Pa/m — a 10⁴× collapse over a one-shot linearized baseline.r_bs(λ,z) = [60 − 10(λ/(π/4))] km + z, Gaussian radial shape withσ_r = 6 km, sinusoidal vertical shape withσ_zs = 2 kmcentered atz_bs = 4 km, super-Gaussian azimuthal window atλ = −π/4, 1-h linear ramp from zero to full strength.damp_opt=2analog. Rayleigh damping ofρu/ρv/ρwtoward zero andρetoward the reference dry-static-energy-density profileρᵣ(z)[cᵖᵈ Tᵣ(z) + gz], sin² ramp fromz = 20 kmto max atz = 25 km.Scientific outcome
Reproduced on NVIDIA H200 (GPU), 214² × 75, Float64:
The quadrupole pattern and dipole in v̄′ are reproduced. The θ′ magnitude shortfall is a known formulation caveat (mass-coord vs z-coord Picard closure) that survives the 24 h spinup roughly unchanged.
What the example teaches
em_tropical_cyclone).Forcing.Figures produced
F01_preflight.png— vortex IC sanity checkF02ab_vortex.png— basic-state vortex (YD19 Fig 2a,b)F02cd_heating.png— analytic heating (YD19 Fig 2c,d)F03a_axisym_response.png— axisymmetric response (YD19 Fig 3a)F04_plan_response.png— plan-view response (YD19 Fig 4a-c)F05_cross_sections.png— cross sections (YD19 Fig 5)F06_response_timeseries.png— response amplitude vs time (diagnostic)response_w_z3km.mp4— 25-frame animation of the w′ response at z ≈ 3 kmMature-example form
includes.[Author](@citet)/@citemarkers for every scientific reference; six bib entries added.@refcross-refs for Breeze API (ReferenceState).embed for the animation so Documenter renders it inline.FieldTimeSeries(...; backend=Oceananigans.OnDisk())and preallocatedFloat32scratch buffers — peak RSS during analysis is bounded to a handful of 3D fields (~50 MB at this resolution) regardless of snapshot count.Implementation notes & caveats
Float32was attempted and deferred: the anelastic pressure solve NaN's inρuwithin 100–300 spinup steps at 3 km on GPU with the YD19 vortex intensity. Smoke-domain (12 km) Float32 runs were stable. Worth a separate Breeze-level stability investigation.build_always=false, gpu=true, it only runs whenBREEZE_BUILD_ALL_EXAMPLES=trueon a GPU runner.Test plan
Meta.parseallpasses.@citemarkers resolve,@refresolves forReferenceState, no example-specific errors.BREEZE_BUILD_ALL_EXAMPLES=trueor equivalent).References