WAVEWATCH III® in pure Rust, on the GPU, through Rust-CUDA
and rust-gpu. It is compared with
metocean/WW3 7.14 (7.14.mos-92e2cf6), and it follows the
discipline of ww3-gpu without Kokkos.
State, 2026-11-04: a run with no Fortran program in it exists. Rust's ww3_grid, ww3_strt, ww3_prep (for the
case with a forcing file) and ww3_shel, in sequence from the namelists, give mod_def.ww3, current.ww3,
out_grd.ww3, out_pnt.ww3, track_o.ww3 and both restarts byte-identical to the reference on 96 files (v,
just rust-only). ww3_prep takes every input type, and ww3_strt every start type
(prep, strt). ww3_prnc reads NetCDF forcing for
types AI and LL, byte-identical on 81 cases whose data are synthetic, because the regtests' NetCDF files are not
in WW3's repository (report). ww3_shel takes water levels, IC0 ice, file winds and
boundary input from nest.ww3, which Rust's ww3_bound writes: 214 comparisons identical over 34 boundary cases (v,
just bound-all), on the host only (bound, W3IOBC).
After the run, ww3_ounf and ww3_ounp write NetCDF files byte-identical to the reference's through the system
libnetcdf (ounf, ounp), ww3_outf and ww3_outp
write the same text files on 40 regtest inputs (outf,
outp), and ww3_trck and ww3_trnc the same track files (v, just track-all, 74
comparisons). Spectral partitioning fields are byte-identical too (partitions).
ww3_bounc is not ported. ww3_shel takes --threads N and, built with the feature mpi, mpirun -n R, with the
same bytes (v, just mpi-pair). With W3SRCE, W3XYP3 and W3KTP3 as compiled SPIR-V on CPU Vulkan and VA
resident on the device, the same files are byte-identical too. Batch 7, the alternative physics, is under way at
the routine level: W3SBT4, MetOcean's bottom friction, is called from W3SRCE in a BT4 build
(report). Thirty more routines, thirteen of ST1, FLX1, ST3, IC1 and IS1 and
seventeen of ST2, ST6, FLX2, FLX3 and FLX4, have every captured call bit-identical on the host and, for the
twenty that run on the device, in SPIR-V (plan, "Batches 7 and 8"). No
model run uses any of them yet. Nothing has run on a real GPU, the PTX has never executed, and
there are no timings: this is a verification result, not a speed one.
Generated by just port-summary from WW3/model/src at 92e2cf66 and rust/ports.tsv.
| WW3 area | Files | Fortran lines | Not comments | Routines with Rust, lines | Share | Partial |
|---|---|---|---|---|---|---|
| Source terms | 38 | 38 360 | 12 613 | 11 987 | 31% | 0 |
| Propagation, structured grids | 7 | 12 190 | 4 783 | 3 059 | 25% | 0 |
| Propagation, unstructured grids | 5 | 20 388 | 10 108 | 0 | 0% | 0 |
| Time loop, updates, state | 20 | 45 309 | 20 815 | 7 657 | 17% | 4 003 |
| File I/O in the model | 10 | 16 697 | 8 463 | 11 570 | 69% | 629 |
| Grid search and metrics | 1 | 9 654 | 5 652 | 3 090 | 32% | 30 |
| Drivers | 12 | 30 440 | 15 373 | 0 | 0% | 2 921 |
| Preprocessors | 22 | 39 924 | 20 309 | 9 637 | 24% | 8 064 |
| Postprocessors | 14 | 28 619 | 17 648 | 11 377 | 40% | 7 295 |
| Coupling and other | 6 | 10 538 | 4 941 | 0 | 0% | 0 |
All of model/src/*.F90 |
135 | 252 119 | 120 705 | 58 377 | 23% | 22 942 |
Other model source: SCRIP/, PDLIB/, .f, .f90, .c |
30 | 26 736 | 13 105 | 0 | 0% | 0 |
| All model source | 165 | 278 855 | 133 810 | 58 377 | 21% | 22 942 |
Routines with Rust sums the whole Fortran routine for each row of rust/ports.tsv with a verdict on the code reached, comments included, so a share is an upper bound on what was exercised, and it counts only the switches of switch_chaceon_shrd. Partial is translated: Rust exists and is not fully reached.
| Rust by evidence, code lines | Lines |
|---|---|
| Real GPU: byte-identical whole runs | 0 |
| SPIR-V on CPU Vulkan (lavapipe); its kernels also natively on the CPU | 5 189 |
| Native on the CPU only | 10 080 |
| Every captured call identical, no whole-run verdict | 3 090 |
| Partly reached, or compiled and never run | 10 870 |
| Rust ported | 29 229 |
| Verification tools, not port code | 5 936 |
Badges compare code lines on both sides: 133 810 Fortran and C lines of all model source that are not comments or preprocessor lines, every switch included, out of 278 855 lines with comments; WW3's regtest programs are not port targets. They are compared against Rust lines that are not blank or // comments. The two languages' lines are not the same unit, so the ratio is not a percentage of the port. CPU validated is the first two rows. SPIR-V on CPU Vulkan is compiled for a GPU API but runs on a CPU, so it does not count as GPU validated. A Rust file counts at the weakest ledger row pointing at it, which never overclaims and understates shel.rs and gridpre.rs, partly reached only through W3WAVE and W3NMLGRID.
| Rust, all lines | Lines |
|---|---|
ww3-kernels, runs on the device |
6 492 |
ww3-libm, glibc's bits in plain Rust |
1 273 |
ww3-host, the host side |
20 557 |
| GPU entry points and builders | 1 900 |
| Tools | 9 415 |
| All | 39 637 |
| Verdict, lines of Fortran routines | Lines |
|---|---|
spirv: byte-identical whole runs on CPU Vulkan |
7 828 |
host: byte-identical whole runs on the CPU |
43 879 |
routine: every captured call identical |
6 670 |
translated: exists, not fully reached |
22 942 |
What still depends on Fortran. No Rust binary links Fortran. A run still reads files that Fortran programs wrote where Rust stops: mod_def.ww3 from ww3_grid for unstructured and SMC grids, formatted or unformatted data files (IDFM 2 and 3), the old ww3_grid.inp and tripole closure; the forcing file of ww3_prnc for input types AT, F1, F2 and DAT and of either forcing program on an unstructured grid; and nest.ww3 from NetCDF spectra, which only Fortran's ww3_bounc writes (Rust's ww3_bound writes it from text spectra). Rust's ww3_shel takes water levels, ice and boundary input on the host and refuses them on a device. ww3_prep and ww3_prnc are 4 470 lines, 2% of model/src. Every verdict also needs the Fortran reference, by design: it is what Rust is compared with.
| Read | For |
|---|---|
AGENTS.md |
The rules |
docs/RUST_GPU_PLAN_202610.md |
The plan, in batches |
docs/FLOAT_REPRESENTATION_202610.md |
f32 and f64 against Fortran's kinds |
docs/LEAN_202610.md |
What Lean proves here, and what it cannot |
docs/WW3_GPU_PARITY_202611.md |
Feature parity with ww3-gpu, switch by switch |
docs/ADRs/ |
The decisions |
VERSIONS.md |
What is pinned |
MPL-2.0, translated files included (ADR-0006). WAVEWATCH III is a trademark of the NWS.