Skip to content

Production single-node Kokkos runtime: no-copy resident VA, strict mode, preset, packaging, GPU-run plan - #191

Merged
h0ffmann merged 27 commits into
mainfrom
goal/abbb0456-6043-production-single-node
Oct 18, 2026
Merged

h0ffmann merged 27 commits into
mainfrom
goal/abbb0456-6043-production-single-node

Conversation

@h0ffmann

@h0ffmann h0ffmann commented Oct 18, 2026 •

Copy link
Copy Markdown
Owner

Before. The resident Kokkos preset of the fork (WW3@80644ba9) was byte-identical to the Fortran on ww3_shel's smoke and full, but not production-ready:

  • ww3_multi gave wrong numbers. Its exchanges between grids wrote VA on the host between W3WAVE calls, while the device copy was marked current. So mww3_test_02 to _04 differed from the Fortran in 4 to 10 files.
  • W3WAVE copied the whole spectrum back to the host at every return.
  • Partitioning, boundary output and track output each copied the whole spectrum at every output time.
  • WW_KOKKOS_ALL=1 and the W3SRCE gate fell back to the Fortran without a word, so a "pass" could compare the Fortran with itself.
  • The preset lived in the lab script. ww_kokkos could not be installed without GoogleTest, NetCDF and Fortran.
  • No CUDA build had been checked for this preset.

After. WW3/ is pinned at 50a10730 (fork branch ww3-gpu/integ-fixes), and the tree is rebased onto main c04035e, with #192, #193 and #194.

  • No whole-spectrum copy in steady state. W3WAVE no longer reads VA at its return. ww3_multi's exchanges, the boundary output and the track output sync only the columns they read or write. W3CPRT (partitioning) and W3OUTG's partition fields run on the resident VA. On full, the copies are 1 host-to-device (the bind) and 0 device-to-host (v). That is now a hard rule in AGENTS.md, "Resident spectrum".
  • ww3_multi is byte-identical on mww3_test_01 to _05 (SHRD), also with WW_KOKKOS_VA_POISON=1 (see the regtest table).
  • The ESMF cap reads VA once before its exports (not compiled here ⚠).
  • WW_KOKKOS_STRICT=1 turns every fallback into a stop with its reason. Without it, the run prints one line with the count of calls left on the Fortran. The regtest driver's Kokkos runs use strict mode.
  • WW_KOKKOS_PRESET=resident is read through W3INIT, from one table (presets.txt) shared by the shim, the script and the driver. CPRT is in it.
  • An install-only ww_kokkos (WW_KOKKOS_BUILD_TESTS=OFF) needs Kokkos only, and its package config pins the Kokkos version and backends. ADR-0018 (Proposed) asks where ww_kokkos lives for upstream. The licence statement is corrected: 249 of 347 files under kokkos/src are LGPL-3.0-or-later.
  • The CUDA build of the preset compiles (--build-only, no device run). A checklist for your supervised GPU run is in docs/GPU_SUPERVISED_RUN_CHECKLIST_202610.md.
  • Plans: 002 (this PR), 003 (the first supervised GPU run, and the five plans after it), 004 (the pin to production/GFS.v17, in its own PR).

Goal abbb0456-6043, Claude Code session e664b977-8f49-44ff-a914-0cf9abbb0456.

Evidence

Machine: i9-14900, 32 threads, OpenMP backend, gfortran and g++ 16.2.0, Kokkos 5.2.2. The machine was shared during these runs, so every wall time here is ⚠, and none is for a table.

Check, on daaef07 Result
just kokkos-test serial-debug, openmp-release 11/11, 11/11
just ww3-gpu-matrix-selftest, bash scripts/ww3-gpu.sh --self-test, port_score.py --check ok
python3 -m unittest discover tests 88 OK in a clean worktree. In a checkout that holds agent worktrees under .claude/worktrees/, test_results fails because results.py check also scans those untracked copies
WW_KOKKOS_VA_POISON=1 WW_KOKKOS_VA_COUNT=1 bash scripts/ww3-gpu.sh --ww3-gpu smoke --cpu --kokkos resident every model file byte-identical to the Fortran of the same executable; every file except the NetCDF byte-identical to --ww3, and nccmp-tol passes on the NetCDF
the same with full the same verdicts; VA copies H2D 1, D2H 0
WW3GPU_KOKKOS=resident WW3GPU_LAB_SWITCH=ON just ww3-gpu-matrix 4 serial (the owner, worktree ~/code/ww3-gpu-pr191) entries 1 and 2, ww3_tp2.6 ST4 and ST4_ASCII: FAIL, left as FAIL by the owner's decision, ran fortran-only, kokkos_spectra 0. The Kokkos run stops at start-up with W3KOKKOSMD : WW_KOKKOS_XYP3=1, BUT ITS KOKKOS TRANSLATION DOES NOT COVER THIS SWITCH FILE (logs/1.K.log:160): LIMON is an unstructured grid, which W3KOKKOS_PROP3_SETUP refuses, and the ww3_ounf IOSTAT=2 after it is a downstream effect. main records the same as refused by design (docs/log/2026-10-18-resident-regtest-lab-switch.md:51). Selection, verdict and parts unchanged. Entries 3 to 7 PASS: ww3_tp2.15 default, -g 5km, -i input_const, -i input_rho (test.comp 0/23, 0/23, 0/23, 0/25, nccmp-tol PASS on dir,dp,fp,hs), ww3_ts2 ST4_PR3_UQ (0/22); ctest 9/11 (v, the run's summary.tsv)
security-reviewer nothing at confidence 8 or above
CI green

Regtests on daaef07, WW3@50a10730 (unit 3; docs/log/2026-10-18-u3-regtests-v2.md)

All runs used WW3GPU_LAB_SWITCH=ON, WW3GPU_STRICT=ON, WW_KOKKOS_STRICT=1 in the Kokkos run, WW_KOKKOS_VA_POISON=1 and WW_KOKKOS_VA_COUNT=1. ww3_self was never needed, because no test.comp difference appeared. D2H counts whole-VA device-to-host copies.

Selection, parts Entries test.comp D2H
serial, resident (the owner's run and unit 3's agree) ww3_tp2.15 x4, ww3_ts2 ST4_PR3_UQ 0/23, 0/23, 0/23, 0/25, 0/22 0
serial, resident ww3_tp2.6 ST4, ST4_ASCII FAIL, left as FAIL by the owner: refused at start-up on an unstructured grid 0
omp, SRCE,OUTG,IOPE,UPDV,CPRT (XYP3/KTP3 refuse moving grids) ww3_ts3 x5, mww3_test_05 x5 (every propagation scheme) 0/20 each, 0/27 each 24 and 153 each, from the Fortran propagation's host write
serial, resident, ww3_multi mww3_test_01 to _04 0/22, 0/23, 0/34, 0/25 12, 0, 3, 0 (before the fix: 24, 384, 216, 864)
omp, SRCE,OUTG,IOPE,UPDV mww3_test_05 ST1, ST4_PR3_UQ_OMP 0/27 each 156 each
serial, mww3_test_07 FAIL: WW3's own ww3_grid fails in the Fortran run too (SDS4 namelist under the lab switch) —
serial, SRCE,OUTG,IOPE,UPDV,CPRT, words PR0;SHRD ww3_tnc1 (partition fields) 0/30, W3CPRT on Kokkos 0
the same with resident ww3_tnc1 FAIL by design: stops in W3INIT naming XYP3 (PR0) —

Not run: the restart-reproduction pair (scripts/restart_pair.sh, new; the owner's test-191-restart.sh), and mww3_test_08 (MPI, ADR-0017). mww3_test_01 to _04 have the source terms off in their grid inputs, so they test the exchanges, the propagation and the outputs on the resident VA, not W3SRCE.

Needs a person's review before merge (AGENTS.md, "Never cheat a regtest tool")

  1. A gate that now prints instead of failing. scripts/ww3-gpu.sh failed a run whose VA was "still newer on the device at finalize". With the exit read gone, that state is normal. The check for a missed sync is now WW_KOKKOS_VA_POISON=1, which fills a stale host copy with NaN.
  2. Strict mode in the regtest driver's Kokkos runs (regtests/cmake/ww3gpu_common.cmake, ww3gpu_kokkos_env). An entry that used to fall back silently now fails.
  3. The selection fix (WW3GPU_NO_OPTS): an entry with no options keeps its place in the list. Every existing selection count is unchanged.
  4. WW3GPU_KOKKOS_PREFIX, which links WW3 against an installed ww_kokkos.
  5. The ESMF cap's read (wmesmfmd.F90, PATCH.md section 29). Not compiled here: there is no ESMF library.
  6. Two FAIL rows that stay FAIL (the owner, 2026-10-18): ww3_tp2.6 ST4 and ST4_ASCII under the resident preset, refused by design at start-up on an unstructured grid (evidence table). They are not dropped from the selection or marked expected-to-fail.
  7. scripts/restart_pair.sh (new, from unit 3): the restart-reproduction pair on a SHRD case. It passes bash -n, shellcheck and its --self-test, and has never run.
  8. selection:count fails on a custom WW3GPU_SWITCH_WORDS list, because regtests/CMakeLists.txt has no expected count for it. The entries themselves ran and passed. Not changed; the owner decides.

Owner steps (not for agents)

  • Run ~/code/ww3-gpu-3/test-191-restart.sh (the restart pair, never run), and test-fortran-ab.sh --controls --patch <the W3SDS4 diff> if the NOAA record needs the Fortran A/B.
  • Fast-forward the fork's ww3-gpu/kokkos-pnt to 50a10730: git -C WW3 push origin 50a10730:refs/heads/ww3-gpu/kokkos-pnt.
  • Timing: a median of three on a quiet machine of main before kokkos: three bit-neutral resident speed-ups, the CPU study PDF, a selected-regtests runner #193, main after it, and this PR. One loaded run on this tree had Kokkos slower than the Fortran (46.4 s against 31.8 s), against your earlier 15.5 s against 23.4 s ⚠. Then the bench/results/ record, and the speed sentence of docs/NOAA_PROGRESS_RECORD_202610.md.
  • Whether the lab-switch regtests let the regtested cells of kokkos/ports.tsv move to "yes".
  • Any GPU run (plan 003, the checklist).
  • Whether to act on the profile's speed proposals. They change loop nesting or skip zero weights, so each one is its own PR with L2 evidence.
  • Where the A/B harness for a Fortran change proposed to NOAA goes (branch goal/abbb0456-6043-fortran-ab, e9366f9).

After merge

docs/NOAA_PROGRESS_RECORD_202610.md then has stale facts:

  • the resident preset has seven parts (CPRT joined);
  • the fork pin is 50a10730;
  • ww3_multi and the restart are now shown, if the table above says so.

🤖 Generated with Claude Code

@h0ffmann
h0ffmann marked this pull request as draft October 18, 2026 14:51
@h0ffmann h0ffmann changed the title docs/compound: plan for the production single-node Kokkos runtime Production single-node Kokkos runtime: no-copy resident VA, strict mode, preset, packaging, GPU-run plan Oct 18, 2026
@h0ffmann

Copy link
Copy Markdown
Owner Author

Open concerns for review

These are recorded while the PR is in draft. Each one says what was checked and what was not.

1. The CUDA build compiles its host C++ with another g++

  • In the CPU build, both gfortran and g++ are 16.2.0.
  • In the CUDA build (the #cuda shell), gfortran is still 16.2.0, so WW3's Fortran is compiled the same way. But nvcc_wrapper hands the host half of every .cpp to g++ 14.4.0. That covers the shims, the table set-up and every host branch of a kernel (v, docs/log/2026-10-18-cuda-build-only.md:25-26, :74-77).
  • Every static parity argument in kokkos/ports.tsv read g++ 16.2.0's output. No host path compiled by g++ 14.4.0 has been compared with the Fortran ⚠.
  • Why the shell pins g++ 14.4 is not recorded. Presumably it is the newest host GCC that nvcc 12.9 accepts ⚠ (not read in NVIDIA's support matrix).
  • Device code is compiled by nvcc's device compiler with --fmad=false, -prec_div=1, -prec_sqrt=1 and -ftz=0, and no fast-math flag (v, same log).
  • Next step: plan 003's phase A4 runs the CPU reference on the frozen commit. It does not cover this. Phase A3 should add the -O3 GIMPLE of one host-side shim path under both compilers, or a CPU-backend build of the library with g++ 14.4 run pair to pair, so the GPU run is not judged on an unknown host compile.

2. The total number of whole-spectrum copies has not dropped yet (U8)

  • Boundary output and track output now read only their columns: 70 kB in all on ww3_tr1, and 4.4 kB of track columns on ww3_tp2.2 (v, docs/log/2026-10-18-resident-output-readers.md).
  • The per-run count of full copies is unchanged, because another sync in the same step still copies VA:
    • W3WAVE's exit read on ww3_tp2.2. U1, still running, removes it.
    • The host write after the Fortran PR1 propagation on ww3_tr1, every step. This PR does not cover it.
  • The PR is not done on the "Resident spectrum" rule until U1's WW_KOKKOS_VA_COUNT=1 numbers show the drop.

3. A fork defect found and fixed

No KOKKOS switch without PR3 compiled: W3KOKKOS_MAP3 and W3KOKKOS_MAPT used W3ADATMD names that exist only under PR3. Fixed on the fork in 31a09522 (branch ww3-gpu/u8-out-readers). It goes into the one pin bump at the end of this PR.

4. A regtest-driver bug, not fixed (needs a person's review)

In regtests/cmake/ww3gpu_common.cmake:337-343, ww3gpu_select_entries drops the empty options of the first selected entry when that entry has none. E_OPTS then has one item fewer than E_TESTS, and configure stops with "list index out of range" (seen on the SHRD;RTD selection). U8 ran ww3_tr1 through run_entry.cmake directly for that reason ⚠. The fix changes how entries are selected, so it is a change to a comparison's invocation: it waits for review (AGENTS.md, "Never cheat a regtest tool").

5. Licence statement corrected (U6)

Gap 12 said the C++ is MIT. The SPDX lines say otherwise:

  • 249 of the 347 files under kokkos/src are LGPL-3.0-or-later;
  • 22 are MIT;
  • 76 have no SPDX line.

ADR-0018 (Proposed) builds on these counts. The licence of the 76 files without an SPDX line, and the legal reading of each option, are open ⚠.

6. Changes to comparisons or their invocation in this PR

A person reviews these before merge:

  • the U2 strict mode in regtests/cmake/run_entry.cmake (coming);
  • WW3GPU_KOKKOS_PREFIX in scripts/ww3-gpu.sh (U6), which changes which ww_kokkos WW3 links;
  • any fix for item 4.

h0ffmann added a commit that referenced this pull request Oct 18, 2026
The owner asked for a stable WW3 pin. NOAA-EMC/WW3's only release tag is
6.07.1 (2019); NOAA ships through production branches. The owner chose
production/GFS.v17 (7a23cd77) in its own PR after #191: every file of the
KOKKOS patch and two ported modules changed there, ST4 and the DIA did
not.

Tested: nix shell nixpkgs#vale -c scripts/vale.sh on the plan, 0 errors; facts from git ls-remote, gh release list and git diff --stat in WW3-noaa/

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@h0ffmann
h0ffmann marked this pull request as ready for review October 18, 2026 16:37
h0ffmann added a commit that referenced this pull request Oct 18, 2026
The owner asked for a stable WW3 pin. NOAA-EMC/WW3's only release tag is
6.07.1 (2019); NOAA ships through production branches. The owner chose
production/GFS.v17 (7a23cd77) in its own PR after #191: every file of the
KOKKOS patch and two ported modules changed there, ST4 and the DIA did
not.

Tested: nix shell nixpkgs#vale -c scripts/vale.sh on the plan, 0 errors; facts from git ls-remote, gh release list and git diff --stat in WW3-noaa/

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@h0ffmann
h0ffmann force-pushed the goal/abbb0456-6043-production-single-node branch from 43bc284 to b0bdbd9 Compare October 18, 2026 17:48
h0ffmann and others added 23 commits October 18, 2026 14:48
Goal abbb0456-6043, from the owner's brief of 2026-10-18 (session
e664b977-8f49-44ff-a914-0cf9abbb0456): seven units after #189 and #190,
the ww3_multi resident VA first, then strict mode, wider CPU regtests,
a preset W3INIT reads, GPU build-only readiness, packaging and a stale
remark. Records the brainstorm decisions B1 to B6.

Tested: nix shell nixpkgs#vale -c scripts/vale.sh on the plan, 0 errors

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The owner rejected a host-to-device copy of VA per grid per step: the fix
must not cost speed. The plan now syncs after the WMIOHG and WMIOEG host
writes only, so ww3_shel pays nothing.

Tested: nix shell nixpkgs#vale -c scripts/vale.sh on the plan, 0 errors

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The owner, 18 October 2026: a defect of the resident VA is never fixed by
copying the whole spectrum between host and device per step, per grid or
per W3WAVE call; sync what the host wrote, where it wrote it. Stated in
AGENTS.md (invariant and section), CONTRIBUTING.md and the ww3-port skill.

Tested: nix shell nixpkgs#vale -c scripts/vale.sh AGENTS.md CONTRIBUTING.md, 0 errors; python3 .claude/hooks/check_agent_frontmatter.py, ok

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The owner, 2026-10-18: the resident spectrum is the design, with no
copies. U8 turns the output readers' whole-array reads into column reads,
U9 ports partitioning onto the resident VA, U1 moves the ww3_multi
exchange to the device and drops W3WAVE's exit read.

Tested: nix shell nixpkgs#vale -c scripts/vale.sh on the plan, 0 errors

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… drafted

Unit U6 of the production single-node plan (goal abbb0456-6043). WW_KOKKOS_BUILD_TESTS
(default ON, today's tree) set OFF configures ww_kokkos with C++ only and Kokkos as the one
package searched: no GoogleTest, NetCDF, tools, intro programs or Fortran module. The kernels
and their PRIVATE contraction flags are unchanged; the 25 objects equal openmp-release's.
The installed ww_kokkosConfig.cmake (from cmake/ww_kokkosConfig.cmake.in) records
Kokkos_VERSION, Kokkos_DEVICES and Kokkos_ARCH, asks for find_dependency(Kokkos <v> EXACT),
which Kokkos' basic version file honours, and refuses other backends or architecture. No fork
change: WW3's find_package(ww_kokkos 0.9 REQUIRED) is untouched.

scripts/ww3-gpu.sh gains WW3GPU_KOKKOS_PREFIX, so --ww3-gpu builds WW3 against an installed
package elsewhere (a changed prefix reconfigures WW3). ADR-0018 (Proposed) sets out where
ww_kokkos could live for upstream: an external package, a submodule of WW3, or inside
model/src, with no option chosen; its licence count corrects gap 12, which called the C++ MIT
(249 of 347 files are LGPL-3.0-or-later, 22 MIT, 76 without a line, legal reading pending).
Gaps 5 and 12 of PRODUCTION_READINESS_202610.md, kokkos/README.md and the glossary updated.

Tested: install-only configure traced with cmake --trace-expand in the #ww3 shell: only
find_package(Kokkos) and Kokkos' own find_package(OpenMP) ran, Kokkos_DIR the only package
dir in the cache; build + install into kokkos/build/install-only.prefix: ok; a consumer
find_package(ww_kokkos 0.9) finds Kokkos 5.2.2, stops on a recorded 5.2.1 (EXACT) and on
recorded backends CUDA;SERIAL; WW3GPU_KOKKOS_PREFIX=<prefix> scripts/ww3-gpu.sh --ww3-gpu
smoke --cpu: Kokkos/Fortran byte-identical, every binary file byte-identical to --ww3,
nccmp-tol PASS with 0 difference; just kokkos-test serial-debug and openmp-release: 11/11
each; scripts/ww3-gpu.sh --self-test ok; shellcheck and bash -n ok; vale 0 errors on the 5
Markdown files; python3 -m unittest discover tests: 88 OK; port_score --check current.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Goal abbb0456-6043, unit U5 of docs/compound/plans/2026-10-18-002-production-single-node-plan.md.
ww_kokkos (cuda-release) and the fork for the resident preset were built on Kokkos' CUDA
backend, build only, with no device run; the 51 nvcc warnings are listed in a dated log entry,
none in a wired part (48 host-only lambdas in the unwired DO_OUTPUT_EXCHANGES, the GCC novector
pragma nvcc does not know and still forwards, one dead store). The checklist gives the owner the
order of the supervised run (libm_bits --device, smoke, full, the CUDA matrix on the entries U3
passed, filled by the integrator) and what ADR-0014 asks each step to record. It notes that
just ww3-gpu-matrix-cuda forwards neither WW3GPU_KOKKOS nor WW3GPU_LAB_SWITCH, left for review.

Tested: nix develop picasso/labs/pratico#cuda --command cmake -S kokkos --preset cuda-release and
cmake --build kokkos/build/cuda-release -j8: pass; JOBS=8 scripts/ww3-gpu.sh --ww3-gpu smoke
--gpu --kokkos resident --build-only: pass (21 programs); nix shell nixpkgs#vale -c
scripts/vale.sh on the 7 changed files: 0 errors, 0 warnings; python3 scripts/figures.py check:
pass; relative links of the changed pages resolve. No GPU run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ns after it

The owner asked whether WW3 with its step resident on the GPU can beat
the CPU-only resident run, and for the next five plans for speed or
correctness, consolidated with NOAA's GFS-Wave use case. Plan 1, the
first supervised GPU run, is detailed for the next session: agent
preparation with no device run (tool fixes for human review, builds,
CPU reference, static occupancy), the owner's ordered session with a
stop rule per step, and the decision table for plans 2 and 4. The
traps come from a read of ww3-gpu.sh, nccmp-tol, results.py,
libm_bits.sh and the CUDA build-only record.

Tested: nix shell nixpkgs#vale -c scripts/vale.sh on the plan, 0 errors

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Goal abbb0456-6043, unit U8 of the production single-node plan. On the
fork branch ww3-gpu/u8-out-readers (31a09522, 791e8c34 on 80644ba9; no
gitlink change here), under WW_KOKKOS_IOPE=1 W3IOBC ('WRITE') reads back
only the columns ISBPO and W3IOTR only the columns of its track points,
from inside W3IOTR once the track file is read; the OASIS coupling's sync
is dropped because it reads no VA; W3IOSF keeps its full read because it
partitions every sea point. The shim keeps up to four column lists per
grid so the point and boundary outputs do not reallocate at every call.
PATCH.md section 23 and the docs/log entry carry the Fortran lines read,
the static -O3 check of W3IOTR and the counters before and after; the
whole-spectrum copies per run did not drop in the two entries, because
another full sync follows in the same step.

Tested: just kokkos-test openmp-release and serial-debug (11/11 each);
WW3GPU_LAB_SWITCH=ON WW_KOKKOS_VA_POISON=1 WW_KOKKOS_VA_COUNT=1
ww3_tp2.2 PR3_UQ resident test.comp 0/24, ww3_tr1 -i input_std
SRCE,OUTG,IOPE,UPDV test.comp 0/23 via run_entry.cmake; bash
scripts/ww3-gpu.sh --ww3-gpu smoke and full --cpu --kokkos resident
byte-identical to the Fortran and --ww3 (D2H 37 and 1, unchanged);
bash scripts/ww3-gpu.sh --self-test ok; scripts/vale.sh on the three
Markdown files 0 errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…IA changes

Another session builds the W3SDS4 loop interchange, a DIA direction-halo
layout and -fno-math-errno on goal/eb10363f-4821-noaa-progress-record.
Plan 2 starts from that result, and both PRs need one resident regtest
pass on the combined tree before a timing enters a table.

Tested: nix shell nixpkgs#vale -c scripts/vale.sh on the plan, 0 errors

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the GPU run

The CUDA build compiles its host C++ with g++ 14.4.0, the CPU build and
every parity argument with g++ 16.2.0; gfortran is 16.2.0 in both. Phase
A3b runs the CPU backend under g++ 14.4.0 pair to pair, or compares the
GIMPLE, so a GPU difference can be split between device and host.

Tested: nix shell nixpkgs#vale -c scripts/vale.sh on the plan, 0 errors

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…resets.txt (goal abbb0456)

Gaps 6 and 7 of docs/PRODUCTION_READINESS_202610.md, unit U2 + U4 of
docs/compound/plans/2026-10-18-002-production-single-node-plan.md. part_flags.cpp
reads WW_KOKKOS_STRICT and WW_KOKKOS_PRESET once, turns a preset's parts on as
if each WW_KOKKOS_<PART> were 1 (a set WW_KOKKOS_<PART> still wins), and keeps
the per-part count of calls left on the Fortran, printed in one line at exit.
The resident part list moves from scripts/ww3-gpu.sh into
kokkos/src/fortran_iface/presets.txt, which CMake compiles into the shim and the
script and the regtest matrix read. The fork side is h0ffmann/WW3 branch
ww3-gpu/u2-strict-preset (f0cbe70d strict mode, 237ca0de the preset, on
80644ba9); the WW3/ gitlink is not moved here, the integrator bumps it once.
PATCH.md sections 24 and 25, GLOSSARY, kokkos/README.md.

Needs human review before merge: the matrix's Kokkos run now sets
WW_KOKKOS_STRICT=1 (ww3gpu_kokkos_env, regtests/cmake/ww3gpu_common.cmake) and
every run unsets WW_KOKKOS_PRESET, which changes how a comparison is invoked: an
entry whose Kokkos run would fall back to the Fortran now fails instead of
comparing the Fortran with itself.

The hot path: one new per-step function, W3KOKKOS_SRCE_STEP, outside the loop
over sea points, adds a test of two LOGICALs per step; the fallback branch is one
call and one increment; no getenv, string or lock per call or per point.

Tested: just kokkos-test serial-debug (11/11 passed); just kokkos-test
openmp-release (11/11 passed); just ww3-gpu-matrix-selftest (ok; 99 serial,
50 omp, 161 mpi, 310 all, 7 resident serial at 80644ba9, unchanged); bash -n
and shellcheck scripts/ww3-gpu.sh (clean); bash scripts/ww3-gpu.sh --self-test
(ok); vale on the four Markdown files (0 errors); bash scripts/ww3-gpu.sh
--ww3-gpu smoke --cpu --kokkos resident before and after (every model file
byte-identical to the Fortran's and to the run before this change); the
same run with only WW_KOKKOS_PRESET=resident (parts line and all four model
files identical); WW_KOKKOS_PRESET=bogus stops; WW_KOKKOS_ALL=1 with TAUWBUG=0
counts SRCE=2160 and with WW_KOKKOS_STRICT=1 stops naming the reason

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…oal abbb0456)

ww3gpu_select_entries built <prefix>_OPTS with list(APPEND), and a CMake list
cannot hold an empty first item: when the first selected entry had no options
(ww3_tr1's first line, "$rtst $ww3 ww3_tr1"), E_OPTS had one item fewer than
E_TESTS, every later entry read the next one's options and configure stopped with
"list index: 3 out of range (-3, 2)" (WW3GPU_KOKKOS=resident
WW3GPU_SWITCH_WORDS="SHRD;RTD" just ww3-gpu-matrix-list serial, found by agent F).
An entry with no options is now the placeholder WW3GPU_NO_OPTS, and
ww3gpu_entry_opts reads it back as empty where regtests/CMakeLists.txt and
stage.cmake take an entry's options. selftest.cmake gets a fixture whose first
entry has no options, read back item by item.

Needs human review before merge: this changes how entries are selected and
which options each entry runs with.

Tested: just ww3-gpu-matrix-selftest (ok; the new fixture gives 3 tests and
3 options, read back as [], [-s K1 -w work_K1], []); just ww3-gpu-matrix-list
for serial, omp, mpi and all, default and WW3GPU_KOKKOS=resident: 99, 50, 161,
310 and 7, 0, 0, 7 tests, unchanged against the same commands before the fix;
WW3GPU_KOKKOS=resident WW3GPU_SWITCH_WORDS="SHRD;RTD" serial: 4 tests, was the
out-of-range error; the generated CTestTestfile gives the first ww3_tr1 entry
OPTS= (empty) and the next ones their own options

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…al abbb0456)

The table of what the two sections were checked on: the resident smoke before and
after, the preset alone, an unknown preset, TAUWBUG = 0 counted and stopped under
WW_KOKKOS_STRICT=1, and UWND left on the Fortran by a WNT2 switch, counted and
stopped. The preset's fork commit is 237ca0de after a fix of its report line (the
preset's name printed before the parts line, not in place of it).

Tested: nix shell nixpkgs#vale -c scripts/vale.sh on the four Markdown files
(0 errors, 0 warnings); the runs in the table, commands in PATCH.md section 24

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The owner asked for a stable WW3 pin. NOAA-EMC/WW3's only release tag is
6.07.1 (2019); NOAA ships through production branches. The owner chose
production/GFS.v17 (7a23cd77) in its own PR after #191: every file of the
KOKKOS patch and two ported modules changed there, ST4 and the DIA did
not.

Tested: nix shell nixpkgs#vale -c scripts/vale.sh on the plan, 0 errors; facts from git ls-remote, gh release list and git diff --stat in WW3-noaa/

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
c487900 committed a product_contract_source value with an unquoted
': ', which YAML refuses; vale's failure was hidden by a pipe. Quoted.

Tested: nix shell nixpkgs#vale -c scripts/vale.sh on the plan, rc 0, 0 errors

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… at W3WAVE's return

Goal abbb0456-6043, units U1 and U7 of the production single-node plan (gaps 2 and 13 of
docs/PRODUCTION_READINESS_202610.md). With the resident VA, ww3_multi's WMIOHG and WMIOEG wrote
a grid's VA on the host between W3WAVE calls with no sync; the matrix with the lab switch showed
it: WW_KOKKOS_VA_CHECK=1 stops mww3_test_02 to _04, and without it they differ from the Fortran
in 5, 10 and 4 files (ww3_self 0). The owner refused a whole-VA copy at W3WAVE's exit, so the
fork branch ww3-gpu/u1-multi-va (f330dc53, five commits on 80644ba9; no gitlink change here)
syncs only the columns each exchange reads or writes and drops the read at W3WAVE's return.
Here: ww_va_host_wrote_cols (ww_kokkos 0.10.0), a column scatter sharing the column lists of
the partial read (now up to 8 per grid); PATCH.md section 24 with every host use of VA outside
W3WAVE; the fork's wminiomd.F90 and wmwavemd.F90 as FILE lines of parts.d/resident.txt;
scripts/ww3-gpu.sh prints the "still newer on the device at finalize" line instead of failing
on it, since no read at the return is now the design (a gate change for a person to review);
the docs/log entry with before and after; ports rows and reports for WMIOHG and WMIOEG; the
glossary rows; gaps 2 and 13 updated.

Tested: WW3GPU_KOKKOS=resident WW3GPU_LAB_SWITCH=ON WW3GPU_SWITCH_WORDS='PR3,UQ,SHRD,!PDLIB,!MGP,!MGG'
just ww3-gpu-matrix 2 serial -R '^0(33|34|38|43):' and WW3GPU_KOKKOS=SRCE,OUTG,IOPE,UPDV
WW3GPU_SWITCH_WORDS='PR3,UQ,SHRD,MGP,!PDLIB' just ww3-gpu-matrix 2 omp -R '^00(2|8):', with the
fork at f330dc53's tree, plain and with WW_KOKKOS_VA_POISON=1 WW_KOKKOS_VA_CHECK=1: test.comp 0
files different on all six; scripts/ww3-gpu.sh --ww3-gpu full|smoke --cpu --kokkos resident,
plain and poisoned: byte-identical to the Fortran and to --ww3, whole-VA D2H on full 1 -> 0;
just kokkos-test serial-debug and openmp-release 11/11; bash scripts/ww3-gpu.sh --self-test ok;
shellcheck scripts/ww3-gpu.sh; python3 scripts/port_score.py --write then --check current;
scripts/vale.sh on the changed Markdown: 0 errors

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The C++ line count of the port changed once U1's shim changes joined U2's
and U8's on one branch; regenerated, not hand-merged.

Tested: python3 scripts/port_score.py --write, then --check, current

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… numbers

Tested: nix shell nixpkgs#vale -c scripts/vale.sh on the plan, rc 0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Goal abbb0456-6043, unit U9 of docs/compound/plans/2026-10-18-002-production-single-node-plan.md.
At every output time with partitioning on, W3WAVE copied the whole VA back
from the device for W3CPRT and W3IOSF, and W3KOKKOS_OUTG fell back to the
Fortran W3OUTG for any partition field. W3CPRT is now translated
(iosf_w3cprt.hpp: per point the Fortran's serial code and the existing
W3PART translation, called unchanged; the DTPRT/ICPRT table placed by an
integer prefix sum) and run on the resident VA by cprt_shim.cpp
(ww_cprt_va, ww_cprt_fetch); W3OUTG section 6 is its own entry point,
ww_outg_part, moved unchanged out of ww::iogo::w3outg. Only the table and
the partition fields W3IOGO writes come back. WW_KOKKOS_CPRT is opt-in.
Fork: h0ffmann/WW3 ww3-gpu/u9-cprt 4f126d85 (gitlink not moved).
PATCH.md section 27, port report W3CPRT_KOKKOS.md, ports.tsv row
w3iosfmd:w3cprt, the W3PART family's regtested and wired cells, GLOSSARY,
docs/log/2026-10-18-cprt-resident.md.

Tested: just kokkos-test serial-debug (11/11, no warning) and openmp-release (11/11); static parity by -O3 GIMPLE of w3iosfmd.F90 and cprt_shim.cpp (port report); scripts/ww3-gpu.sh --ww3-gpu full --cpu --kokkos SRCE,XYP3,KTP3,OUTG,IOPE,UPDV[,CPRT] on two bench_small partition variants (switch_lab_shrd, switch_lab_ompg), WW_KOKKOS_VA_POISON=1 WW_KOKKOS_VA_COUNT=1: every model file and partition.ww3 byte-identical to the Fortran and to --ww3, VA D2H 13 -> 1 in 12 h; smoke byte-identical; WW3 ww3_tpt1.1 PTM1-5 through regtests/cmake/run_entry.cmake (PR3 UQ for PR0): test.comp 0/22 each, nccmp-tol PASS; python3 scripts/port_score.py --write then --check; vale 0 errors on the changed Markdown
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
presets.txt's resident line becomes SRCE,XYP3,KTP3,OUTG,IOPE,UPDV,CPRT, so
--kokkos resident, WW_KOKKOS_PRESET=resident and the matrix's
WW3GPU_KOKKOS=resident partition on the device copy of VA (PATCH.md
section 27) instead of reading it whole at each output time with
partitioning on. CPRT refuses no switch the preset did not refuse
already: W3KOKKOS_CPRT_SETUP accepts SHRD without MPI or T, and
W3KOKKOS_OUTG_SETUP, already in the preset, accepts SHRD without MPI,
IG1, O8, O9 or T (WW3@711afb80 w3kokkos_cprtmd.F90:70-76,
w3kokkos_outgmd.F90:74-80), so the selection words stay. The consumers
follow: the self-test of scripts/ww3-gpu.sh, the fixture parts.d and the
expected lists of regtests/cmake/selftest.cmake, and the docs that
restate the list (README.md, README.pt-BR.md, kokkos/README.md,
docs/GLOSSARY.md, the regtests/CMakeLists.txt comment). Goal abbb0456-6043.

Tested: just ww3-gpu-matrix-selftest (ok, 7 serial / 0 omp / 0 mpi entries of the resident preset at WW3@711afb80); bash scripts/ww3-gpu.sh --self-test (0); shellcheck scripts/ww3-gpu.sh (0); just kokkos-test serial-debug and openmp-release (11/11 each); python3 scripts/port_score.py --write then --check (current); scripts/vale.sh on README.md kokkos/README.md docs/GLOSSARY.md (0 errors); matrix entry 38 ww3_tnc1 with WW3GPU_KOKKOS=resident, WW3GPU_LAB_SWITCH=ON, WW3GPU_STRICT=ON, WW_KOKKOS_VA_POISON=1 WW_KOKKOS_VA_COUNT=1: CPRT=K, test.comp 0/30, failed only its parts-line check for XYP3,KTP3 on a PR0 switch

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A fork-table row for ww3-gpu/integ-fixes (711afb80 on b733066b) and a
section for the three integration tasks: the two W3KOKKOS_CPRT fallbacks
now report to WW_KOKKOS_STRICT through KOKKOS_FALLBACK; CPRT in the
resident preset refuses no switch OUTG did not refuse already; and the
KOKKOS build without PR3 needed no fork change, since 31a09522 already
guards the PR3-only USE of w3kokkosmd.F90:3183 at 80644ba9 and b733066b
contains it. It records ww3_tnc1 (SHRD PR0, partition fields) through
the matrix and the smoke and full pairs at 711afb80, and the preset gap
it found: without PR3 and UQ, XYP3 and KTP3 never reach KOKKOS_PART, so
only the matrix's parts-line check reports them. Goal abbb0456-6043.

Tested: matrix entry 38 ww3_tnc1 (WW3GPU_LAB_SWITCH=ON, WW3GPU_STRICT=ON, WW3GPU_SWITCH_WORDS=PR0;SHRD, WW_KOKKOS_VA_POISON=1 WW_KOKKOS_VA_COUNT=1) with WW3GPU_KOKKOS=resident (test.comp 0/30, parts-line check fails on XYP3,KTP3) and SRCE,OUTG,IOPE,UPDV,CPRT (passes, test.comp 0/30, whole-VA D2H 0); bash scripts/ww3-gpu.sh --ww3-gpu smoke|full --cpu --kokkos resident with the same two variables at WW3@711afb80 (byte-identical to the Fortran and to --ww3, nccmp-tol PASS, whole-VA D2H 37 and 0); scripts/vale.sh kokkos/src/fortran_iface/PATCH.md (0 errors)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent H found that on a switch without PR3 and UQ the PROP3 setup compiled
to nothing, so the resident preset ran XYP3 and KTP3 on the Fortran
without a word, under strict mode too. The fork commit a304018c asks
KOKKOS_PART with SUPPORTED false there.

Tested: gfortran -E -P of w3kokkos_prop3md.F90, switch_lab_shrd and switch_lab_ompg plus KOKKOS, identical apart from blank lines; ww3_tnc1 matrix entry 38, WW3GPU_KOKKOS=resident, WW3GPU_LAB_SWITCH=ON, words PR0;SHRD, at a304018c: the Kokkos run stops in W3INIT naming XYP3; nix shell nixpkgs#vale -c scripts/vale.sh PATCH.md, rc 0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ixes

One pin bump for goal abbb0456-6043: the fork commit a304018c (branch
ww3-gpu/integ-fixes of h0ffmann/WW3) merges ww3-gpu/u1-multi-va,
u2-strict-preset, u8-out-readers and u9-cprt onto 80644ba9, plus the
CPRT strict fallbacks (711afb80) and the PROP3 setup without PR3
(a304018c). The WMIOHG, WMIOEG and W3CPRT rows of kokkos/ports.tsv are
wired at this pin; the port score is regenerated.

Tested: python3 scripts/port_score.py --write, then --check, current; the fork commits' own evidence is in PATCH.md sections 23 to 28

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
h0ffmann and others added 3 commits October 18, 2026 14:48
The fork commit 50a10730 (ww3-gpu/integ-fixes) adds one host read of VA
in WMESMFMD's SetExport: with no read at W3WAVE's return, the ESMF cap's
export fields would have read a stale host VA. wmesmfmd.F90 joins the
FILE lines of parts.d/resident.txt, so --ww3's fork check accepts it, and
PATCH.md section 29 records it. The file is compiled only with
MULTI_ESMF, which no regtest here builds, so the evidence at a304018c
holds.

Tested: gfortran -E -P of wmesmfmd.F90 with switch_lab_shrd, without KOKKOS identical to WW3-noaa's apart from __LINE__ in ESMF messages and the include-path comment; bash scripts/ww3-gpu.sh --self-test ok; nix shell nixpkgs#vale -c scripts/vale.sh PATCH.md, rc 0; not compiled (no ESMF library)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tested: python3 scripts/port_score.py --write, then --check, current

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Plan 003: #193 is merged; the CUDA Docker image of #192 builds with
WW_KOKKOS_LIBM=OFF, so it calls CUDA's libm and stays out of the first
GPU run; #194's KOKKOS_LIBM_ON_VS_OFF.md holds the owner's decision on
that option, and A3 records the value the run's build has. Plan 004: the
UFS NUOPC cap on production/GFS.v17 reads VA after W3WAVE, so its host
uses are listed and synced, and one coupled case runs with the VA
poison, as section 29 did for the ESMF cap.

Tested: nix shell nixpkgs#vale -c scripts/vale.sh on both plans, rc 0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@h0ffmann
h0ffmann force-pushed the goal/abbb0456-6043-production-single-node branch from b0bdbd9 to daaef07 Compare October 18, 2026 17:52
@h0ffmann

Copy link
Copy Markdown
Owner Author

Two FAIL rows that stay FAIL (the owner, 2026-10-18)

The owner's serial run on daaef07, WW3GPU_KOKKOS=resident WW3GPU_LAB_SWITCH=ON just ww3-gpu-matrix 4 serial (worktree ~/code/ww3-gpu-pr191):

  • Entries 1 and 2, ww3_tp2.6 ST4 and ST4_ASCII: FAIL. ran is fortran-only and kokkos_spectra is 0.
  • Cause: the Kokkos run stops at start-up with W3KOKKOSMD : WW_KOKKOS_XYP3=1, BUT ITS KOKKOS TRANSLATION DOES NOT COVER THIS SWITCH FILE (build/ww3-gpu-matrix-serial-kokkos-resident-lab/logs/1.K.log:160, v). LIMON is an unstructured grid, which W3KOKKOS_PROP3_SETUP refuses. The ww3_ounf IOSTAT=2 that follows is a downstream effect.
  • Same as main: main already records this as refused by design (docs/log/2026-10-18-resident-regtest-lab-switch.md:51).
  • Decision: both entries stay FAIL. The selection, the verdict and the parts are unchanged, and neither entry is dropped or marked expected-to-fail. The PR body's Tested section and its review list say the same; unit 3's records will too.

Entries 3 to 7 of that run follow when it ends.

…ww3_tnc1

Goal abbb0456-6043, unit U3 of docs/compound/plans/2026-10-18-002-production-single-node-plan.md,
PR #191. On daaef07 with WW3 at 50a10730 and WW3GPU_LAB_SWITCH=ON, WW3GPU_STRICT=ON, every Kokkos
run that ran gave test.comp 0 files different, with WW_KOKKOS_VA_POISON=1: the resident serial
selection (the owner's run and the agent's), the ten ST4 OMPG entries with
SRCE,OUTG,IOPE,UPDV,CPRT, agent A's ww3_multi entries and ww3_tnc1 with CPRT. ww3_tp2.6 (both)
and ww3_tnc1 under resident stop in W3INIT by design (XYP3 refuses an unstructured grid or a
switch without PR3 UQ) and stay FAIL rows, as the owner decided; mww3_test_07 fails in the
Fortran's ww3_grid too. The summaries go to docs/data/, the record to docs/log/, the CPRT row of
kokkos/ports.tsv names the matrix record and stays "no" (the owner decides on lab-switch
evidence), and gaps 2 and 10 are updated.

No matrix.base restart pair is SHRD, so scripts/restart_pair.sh is the smallest equivalent on
the full case. It is new, was not run (the owner stopped new long runs), changes no gate, and
needs a person's review before it merges.

Tested: WW3GPU_KOKKOS=resident WW3GPU_LAB_SWITCH=ON WW3GPU_OMP_THREADS=4 just ww3-gpu-matrix 4 serial (with WW_KOKKOS_VA_POISON=1 WW_KOKKOS_VA_COUNT=1): 5 pass, ww3_tp2.6 x2 FAIL by design
Tested: WW3GPU_KOKKOS=SRCE,OUTG,IOPE,UPDV,CPRT WW3GPU_SWITCH_WORDS='ST4,SHRD,!PDLIB' WW3GPU_LAB_SWITCH=ON WW3GPU_OMP_THREADS=4 just ww3-gpu-matrix 4 omp: 10/10 entries 0 files different; selection:count fails (no expected count for this word list)
Tested: WW3GPU_KOKKOS=resident WW3GPU_SWITCH_WORDS='PR3,UQ,SHRD,!PDLIB,!MGP,!MGG' ... just ww3-gpu-matrix 2 serial -R '^0(33|34|38|43|61):' and -R '^061:': 4 pass, 61 fails in the Fortran ww3_grid
Tested: WW3GPU_KOKKOS=SRCE,OUTG,IOPE,UPDV WW3GPU_SWITCH_WORDS='PR3,UQ,SHRD,MGP,!PDLIB' ... just ww3-gpu-matrix 2 omp -R '^00(2|8):': 2 pass
Tested: WW3GPU_SWITCH_WORDS='PR0;SHRD' just ww3-gpu-matrix 1 serial -R '^038:' with SRCE,OUTG,IOPE,UPDV,CPRT (pass, 0/30) and resident (stops in W3INIT naming XYP3)
Tested: bash -n, shellcheck and --self-test of scripts/restart_pair.sh; python3 scripts/port_score.py --write and --check; scripts/vale.sh on the changed Markdown (0 errors)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@h0ffmann
h0ffmann merged commit 5cd0140 into main Oct 18, 2026
11 checks passed
@h0ffmann
h0ffmann deleted the goal/abbb0456-6043-production-single-node branch October 18, 2026 20:03
h0ffmann added a commit that referenced this pull request Oct 18, 2026
The owner fast-forwarded the fork's ww3-gpu/kokkos-pnt from 80644ba9 to 50a10730, so the
integration branch again holds the pin and the README rows name it, as before #191.

Tested: git -C WW3 ls-remote origin shows ww3-gpu/kokkos-pnt and ww3-gpu/integ-fixes both at 50a10730
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
h0ffmann added a commit that referenced this pull request Oct 18, 2026
The owner stopped this session's runs for another session to continue.
The entry records what PR #191 delivered with its records, the state and
next step of every open branch (the follow-up of #191's review, pushed
without a PR; this PR's ADR-0019 and plan 006; the Fortran A/B harness),
what waits on the owner, and the traps met on the way.

Tested: nix shell nixpkgs#vale -c scripts/vale.sh on the entry and the log index, rc 0; python3 -m unittest discover tests, 88 OK

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
h0ffmann added a commit that referenced this pull request Oct 18, 2026
…production

docs: the NOAA record after #191 with a 10-run median; plan 005, W3SRCE points in lanes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant