FORECASTEAGLE.COM · NOAA / NWS DATA · NORTH AMERICA HOMERRFSHRRRRTMAGFSNDFDNBMALERTSMODELSNOTESCOLOURSBUILDERSTATUSABOUT

WHY THE GFS HERE IS 13 KM, NOT 25

The obvious file is the wrong one, and the right one is missing two fields.

The obvious source for GFS charts is gfs.tHHz.pgrb2.0p25.fNNN. It carries every field this site draws, ready-made, on a tidy 0.25-degree lat/lon grid — 1440 by 721 points, about 25 km. This site reads gfs.tHHz.sfluxgrbfNNN.grib2 instead, and the reason is resolution.

gridspacing
pgrb2.0p251440 × 721 regular lat/lon0.25° (~25 km)
sfluxgrb3072 × 1536 Gaussian0.117° (~13 km)

The flux files sit on the model's own grid. The 0.25-degree product is an interpolation of the same forecast onto a grid twice as coarse in each direction. Four times the detail is worth some work, and the gain is measurable rather than notional: differencing our 3-hour precipitation against the product file's own accumulation, the global peak is 159 mm against 123 mm, and area-averaging ours down to 0.25 degrees first brings it to 112 mm, either side of the product's number. A 13 km convective core really is more intense than the 25 km field that smooths it.

What the flux files do not carry

The price of the finer grid is that the flux files have no dewpoint and no accumulated precipitation: 113 messages, and neither is among them. So two of the quantities on the GFS page are derived — and each was checked against NCEP's own answer rather than trusted.

Dewpoint comes from specific humidity at 2 metres and pressure at the surface, through the exact mixing-ratio form of the vapour pressure and the Magnus inverse. Differenced against the GFS's own published dewpoint over all 1,035,360 points of the 0.25-degree grid, by 2-metre air temperature:

2-m air temperatureshare of pointsmean errormax
above freezing76.3%+0.013 °F0.20 °F
0 to −15 °C11.1%−0.023 °F0.22 °F
−15 to −30 °C4.5%−0.020 °F12.4 °F
−30 to −50 °C5.1%+1.04 °F11.9 °F
below −50 °C2.8%+15.6 °F20.4 °F

Over 92% of the planet that is agreement to within a fifth of a degree — a sixth of what one step of the palette can even express. Below about −30 °C it is not: NCEP's dewpoint there is drier than the 2-metre specific humidity implies, and saturating over ice instead of water makes the disagreement worse, so whatever that diagnostic does is not the standard phase switch and is not reproduced here.

The residual was left alone because of where it lands. Count only the points that differ by more than one palette step and are not both below the ramp's −70 °F floor, where the colour clamps anyway: 1.81% of the globe, every pixel of it between 70 °S and 90 °S. The disagreement is the Antarctic ice sheet and nothing else. Matching NCEP exactly would mean pulling dewpoint from the product file — a second file per step and four times the grid spacing everywhere — to fix a continent with no observers on it.

Precipitation is integrated from the model's mean precipitation rate, and the catch is the window. The GFS restarts its time-averaged fields every six hours, so each rate message names a window that is neither "the last hour" nor "the whole run": f001 covers hours 0–1, f006 covers 0–6, f007 covers 6–7 and f123 covers 120–123. At the multiples of six the naive rule is a whole bucket out. Two products come off it — a per-step field, one hour to F120 and three hours after, and a run total — and both match the GFS's own accumulations: the run total within 0.13% at F006 and 0.03% at F007, the per-step within 1.51%, each with a median difference of exactly zero. The two also agree with each other to 0.007 mm: summing the per-step frames F001 to F007 reproduces the run total at F007, which is the check that matters, since nothing forces those two paths through the same code.

A grid whose rows are not evenly spaced

A Gaussian grid's latitudes are the roots of a Legendre polynomial, not a constant step, so the row-from-latitude arithmetic every other grid on this site uses does not hold. The latitudes are computed exactly and inverted by interpolation, checked against wgrib2's own coordinates at eight rows from first to last: every one agrees to a millionth of a degree. Measured rather than assumed, it barely matters — against a constant-step division the row index differs by 0.005 cells at 30 °N and 0.014 at 89 °N, about 200 metres at worst, and you could not have told from the map. The exact version is kept because it is exact, costs one interpolation per cycle, and at 48 latitude bands the same error would be a full cell.

The raster, and why it is not square

3072 columns is the Gaussian grid's own column count, so 360 degrees of longitude is sampled one-for-one. The height is derived, not chosen: Web Mercator stretches latitude, so a raster with as many rows as the source would undersample the equator by a factor of two — precisely where a global model has the most to show. Square pixels are the condition that fixes it, and at 3072 wide over ±85 degrees that comes to 3072 by 3062.

±85 because that is as far as Web Mercator goes at all — the projection is infinite at 85.0511 degrees — so the poles cannot appear on this raster at any size. The globe view drapes the same raster and stops at the same latitude.

Wind that crosses the dateline

A global field has a seam at 180 degrees, and the wind overlay has to know it. The particle sampler wraps so that the last column blends into the first, and the map's coordinate handling wraps longitude too, because a panned world map hands back longitudes like 190 or −240. On a regional field those are genuinely off the grid and must be refused; on a global one they are the same place as −170 and 120. With only one half of that, particles advecting into the seam sample nothing, die and respawn elsewhere — the flow stops dead at 180 and resumes on the far side, which over the Pacific is most of the picture. Which case applies is stated in the catalog outright rather than inferred from bounds that happen to span 360 degrees.

What it costs

Seven of the 113 messages per file, byte-ranged from the index — about 25 MB of each 285 MB file, and around 4 GB for a whole 161-step run against the 46 GB the files would cost whole. Five to seven seconds a step, about fifteen minutes a cycle, read from the AWS Open Data bucket rather than NOMADS, because NOMADS is a shared national resource with real contention and S3 is not. A rendered cycle is about 1.1 GB and five are kept.

One known limitation, stated rather than hidden: city value labels are US-only, because the city list is weather.city's US index, so a global map gets numbers over North America and none over Europe or Asia. The fix is a world city list, not a change to anything above.