Skip to content

Juniata single-catchment sample + deprecate ddr_match (corrected physics by default) - #36

Merged
taddyb merged 2 commits into
masterfrom
juniata-sample
Aug 20, 2026
Merged

Juniata single-catchment sample + deprecate ddr_match (corrected physics by default)#36
taddyb merged 2 commits into
masterfrom
juniata-sample

Conversation

@taddyb

@taddyb taddyb commented Aug 20, 2026

Copy link
Copy Markdown
Owner

Summary

Two tightly coupled changes:

1. examples/juniata/ — the ddrs mirror of DeepGroundwater/ddr#193. A self-contained quickstart on the Juniata River at Newport, PA (USGS 01567000, 8,657 km², 213 MERIT reaches), running on the byte-identical 8.9 MB bundle committed in the ddr repo: icechunk Q' + obs stores, attributes NetCDF, COO adjacency zarrs, one-row gage CSV, plus the attribute-statistics JSON (committed here because ddrs never recomputes statistics). Two commands, no HPC/S3/CUDA:

target/release/ddrs --config examples/juniata/ddrs.yaml plan
target/release/ddrs --config examples/juniata/ddrs.yaml run --workflow train-and-test --backend cpu

2. ddr_match deprecation. DDR ported ddrs's corrected physics (trapezoid-exact celerity β, Cunge-matched X, own-reach gauge readout) in DeepGroundwater/ddr#192 as a clean break, so the flag's default flips to false (corrected). Explicit ddr_match: true still parses with a deprecation WARN (needed to reproduce pre-#192 results and for use_cuda_graphs, whose captured kernel hardcodes the legacy 5/3 celerity). BREAKING: use_cuda_graphs: true without an explicit ddr_match: true now fails config load; config/merit_training.yaml flips to use_cuda_graphs: false.

Cross-implementation validation (same bundle, both directions)

test 1995-10-01 – 2010-09-30 NSE KGE
ddrs routed (30 epochs, CPU, ~21 s) 0.790 0.881
DDR-Python routed (ddr#193 reference) 0.784 0.877
summed-Q' baseline (both implementations, to rounding) 0.695 0.819

The routed residual is only the window-sampling RNG stream (torch global RNG vs ChaCha12; ddrs 4-seed spread NSE 0.790–0.800). Invariant 1 re-anchored: the V1 sandbox fixture is regenerated from post-#192 DDR master and compare_ddr_sandbox reports ABSOLUTE MATCH on the corrected physics (max abs 1.5e-5 m³/s, max rel ~2e-7 — the f32 floor), which doubles as a bit-exactness proof of DDR's #192 port. The 2026-06-06 desktop-only-reference caveat is obsolete.

Test plan

  • cargo test --no-fail-fast green under the new default (one legacy-physics fixture test now pins ddr_match: true; ddr_match_flag.rs asserts the new default; new juniata_bundle.rs contract tests never skip)
  • compare_ddr_sandbox = ABSOLUTE MATCH against the regenerated post-#192 fixture
  • Fresh-clone simulation (tracked files only, clean workspace): plan reproduces the baseline and run --workflow train-and-test --backend cpu reproduces NSE 0.790 / KGE 0.881 from the committed files alone

🤖 Generated with Claude Code

taddyb and others added 2 commits August 19, 2026 23:19
… quickstart

Mirror of DeepGroundwater/ddr#193 on the byte-identical 8.9 MB bundle
(USGS 01567000, 8,657 km², 213 MERIT reaches): icechunk Q' + obs,
attributes NetCDF, COO adjacency zarrs, one-row gage CSV, plus the
attribute-statistics JSON (committed here because ddrs never recomputes
statistics). Full config + README; two commands run plan and
train-and-test on CPU in ~21 s, no external stores.

Cross-implementation results on the same bundle: summed-Q' baseline
NSE 0.695 / KGE 0.819 (matches DDR-Python to rounding); routed
NSE 0.790 / KGE 0.881 vs DDR's 0.784 / 0.877 (residual is the
window-sampling RNG stream only; ddrs 4-seed spread NSE 0.790-0.800).

tests/juniata_bundle.rs asserts the bundle contract through the real
readers and never skips (the bundle is committed). .gitignore gains
!examples/juniata/ddrs.yaml so the example config survives the global
ddrs.yaml ignore; the example workspace examples/juniata/.ddrs/ stays
ignored.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ault

DDR ported ddrs's corrected physics (trapezoid-exact celerity beta,
Cunge-matched X, own-reach gauge readout) in DeepGroundwater/ddr#192 as a
clean break, so both implementations now share one formulation.
default_ddr_match() flips to false; an explicit ddr_match: true still
parses (legacy pre-#192 path, needed for old-result reproduction and for
use_cuda_graphs whose captured kernel hardcodes the 5/3 celerity) but
emits a deprecation WARN. validate_ddr_match's error is reworded for the
new default.

BREAKING: configs relying on the implicit legacy default now run
corrected physics; use_cuda_graphs: true without an explicit
ddr_match: true fails config load. config/merit_training.yaml flips to
use_cuda_graphs: false accordingly.

Invariant 1 re-anchored: the V1 sandbox fixture is regenerated from
post-#192 DDR master and compare_ddr_sandbox reports ABSOLUTE MATCH on
the corrected physics (max abs 1.5e-5 m³/s, max rel ~2e-7 — the f32
floor), which doubles as a bit-exactness proof of DDR's #192 port. The
2026-06-06 desktop-only-reference caveat is obsolete: any DDR checkout
at or past #192 is a valid reference.

Tests: ddr_match_flag.rs asserts the new default and that the legacy
path still loads; leakance_off_parity's committed hydrograph fixture
pins ddr_match: true (it was captured from the legacy chain — recapture
when the legacy path is removed). Full suite green under the new
default.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@taddyb
taddyb merged commit 7e272d8 into master Aug 20, 2026
2 checks passed
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