WW3 solves the spectral action density balance equation. At every point in space and every moment in time, it carries a two-dimensional spectrum: how much wave energy sits at each frequency and each direction.
where is action density (energy over intrinsic frequency, conserved in the presence of currents, where energy isn't).
Read the terms left to right and you have the whole model:
| Term | Physics | WW3 switch/flag |
|---|---|---|
| evolution in time | — | |
| waves travel at the group velocity | RUN%FLCX, RUN%FLCY |
|
| shoaling, current-induced frequency shift | RUN%FLCK |
|
| refraction by depth and current | RUN%FLCTH |
|
| all the physics you can't derive | RUN%FLSOU |
The left side is clean conservative transport in a 4D phase space (x, y, k, θ). It's numerics, and it's solvable. The right side is where the model earns its keep and where all the uncertainty lives.
The first half of this course (00–08) teaches you to run the
thing that solves this equation. The second half (09–13) teaches you to
make it run faster without changing the answer, and it follows
the ladder of the UFRJ/DEL project proposal that this repository serves:
compile options → run configuration → modern Fortran → C++/Kokkos
kernels for the GPU, each rung gated by parity against the reference run
before the next one is allowed to start. The proposal itself is in ../pubs/proposal/pt/
(Portuguese, eight short sections) and its mind maps in ../pubs/proposal/mapas-mentais.pt.md;
the lessons are the English, hands-on version of the same ladder, with
the code in ../kokkos/.
ST2,
ST4, ST6) mostly means picking a version of
this.NL1, Hasselmann 1985) and everybody knows
it's the weakest link.IC1–IC5,
IS1/IS2).The thing to internalise:
and
are individually large and individually uncertain, and they nearly
cancel. The net is a small difference of big numbers. That's why
source-term packages come as matched sets: you cannot mix the
ST4 input with the ST6 dissipation and expect
anything sensible.
WW3 does not know where any individual wave crest
is. It tracks statistics. If you want a surface you can render, or
wave-by-wave runup on a beach, or slamming loads on a hull, you want a
different class of model entirely (SWASH, XBeach, FUNWAVE, OpenFOAM; see
docs/AWESOME-WW3_202609.md).
What WW3 gives you is: the spectrum, and everything derivable from it. , peak period, mean direction, directional spread, Stokes drift, radiation stresses, partitioned swell systems.
Every field WW3 carries lives on latitude × longitude × frequency × direction × time. A modest regional run (81 × 81 points, 32 frequencies, 36 directions) is 7.5 million numbers per timestep, before any output. This is why WW3 is expensive, and it is directly relevant to the GPU question in lessons 11–13: you cannot casually shuttle that array across PCIe every step, so a port has to decide where the spectrum lives.
WW3 isn't one binary. It's a family, communicating through files:
ww3_grid bathymetry + spectrum + timesteps ──► mod_def.ww3 [THE model definition]
ww3_strt initial conditions ──► restart.ww3
ww3_prnc netCDF forcing → binary ──► wind.ww3, current.ww3, ice.ww3
ww3_bounc spectra from a parent run ──► nest.ww3
│
▼
ww3_shel THE MODEL (single grid) ──► out_grd.ww3, out_pnt.ww3, log.ww3
ww3_multi THE MODEL (mosaic of grids) restart.ww3
│
▼
ww3_ounf gridded fields → netCDF ──► ww3.*.nc
ww3_ounp point spectra → netCDF ──► ww3.*_spec.nc
ww3_outf / ww3_outp → ASCII (legacy, avoid)
ww3_trnc track output → netCDF
ww3_gint grid interpolation
ww3_systrk wave system tracking
ww3_uprstr restart update from Hs analysis
mod_def.ww3 is the centre of gravity.
It's an opaque binary produced by ww3_grid containing the
complete model definition: grid, spectral discretisation, timesteps,
physics configuration. Every other program reads it. Change
ww3_grid.nml, and every downstream artifact is stale until
you rerun ww3_grid. A large share of all confusing WW3
behaviour reduces to a stale mod_def.
WW3 accepts legacy .inp (fixed-format,
positional, comment lines start with $) and modern
.nml (Fortran namelists, order-independent,
self-documenting). Both work in v7. Everything in this repo uses
.nml, because:
$WW3/model/nml/ document
every single parameter inline;examples/ write them,
and so does every third-party wrapper you might meet (lesson 08). Nobody
targets .inp any more.If you follow an older tutorial and get
error reading input file, check whether it's handing an
.inp to a program expecting .nml or vice
versa. That's a real and common failure mode.
→ 01-build.md:
get it compiled.