A Rust reimplementation of wrf-python's getvar diagnostics
wrf-rust reads WRF-ARW output files with a pure-Rust NetCDF-4/HDF5
reader and computes the meteorological diagnostics that NCAR's
wrf-python provides through
getvar() — pressure, height, thermodynamics, CAPE/CIN families,
storm-relative helicity, severe-weather composites, reflectivity, and more —
plus diagnostics wrf-python does not have, such as effective-inflow-layer
products and entraining CAPE. It ships as a Python package
(pip install wrf-rust, imported as wrf) backed by the
wrf-core Rust crate.
| Property | Value | Detail |
|---|---|---|
| Registered diagnostics | 125 | Complete reference table, generated from the source registry at v0.3.0 |
| Reference parity | 0 failures | Differential harness against pinned wrf-python 1.3.4.1 and SHARPpy 1.4.0a5 |
| Pipeline speedup (0.3.0) | ≈3.3× | 79-product severe set on a real 800×800×79 case: 185.3 s → ≈57 s class at 24 threads |
| Interfaces | Python + Rust | PyPI package wrf-rust; Rust crates under crates/ |
1 Installation
The Python package installs a module named wrf. No system NetCDF or
HDF5 installation is required for normal wheel builds; the default reader path is
pure Rust.
pip install wrf-rust
For local development against the repository:
git clone https://github.com/FahrenheitResearch/wrf-rust.git
cd wrf-rust
pip install maturin
maturin develop --release
2 Quickstart: Python
The API mirrors wrf-python's getvar conventions: open a file,
request a variable by name, optionally convert units or select all time steps.
Results are NumPy arrays, (ny, nx) for 2-D fields and
(nz, ny, nx) for 3-D fields.
from wrf import WrfFile, getvar, ALL_TIMES
f = WrfFile("wrfout_d01_2024-01-01_00:00:00")
temp = getvar(f, "temp", timeidx=0, units="degC") # (nz, ny, nx)
cape = getvar(f, "sbcape", timeidx=0) # (ny, nx), J/kg
srh = getvar(f, "srh1", timeidx=0) # 0-1 km SRH, Bunkers
slp = getvar(f, "slp", timeidx=ALL_TIMES, units="hPa")
# Strict NCAR wrf-python/RIP compatibility paths are separately named:
srh_ncar = getvar(f, "srh_wrfpython", timeidx=0, depth_m=3000)
ecape = getvar(f, "ecape", timeidx=0, storm_motion_type="bunkers_rm")
Layer-configurable diagnostics accept explicit bounds, and raw WRF variables fall through by name:
shear = getvar(f, "bulk_shear", bottom_m=0, top_m=6000)
lr = getvar(f, "lapse_rate", bottom_p=700, top_p=500)
srh = getvar(f, "srh", depth_m=1500, storm_motion=(12.0, 8.0))
rain = getvar(f, "RAINNC", units="in") # raw variable fallback
list_variables() returns every registered name with description and
default units; available_variables() prints the same as a table.
interplevel, latlon_coords, get_cartopy,
ll_to_xy/xy_to_ll, and multi-file concatenation cover
the corresponding wrf-python workflows. The ordinary scalar/three-argument
ll_to_xy and interplevel calls preserve wrf-rust's
0.2.35 NumPy-oriented WRF-Runner contracts; their extended
wrf-python-compatible behavior is an explicit opt-in.
3 Quickstart: Rust
The same registry is callable from Rust through the wrf-core crate.
getvar returns a VarOutput holding a flat
Vec<f64>, its shape, the unit string, and a description.
use wrf_core::{getvar, ComputeOpts, WrfFile};
let file = WrfFile::open("wrfout_d01_2024-01-01_00:00:00")?;
let opts = ComputeOpts::default();
let slp = getvar(&file, "slp", Some(0), &opts)?;
assert_eq!(slp.shape, vec![file.ny, file.nx]);
assert_eq!(slp.units, "hPa");
4 Compatibility and scope
wrf-rust separates two kinds of fidelity rather than conflating them:
- Strict compatibility paths. Variables named
cape2d_wrfpython,cape3d_wrfpython,srh_wrfpython, and their components reproduce NCAR wrf-python 1.3.4.1/RIP behavior exactly: parcel selection, 500 m pressure averaging, the pinned pseudoadiabat table, positive-CIN magnitude, missing-value rules, and output ordering. Parcel overrides and extensions are rejected on these paths. - Native diagnostics. The default
sbcape/mlcape/mucapefamilies are parcel-explicit; SRH defaults to modern Bunkers storm motion; severe composites follow current SPC definitions. Where wrf-rust deliberately departs from wrf-python, the departure is documented and tested against the appropriate scientific authority — see Validation.
Unit strings are case-insensitive and cover temperature, pressure, speed,
length, precipitation depth, and moisture categories (for example
degC, hPa, kt, ft,
in, g/kg).
5 Consumers
BowEcho, a desktop
weather radar and satellite application, is the flagship consumer: it uses
wrf-rust for WRF import, severe-weather diagnostic suites, isobaric volumes, and
a synthetic-radar forward operator over WRF output. The repository also contains
Rust-native rendering (wrf-products, wrf-render),
sounding extraction (wrf-sounding), and ensemble reductions
(wrf-ensemble) built on the same core.
6 Further reading
- Repository and PyPI package
- Architecture — crate boundaries and ownership
- Ensembles — same-grid member reductions
- Migration from rustwx — porting history
- Differential parity framework — the acceptance methodology summarized on the Validation page