Releases: FahrenheitResearch/arwen
Release list
ArWen 2.5.0
ArWen 2.5.0
The arbitrary-inputs release. Initialize from 15 weather models through one table-driven engine, mix fields between them, and run the whole data path on Rust. Every route below was proven with a real GPU simulation before shipping.
Install: pip install gpuwm (pulls the new gpuwm-data companion automatically). Python 3.11 to 3.14.
New
- 15 models as initialization sources: GFS, GDAS, HRRR (native and pressure-level), ERA5, 20CRv3 (member archive and public ensemble mean), ICON-EU, AIFS, GEM, ECMWF IFS open data, RAP, GEFS, AIGFS, AIGEFS, RRFS. Adding a model is table work, not code.
- Arbitrary sources: the
mappedroute runs any GRIB2/NetCDF dataset from a user-authored mapping JSON. No adapter code, no rebuild. gpuwm fetch --sourcedownloads bytes for every routed model, parallel by default. Sources without public bytes refuse by name and point at--source-root.- Cross-model composition on shared grids: borrow fields between sources, declared explicitly. The AI models run with GDAS soil this way out of the box.
- Ensemble members are first-class: GEFS and AIGEFS member selection, plus mean, spread, and paintball panels through the Rust ensemble renderer.
- Rust data path end to end: GRIB decode, the mapping engine, terrain and static fields, NetCDF writing, and rendering. The engine reads grids the 2.4 line refused outright, Lambert-projected models like RAP and RRFS included.
- Spectral verification:
gpuwm spectralscores any run against a reference by wavelength band, with coherence, phase error, preregistered gates, and self-hashed receipts. - Run-stamped outputs: every run claims its own
run-<launch>Z_i<init>Z/folder, downloads stay cached across runs,latest-run.txtnames the newest. - The domain wizard accepts every registered source and refuses out-of-coverage domains at plan time with the source's actual window.
- Downscaling has a verified command-by-command walkthrough (
docs/public/DOWNSCALE.md), and tile streaming announces itself in the go banner and files renders per valid day. - Time-to-first-plot instrumentation on by default, with a published scaling law for prep cost.
gpuwm doctorcovers all 31 registered routes, one line each, and prints what changed since the version it last saw.--sourceaccepts any registry id.- Downloads count their bytes as they arrive,
gpuwm setupincluded. No more silent minutes. - New pages: a glossary mapping ArWen vocabulary to its WPS analogues, and a walkthrough of everything a box without a GPU can run.
- A scientific manual for researchers ships with the release, receipts cited throughout, plus a short paper-style summary.
Fixed
- Moving nests reset physics accumulators at every relocation in 2.4.1, wiping convective rain each move. State now moves with the nest, on by default.
- Sub-kilometer nests were floored at 1-minute radiation calls, costing most of the wall clock on fine nests. Nests now inherit the root cadence, and an explicit radt still wins.
- Quickstart output could not be downscaled and nothing said so. It can now, and dry-run warns about anything runtime would refuse.
- Config errors were reported as VRAM refusals. They now name the config problem.
- Watching
progress.jsoncould kill a run on Windows. Runs survive readers. - 2.4.x archives downscale again. 2.4.1 tile caches need one re-preparation, and the refusal names the field.
- GPU installs on driver-only boxes looped forever on a wrong remedy.
pip install 'gpuwm[gpu-cu13]'now works first try, toolkit included. - The HRRR route runs
gpuwm prepthengpuwm simwith no extra flags, and cache restore no longer crashes on solved soil. - Refusals arrive as sentences with remedies, not tracebacks: source coverage, missing data package, short forcing series. When a refusal prints a command, typing it verbatim runs.
- The memory gate priced Windows cards with a guess and refused runs that fit. The envelope is now measured on real hardware, the wizard and the checker use one formula, and profile advice names only configurations your source accepts.
- The domain wizard sizes a config on any box, GPU or not: declare a card, let it measure the local one, or get a refusal naming both options.
- A failed render published an empty run folder and moved
latest-run.txtto it. Folders and pointers now appear only after the first image lands. - Composition scratch moved off the system temp to the run's own disk, so big sources no longer die on RAM-backed
/tmp. - Re-running a printed prep command is a no-op when nothing changed, and a real change refuses naming both digests.
- Renderer: lat/lon grids no longer lose half the frame, and ensemble products ingest each member's whole time series.
- The wheel split into
gpuwmplusgpuwm-dataso both sit well under the PyPI size limit. Installs are unchanged, one command.
Full changelog: CHANGELOG.md
ArWen 2.4.1
2.4.0 was tagged and never published: its own test job refused it on two CLI tests that asserted the exit codes this release deliberately changed. Nothing reached PyPI. 2.4.1 carries everything 2.4.0 built, plus that fix.
New:
- European radar reaches the product.
gpuwm obs radardecodes an ODIM polar volume into the sweeps pack the existing reader accepts, reports per sweep Nyquist and its provenance, and superobs it onto a model domain for the LETKF adapter. No Rust toolchain and no source checkout. - The frozen European radar site table carries an antenna altitude for all 136 sites, read out of the volumes themselves. It refuses a null rather than substituting zero.
- Split file national volumes assemble.
gpuwm obs radar pack --dirbuilds one volume from per elevation files, and refuses a directory holding two nominal times without--stamp. gpuwm obsis the door onto every observation front door: MRMS, Stage-IV, ASOS/METAR, GOES ABI, the European composite and European polar volumes. Baregpuwm obsprints where each binary resolved.gpuwm certifyrefuses an empty kernel manifest and NVRTC compile drift.
Fixed:
- The two CLI tests that refused 2.4.0 declare the capability estate they are about instead of measuring the runner's. The publish workflow's own test list is a pre tag gate now, run with no GPU extra installed.
gpuwm doctorreports every extra the packaging declares, exercises every claim it makes, saysuntestedwhere it cannot exercise something, and means its exit code.- Refusals fire at the front door, before expensive work, and name remedies that exist.
gpuwm go,run,render,run-plan --probeand both prepared runners read one capability registry. - No remedy names an extra that installs nothing. scipy is a base dependency, so the messages that sent readers to
gpuwm[obs]andgpuwm[dealias]name the package instead. - The mapped and 20CRv3 GRIB2 routes resolve their tools through the shared artifact ladder instead of shelling
cargo buildinto a directory no wheel has. - scipy, pyshp, huggingface_hub and h5py are declared where they are used, and the parity between what the wheel imports and what it declares is a gate.
Known issues:
- European radar observations are assimilated and land in the right place with the right footprint, but the analysis magnitude is not yet validated. The ensemble is constructed rather than cycled: mean(d^2)/(spread^2+sigma_o^2) is 9.6, so the size of the increment is not a defensible analysis. Placement is proven on three real volumes: 97.8 percent of the increment within 200 km of the radar, 100 percent within 215 km, all 7,475 radial velocity observations in the solve.
- Reflectivity and clear air assimilation are unexercised on the European route. There is no host reflectivity operator at
mp_physics=10. - A locally built wheel declares no bridge platforms, because pins are generated at release time. Use the published artifact.
Full detail: CHANGELOG.md
ArWen 2.3.3
A fast follow on 2.3.2, which shipped worldwide 30 m terrain that no documented install could reach.
Fixed:
pip install gpuwmnow carries the high-resolution terrain path. rasterio and pyproj were an optionalgeogextra that[all]excluded and no quickstart named, so following the terrain doc downloaded 160.7 MiB of tiles and then died on a missing import. Both are ordinary dependencies now, so every published install line reaches the feature.- The terrain path refuses a missing geography stack before it fetches anything, by name, with the exact command to run. The old check ran after the download and escaped
gpuwm staticas a raw traceback at exit 1. It is one sentence at exit 2 now, with nothing fetched. on_refuse = "fallback-30s"no longer swallows that refusal. A source coverage policy must not answer an install question with 900 m terrain.gpuwm doctorreportsgeography stack (rasterio + pyproj), so the product can say this before a run instead of after a download.gpuwm staticno longer requires a forcing GRIB and a Vtable it never opens. Building terrain no longer needs a forecast cycle on disk first.docs/public/HIGHRES-TERRAIN.mdcarries an install line and a worked example that produces real terrain: one 40 x 40 km Alpine domain at 1 km, about 80 MB of tiles. Verified end to end from a PyPI install.- Terrain doc reproduce commands use
python -m tools.<module>, which works off a wheel.python tools/<file>.pyneeded a source checkout that a pip install does not provide. docs/install.mddocuments every extra, including[obs]and[dealias], which code told users to install and no document mentioned.
Known issues:
- The
geogextra is retained and empty sopip install 'gpuwm[geog]'keeps working. It adds nothing. - Outside the United States a high-resolution run still replaces terrain only. Land use and soil remain the 30 arc-second baseline, unchanged from 2.3.2.
- The base install grows by about 119 MiB. rasterio ships wheels for the same platforms netCDF4 already required, so no platform loses the ability to install.
Full detail: CHANGELOG.md
ArWen 2.3.2
ArWen 2.3.2 builds 30 m terrain anywhere in the world, with no account and no API key.
Install this release with pip install gpuwm[geog]
A plain pip install gpuwm does not install the terrain dependencies. If you install without [geog] and follow the terrain guide, the command downloads about 160 MiB of tiles and then fails with a Python traceback instead of a clear message. gpuwm doctor does not detect it either. This is our bug, not yours. 2.3.3 removes the requirement so that a plain install works.
New
- Copernicus DEM GLO-30 is the default elevation source outside the United States: 30 m ground sampling from 90 S to 84 N, fetched anonymously, no registration required.
terrain_sourcein[static.highres]picks the source by name:auto,copernicus-dem-glo30,srtm-gl1orusgs-3dep-13as.- SRTM is available through OpenTopography's anonymous mirror and declares its own limits, so a request above 60 N or below 56 S is refused by name instead of answered with a hole.
- A domain that runs off the edge of its source is refused with the source named, its footprint printed, and the overshoot given per edge.
- Every run records which source it used and which geoid that source measures against: EGM2008 for Copernicus DEM, EGM96 for SRTM, NAVD88 for 3DEP.
docs/public/HIGHRES-TERRAIN.mddocuments the sources, their limits, their datums, and what switching between them does to a real domain.
Fixed
- Building one domain through two elevation sources keeps both receipts; the second build no longer overwrites the first build's provenance.
- The documentation called USGS 3DEP a surface model. It is bare earth.
Known issues
pip install gpuwmalone cannot run the terrain sources in this release. The dependency check runs after the tile download instead of before it, it raises a raw traceback rather than a named refusal, anddoctorhas no test for it. Installgpuwm[geog]until 2.3.3 lands.- Outside the United States only terrain is upgraded. Land use and soil stay at the older global data, because no freely licensed worldwide land-cover set separates an inland lake from the open sea, and getting that wrong at a coastline costs more than coarse land use does.
- The worldwide default is a surface model, so a forested domain reads about 3.5 m higher than bare ground. Inside the United States
usgs-3dep-13asis bare earth and stays the default there. - Nothing changes for existing United States domains:
terrain_source = "auto"still selects 3DEP and builds the same bytes it built before.
Full notes: https://github.com/FahrenheitResearch/arwen/blob/v2.3.2/CHANGELOG.md
ArWen 2.3.1
ArWen 2.3.1
The complete nesting release.
2.3.0 was tagged but never published: the standalone RW-WPS preprocessing wheel would not build, so nothing reached PyPI. Tags here are forward-only, so the number moved. Everything 2.3.0 carried ships here, plus that fix.
New:
- Two-way feedback nests. A child domain feeds its solution back into its parent, and the parent run carries it.
- A nest can stream its tiles. A parent that cannot hold its child on the card runs the child tile by tile instead of refusing.
- Per-domain
[tiles]control. Any[[domain]]block can carry its owntiles = { ... }table, which replaces the tree-wide table for that grid. - Streamed parent with resident child runs from a plain config through
gpuwm run. Two runs of the same config produced identical bytes on an RTX 5090. - Two-way feedback with a tile-streamed child runs from a plain config through
gpuwm run. Two runs produced identical bytes on an RTX 5090, matching the streamed-parent shape and the all-resident run. - Chain runs: a finished run's wrfout files can start a new higher-resolution child, including a tile-streamed one, with
gpuwm downscale --tiles on. - wrfout files carry the full surface identity, so any ArWen output can initialize a child.
- Streamed runs choose their own tile size against the card they meet, and the run receipt records every grid's decision.
Fixed:
- The standalone RW-WPS preprocessing wheel builds again. It was unbuildable at 2.3.0. Build tooling only: no product source changed and the wheel's behaviour is unchanged.
- Tile streaming now starts on Windows. It could not start at all before.
- A streamed run is bit-identical to the resident run, plots included. Streamed runs used to read their boundary data one timestep late, so upgrade before trusting a streamed result from an earlier version.
- Store-direct streamed runs, the road the largest domains take, carried the same one-step boundary error. The clock is now bound explicitly and checked on every launch.
- Streamed runs publish the OLR the tiles computed. Routes that write frames from the domain state, the offline child included, wrote zeros.
- The ERA5 config route reaches the forecast on every path.
- Nested ERA5 runs apply the terrain soil-temperature correction on child domains.
- A streamed tree prices its children before it tiles the parent. A streamed parent used to claim the whole card and leave its child with nothing to plan.
- A streamed grid names itself in the run receipt even when streaming is declared per domain. It used to stream in silence.
gpuwm doctornow gives correct CUDA toolkit advice and current NVIDIA wheel names when CuPy cannot find CUDA headers.- wrf-rust 0.2.35 through 0.2.x is accepted (0.2.38 verified), so installing gpuwm no longer downgrades a working newer core. The hard
==0.2.35pin is gone.
Known issues:
- Two-way feedback (
feedback = 1) is experimental and is not certified against stock WRF yet. It runs throughgpuwm runonly. gpuwm go --io-mode historywrites no restart, sogpuwm downscalerefuses to chain from agoarchive. Chain fromgpuwm runwithrestart_interval_sset on the parent.- Storm-following (moving) nests run resident. A streamed child refuses relocation with a message naming the grid.
- A coupling edge with both ends streamed is refused. One end of an edge streams, never both.
Changelog: https://github.com/FahrenheitResearch/arwen/blob/main/CHANGELOG.md
ArWen 2.2.1
ArWen 2.2.1 fixes the ERA5 route for everyone it broke: the one-file config that gpuwm domain --source era5 writes now loads in every entry point, so the documented chain from wizard to rendered PNGs runs again from a fresh install.
Fixed
- The config
gpuwm domain --source era5writes is accepted everywhere a config loads:gpuwm check,gpuwm run,gpuwm fetchand the ERA5 initialization front door all consume[case_data]instead of refusing the file it sits in. - Big-domain ERA5 preparation no longer refuses the cache it just wrote; domains of 448x448 and larger prepare again.
- The composed Thompson + Shin-Hong profile no longer stops with a non-finite TKE error on real forecast cases. When its diagnostic-only TKE chain hits a legitimate zero, the value is repaired to the scheme's own floor and the run prints a one-line advisory and continues; that line is expected, not a problem to report.
- An ERA5 series that starts before the experiment start hour is trimmed with a message instead of refused.
- The fetch cache stores one copy of each downloaded object instead of two, cutting its disk use by 25 percent.
gpuwm doctorrecommends the CUDA library wheels that match the CUDA major your box actually serves, and a new check tells a missing CUDA header tree apart from a broken CuPy install and prints the remedy that fixes it.- Releases publish more reliably.
Known issues
- The HRRR native route does not expose
[tiles]. [tiles]streaming currently starts only on Linux; on Windows the memory planner refuses before the configured budget is read.- The ERA5 config route and
gpuwm downscaledo not expose[tiles].
Full detail in CHANGELOG.md.
ArWen 2.2.0
Streamed forecasts now run through the normal config. Put a [tiles] table in a plain TOML, keep your physics, and a domain too big to fit the card runs anyway, with output bit-identical to a resident run.
New
[tiles]in a plain TOML streams a forecast throughgpuwm go, with default physics and either radiation option.- A domain too big to hold in VRAM is admitted and run by default, with no flags:
gpuwm goandgpuwm checknow price a streamed run as streamed, not as the resident run it is not. - Streamed output is bit-identical to a resident run of the same config, field for field and byte for byte, including the running maxima.
tools/streamed_frame_parity.pycompares two runs and reports any field, value or provenance difference between them.- The HRRR horizontal operator runs in the Rust bridge, 107x faster than the mirror it replaces and identical bit for bit.
- Shortwave radiation is armored against the 5090's subnormal flushing with inline PTX, so the same code gives the same numbers on that card.
Fixed
- A streamed run no longer drops
OLRfrom its output. Every frame it wrote was missing that field, and the run still reported success. - A streamed frame that cannot publish everything a resident run publishes is now refused, instead of being written short and passing validation.
- Radiation provenance on a streamed file no longer says nobody wrote the surface fields when radiation demonstrably ran.
UP_HELI_MAXis bit-identical under tiling. It differed at one point per frame, on a tile boundary.gpuwm checkno longer tells you that streaming is refused by the forecast routes. It has not been for a release.- Reflectivity is published by a streamed run rather than refused an hour into a healthy forecast.
- Legacy RRTMG builds its shortwave engine once per process instead of once per tile buffer.
Known issues
- The HRRR native route refuses a
[tiles]table by name, before any download. Support is planned.
Full detail in CHANGELOG.md.
ArWen 2.1.1
Radar velocity dealiasing has a new default engine, a Rust port of Py-ART's region based method. Identical folds, a fraction of the wall clock, and it keeps the strongest couplets the old engine rejected.
2.1.1 is the published form of the 2.1 train. The v2.1.0 tag was never published.
New
- Default dealias engine
region-global: fold for fold identical to Py-ART 2.2.5 on real Level-II volumes, dealias stage 18.3 s to 62 ms, keeps couplet velocities the old engine rejected.--dealias-engine vad-regionselects the old solver;--no-dealias-refinementturns the refinement pass off. - Unfolded gates past 75 m/s are rejected as out of range and counted, never clamped and never passed.
- Correlation coefficient QC at the radar grid build:
--cc-qc, off by default, with per moment rules and a tornado debris fringe exemption (--cc-no-tds-fringe-exemptrestores the strict rule). Receipts count every kept and turned away gate per radar. - The old
vad-regionsolver is over 6x faster where it still runs, with every decision identical. GPUWM_PERF_TIMING=1writes per stage wall clock receipts across the observation, verification and I/O paths.rw_fieldcmpandrw_runscore: Rust judges for paired frames and paired runs. Output identical to the Python judges, 2.6x and 6.6x faster.- A stored hour's plots render in parallel: 85 s to 9 s on a 16 core box, every PNG byte identical to the serial render.
- LETKF analyses report solver timing, and
tools/da_solve_ab.pyA/Bs one analysis between solve devices on byte identical inputs.
Fixed
- The release verifier mishandled bundles carrying more than one library and refused correct artifacts; each library is now proved through the ABI symbol it declares, and vendored artifacts are proved by their contract marker.
- HRRR bridge publication checks hash concurrently; the slowest cases drop from about 270 s to 12 s with identical coverage.
- Two paired run metrics could differ from the reference in the last bit at large sizes; both judges now match at every size.
- The live bundle smoke asserted a stale file count; it now derives from the bundle manifest and passes against the published bundle.
Known issues
- A
[tiles]streamed run launched through the prepared forecast routes fails before its first model step with either shipped full radiation option. The failure is immediate and loud, never a silent wrong result. Domains that fit the card run resident and are unaffected. A fix is in progress for the next release. - The HRRR native route does not expose the
[tiles]table.
Full detail in CHANGELOG.md.
ArWen 2.0.0
A domain larger than the card now runs. Streamed results are bit identical to resident ones, real weather drives a multi-GPU decomposition, and every radiative field a land surface scheme reads must say where it came from.
New
- Streamed forecasts under the
[tiles]table: a grid too large for GPU memory lives in pinned host RAM and cycles through the card one tile at a time.mode = "auto"streams only when the domain does not fit. - Streamed transfers overlap compute by default (
overlap = "on");"off"keeps the single stream loop as the reference. No arithmetic changes either way. - Specified (externally forced) lateral boundaries run through the multi-GPU decomposition, and decompositions that cannot be right are refused by name.
- Every radiative field a land surface scheme reads carries a source and a last producer time, checked immediately before the scheme consumes it.
surface_radiation_policydefaults torequired. - Per carrier provenance in the run receipt and every wrfout frame.
docs/public/TILES.mddocuments the streamed run; it is separate from thegpuwm streamHRRR cycle following feature.
Fixed
- Classic RRTM longwave with Dudhia shortwave no longer stalls large nests on host dispatch: a 2 domain NSSL steady step fell from 39.0 to 4.2 seconds, byte identical output across chunk sizes.
- The reported 16x NSSL versus Morrison cost gap was a benchmark confound; matched configs show 1.0 to 1.4x.
- A streamed run survives its second output frame, and a mid interval checkpoint resumes bit equal to the uninterrupted run.
- The wheel now ships
tilestream;[tiles]modes no longer fail from a clean install. - Land surface schemes can no longer consume stale or fabricated radiation: zero shortwave passes on source and age, never on the value looking plausible, and a run with no live producer refuses before the land surface call.
- Also fixed: NumPy 2 host checkpointing, streamed ERA5 with SST preparation, streamed boundary rebind cost, multi device RRTMGP caching, nocturnal COSZEN staleness, and several smaller streamed path defects.
Verification
Every release gate green. Streamed against resident: 1127 image pairs, pixel identical. Twin verification against stock WRF v4.6.1 across the ported scheme table.
Known issues
- A
[tiles]streamed run launched through the prepared forecast routes fails before its first model step with either shipped full radiation option. The failure is immediate and loud, never a silent wrong result. Domains that fit the card run resident and are unaffected. A fix is in progress for the next release. - The HRRR native route does not expose the
[tiles]table.
Full detail in CHANGELOG.md.
ArWen 1.9.1
Fast follow for 1.9.0. Three defects caught by head-to-head verification against stock WRF v4.6.1, each closed with a class instrument so the pattern cannot ship again.
Fixed:
- Milbrandt-Yau (mp_physics = 9) runs real cases. Seven scheme-keyed tables lacked mp=9 arms; the coupling sets now read one shared inventory, and a new stage-1 suite proves every accepted mp_physics value builds its workspace, classifies, couples, and digests.
- WDM6 and Milbrandt-Yau own the SR roundoff envelope WSM6 already had, keyed on the audited shared-expression family with an analytic bound per member. Healthy runs no longer die one ULP above 1.0.
- RRTM longwave with Dudhia shortwave (1/1) finishes cleanly. p_top is coerced like the legacy adapter, and every registered radiation callable now classifies through the restart manifest.
Known:
- The time-zero history frame publishes the declared constant downward longwave, 300 W m-2, where WRF writes 0.0. The first radiation call overwrites it.
Verification: the fixed schemes were re-run on the reference case and judged against stock WRF v4.6.1; deltas sit inside same-scheme calibration bands.