Expand description
Weather from NOAA’s GFS and RAP forecasts: a small GRIB2 cut from NOMADS’ grib filter around a
launch site, turned into a SoundingProfile.
NOAA’s National Centers for Environmental Prediction (NCEP) run two models whose output NOMADS serves through a grib filter, a web form that cuts chosen variables, levels and a latitude/longitude box out of a forecast file:
| model | grid | runs | forecast hours | pressure levels asked for |
|---|---|---|---|---|
NomadsModel::Gfs, the Global Forecast System | 0.25° latitude/longitude | every 6 h | every hour to 120, every third to 384 | GFS_LEVELS_HPA, 1000 to 10 hPa |
NomadsModel::Rap, the Rapid Refresh | 13 km Lambert conformal, the contiguous U.S. and nearby Canada and Mexico | every hour | to 21; to 51 from the 03, 09, 15 and 21 UTC runs | RAP_LEVELS_HPA, 1000 to 100 hPa every 25 |
A NomadsRequest names the model, the run (its start, the cycle), the forecast hour and the
site; NomadsRequest::url refuses a run or an hour the model doesn’t have. Its URL asks for
a box 0.3° each way around the site, which holds the four grid points around it: 9 GFS points
or about 25 RAP points, 147 or 192 fields (the ground’s skin temperature, TMP at the surface,
comes too and is not used), about 28 or 40 KB. It asks for:
| variable | GRIB2 parameter (discipline 0) | where |
|---|---|---|
HGT, geopotential height, gpm | category 3, number 5 | the ground (the model’s terrain) and each level |
PRES, pressure, Pa | 3, 0 | the ground |
TMP, temperature, K | 0, 0 | 2 m above the ground and each level |
RH, relative humidity, % | 1, 1 | 2 m above the ground and each level |
UGRD, VGRD, wind components, m/s | 2, 2 and 2, 3 | 10 m above the ground and each level |
GRIB2’s code table 4.2 fixes each parameter’s unit, so there are no units to check.
NomadsProfile::parse decodes the cut with hpr_io::grib2 and interpolates every field
bilinearly, in the grid’s own indices, between the four grid points around the site. It keeps:
- The ground, at the model’s terrain height there, with the surface pressure, the 2 m
temperature and humidity, and the 10 m wind, as
crate::open_meteodoes (so the wind on the rail is the 10 m wind, Loft lesson L6). - Each pressure level above the ground: a level whose pressure is not below the surface
pressure, or whose height is not above the ground, is dropped, since the models extrapolate
beneath the terrain. So is one without every variable at every surrounding point.
NomadsProfile::droppedlists each with its reason.
The ground test is made at the site only: a kept level can take weight from a grid point where
it is underground, and so from the model’s extrapolation there. In the recorded RAP cut, 850 hPa
takes 13% of its weight from a point whose ground is at 845.8 hPa, about 0.02 K; in steep
terrain it can be more. A cut of more than MAX_FIELDS fields is refused, and fetch
refuses one whose grid steps and projection are not the model’s (NomadsModel::has_grid).
Winds along the grid. RAP gives its winds along the Lambert grid’s axes, not east and north
(GRIB2 flag table 3.3, bit 5). They are turned to east and north by the angle between the
grid’s y axis and true north at the site, θ = n (λ − λ₀)
(hpr_io::grib2::Grid::earth_relative_wind); at Spaceport America, 12° west of RAP’s central
meridian, θ is −5.06°. The components are interpolated first and turned once, at the site:
across one 13 km cell θ changes by about 0.06°.
Heights are geopotential meters, which is what GRIB2 defines HGT in, converted to
geometric heights at the site’s latitude with WMO-No. 8 eq. 12.16
(hpr_atmos::profile::geometric_from_wmo_geopotential_m), as for Open-Meteo. The terrain
height is also given in gpm and converted the same way: at 1,400 m and 33° N the two differ by
1.9 m, so if a model’s terrain is really a geometric height the ground here sits that far high
(ADR-081’s caveat, from the ERA5
reader). Relative humidity is
taken as over liquid water, which SoundingLevel means. Whether NCEP’s models report it
over ice at cold levels is not settled here; if they do, the density there shifts by under
0.1% (the bound on crate::open_meteo). A humidity above 100% is kept as recorded and
clamped to 100% in NomadsProfile::sounding, as ADR-004 (the atmosphere’s
design) asks of imported humidity.
fetch asks a Client for the URL, so the answer comes from the cache when it can, and
offline from the cache only; only an answer that decodes into a profile for the run and hour
asked is cached. A run’s files don’t change once written, so a copy stays fresh 30 days (NOMADS
keeps only recent runs: on 2026-09-30 its filters listed 10 days of GFS and 2 of RAP). The data is a U.S. government work, free of
copyright; ATTRIBUTION credits it.
How far to trust it: the decoder gives every value and grid point ecCodes does (the tests), and the profile gives back the interpolated values at every level it keeps. How good a forecast is depends on the model, and nothing here measures that. The guide page says more.
use hpr_atmos::WindInterpolation;
use hpr_net::nomads::NomadsProfile;
// A cut recorded from GFS's run of 2026-09-30 00 UTC, hour 18, around Spaceport America.
let body = include_bytes!("../tests/fixtures/replay/nomads-gfs.grib2");
let profile = NomadsProfile::parse(body, 32.99, -106.97)?;
assert_eq!(profile.dropped.len(), 6); // 1000 to 850 hPa lie below the 1,400 m ground.
let air = profile.sounding(WindInterpolation::SpeedDirection)?;
let at_5_km = air.sample(5_000.0)?.air;
assert!((at_5_km.pressure_pa - 55_000.0).abs() < 1_000.0);Structs§
- Dropped
Level - A pressure level left out of the profile, and why.
- Grid
Point - A grid point the profile is interpolated from.
- Nomads
Level - One pressure level above the ground, at the site.
- Nomads
Profile - A NOMADS cut read at a site: the ground and the pressure levels above it.
- Nomads
Request - What to ask NOMADS for: a model’s run, a forecast hour and a site.
- Nomads
Surface - The ground under the forecast, at the site.
Enums§
- Drop
Reason - Why a pressure level was left out of the profile.
- Nomads
Error - Why a NOMADS request or cut was refused.
- Nomads
Model - Which NCEP model to ask for.
Constants§
- ATTRIBUTION
- The credit shown with the data. NCEP’s forecasts are U.S. government works, not under copyright; the credit says where they came from.
- ENDPOINT
- NOMADS’ grib filters, whose scripts a request’s URL names.
- GFS_
LEVELS_ HPA - GFS’s pressure levels asked for, hPa: every level it has from 1000 to 10 hPa (about 31 km).
- MAX_
FIELDS - The most fields a cut may hold: a real one has 147 (GFS) or 192 (RAP). It bounds the work a hostile answer can ask for.
- RAP_
LEVELS_ HPA - RAP’s pressure levels asked for, hPa: all of them, 1000 to 100 hPa every 25 (about 16 km).
Functions§
- fetch
- Fetches
requestthroughclientand reads it at the request’s site.