Diagnostics · rebuilt with every publication

Diurnal structure of the error

Under the four common synoptic instants the models do not carry the same bias at every hour of the day. This page publishes that structure and nothing else: it is an observation about these measurements, not yet attributed to a cause. In the window this build covers, the models are furthest apart at 18Z — 3.49 °F between the two extremes — and closest together at 06Z, 1.98 °F apart.

Window
90 d
Variable
instantaneous 2 m temperature
Init
00Z
Interpolation
bilinear
Stations
23 pooled
Data through
2026-10-28
Updated

What this page does and does not claim

The three figures below describe a pattern in these measurements. They are not yet attributed to any cause, because the analyses that would separate the candidates have not been run. Three explanations are all consistent with what is drawn here, and this page excludes none of them:

  1. Model diurnal amplitude — the models may genuinely produce a flatter or sharper daily temperature cycle, in which case the hour-by-hour bias is a property of the forecast system.
  2. The extreme-sampling penalty — four samples a day cannot see the true daily maximum or minimum, and the size of that penalty depends on the shape of the curve being sampled — the third table below measures it directly (METHODOLOGY §2.3).
  3. The initial conditions — the same architecture run from GFS and from IFS analyses differs by a large fraction of the effect, which points at near-surface temperature in the analysis rather than at the forecast model.

The full statement, and the ordered list of analyses that would settle it, is methodology §10.2. Until those exist, the correct sentence is that the afternoon bias differs between models and we have not separated model diurnal amplitude, sampling penalty and initial conditions.

What each UTC instant is in local time. Offsets are standard time across the 23 stations, which span four zones; local clocks read one hour later while daylight saving is in force.
InstantLocal standard timeRoughly
00Z16:00–19:00evening
06Z22:00–01:00night
12Z04:00–07:00early morning
18Z10:00–13:00midday to afternoon

A. Bias at each synoptic instantt2_00z … t2_18z

Each model is scored at a single instant against the observation at the same instant, so nothing in this figure depends on a model's own daily temperature range or on a definition of a daily extreme. Bars run from a shared zero; positive is too warm. Lead day 1, 90d window, 00Z initialization, bilinear interpolation, 23 stations pooled.

Bias at each of the four synoptic instants, by model — 90-day window, 00Z initialization, bilinear interpolation, lead day 1, all stations pooled-4-20+2bias, °F (forecast − observed)ECMWF IFS HRES00ZECMWF IFS HRES 00Z: -1.50 °F, n = 87-1.506ZECMWF IFS HRES 06Z: -0.69 °F, n = 88-0.6912ZECMWF IFS HRES 12Z: -0.52 °F, n = 88-0.5218ZECMWF IFS HRES 18Z: +0.19 °F, n = 87+0.19ECMWF AIFS Single00ZECMWF AIFS Single 00Z: -0.85 °F, n = 87-0.8506ZECMWF AIFS Single 06Z: -1.58 °F, n = 88-1.5812ZECMWF AIFS Single 12Z: -1.53 °F, n = 88-1.5318ZECMWF AIFS Single 18Z: -0.04 °F, n = 87-0.04NCEP GFS00ZNCEP GFS 00Z: -0.34 °F, n = 87-0.3406ZNCEP GFS 06Z: +0.19 °F, n = 88+0.1912ZNCEP GFS 12Z: +0.68 °F, n = 88+0.6818ZNCEP GFS 18Z: +1.15 °F, n = 87+1.15GraphCast (IFS init)00ZGraphCast (IFS init) 00Z: -2.81 °F, n = 86-2.8106ZGraphCast (IFS init) 06Z: -1.69 °F, n = 87-1.6912ZGraphCast (IFS init) 12Z: -0.97 °F, n = 87-0.9718ZGraphCast (IFS init) 18Z: -1.05 °F, n = 86-1.05GraphCast (GFS init)00ZGraphCast (GFS init) 00Z: -3.26 °F, n = 56-3.2606ZGraphCast (GFS init) 06Z: -1.68 °F, n = 56-1.6812ZGraphCast (GFS init) 12Z: -0.87 °F, n = 56-0.8718ZGraphCast (GFS init) 18Z: -2.09 °F, n = 56-2.09Pangu-Weather (IFS init)00ZPangu-Weather (IFS init) 00Z: -2.86 °F, n = 84-2.8606ZPangu-Weather (IFS init) 06Z: -1.79 °F, n = 85-1.7912ZPangu-Weather (IFS init) 12Z: -0.83 °F, n = 85-0.8318ZPangu-Weather (IFS init) 18Z: +0.83 °F, n = 84+0.83Pangu-Weather (GFS init)00ZPangu-Weather (GFS init) 00Z: -2.68 °F, n = 56-2.6806ZPangu-Weather (GFS init) 06Z: -1.50 °F, n = 56-1.512ZPangu-Weather (GFS init) 12Z: -0.34 °F, n = 56-0.3418ZPangu-Weather (GFS init) 18Z: +0.60 °F, n = 56+0.6FourCastNet v2 (IFS init)00ZFourCastNet v2 (IFS init) 00Z: -0.97 °F, n = 87-0.9706ZFourCastNet v2 (IFS init) 06Z: -1.46 °F, n = 88-1.4612ZFourCastNet v2 (IFS init) 12Z: -1.45 °F, n = 88-1.4518ZFourCastNet v2 (IFS init) 18Z: -0.64 °F, n = 87-0.64FourCastNet v2 (GFS init)00ZFourCastNet v2 (GFS init) 00Z: -1.21 °F, n = 56-1.2106ZFourCastNet v2 (GFS init) 06Z: -1.61 °F, n = 56-1.6112ZFourCastNet v2 (GFS init) 12Z: -1.61 °F, n = 56-1.6118ZFourCastNet v2 (GFS init) 18Z: -0.97 °F, n = 56-0.97Aurora (IFS init)00ZAurora (IFS init) 00Z: -2.58 °F, n = 82-2.5806ZAurora (IFS init) 06Z: -1.50 °F, n = 83-1.512ZAurora (IFS init) 12Z: -0.87 °F, n = 83-0.8718ZAurora (IFS init) 18Z: -1.29 °F, n = 82-1.29Aurora (GFS init)00ZAurora (GFS init) 00Z: -3.28 °F, n = 56-3.2806ZAurora (GFS init) 06Z: -1.62 °F, n = 56-1.6212ZAurora (GFS init) 12Z: -0.85 °F, n = 56-0.8518ZAurora (GFS init) 18Z: -2.34 °F, n = 56-2.34Persistence (baseline)00ZPersistence (baseline) 00Z: +0.22 °F, n = 89+0.2206ZPersistence (baseline) 06Z: +0.21 °F, n = 90+0.2112ZPersistence (baseline) 12Z: +0.20 °F, n = 90+0.218ZPersistence (baseline) 18Z: +0.19 °F, n = 89+0.19

Source: CastCheck 0.3.3, methodology v0.3.1 · ECMWF open data, NOAA/NCEP GFS, NOAA/CIRA AIWP, NWS ASOS · data through 2026-10-28 · CC BY 4.0. Hover a bar for its value and sample size.

The same figure as a table
Bias in °F (forecast − observed) with the sample size under each value, and the spread between a model's own highest and lowest instant in the last column.
Model00Z06Z12Z18Z Spread
ECMWF IFS HRESifs_hres−1.50n=87−0.69n=88−0.52n=88+0.19n=87 1.69
ECMWF AIFS Singleaifs_single−0.85n=87−1.58n=88−1.53n=88−0.04n=87 1.54
NCEP GFSgfs−0.34n=87+0.19n=88+0.68n=88+1.15n=87 1.50
GraphCast (IFS init)graphcast_ifs−2.81n=86−1.69n=87−0.97n=87−1.05n=86 1.84
GraphCast (GFS init)graphcast_gfs−3.26n=56−1.68n=56−0.87n=56−2.09n=56 2.39
Pangu-Weather (IFS init)pangu_ifs−2.86n=84−1.79n=85−0.83n=85+0.83n=84 3.68
Pangu-Weather (GFS init)pangu_gfs−2.68n=56−1.50n=56−0.34n=56+0.60n=56 3.29
FourCastNet v2 (IFS init)fourcastnet_ifs−0.97n=87−1.46n=88−1.45n=88−0.64n=87 0.82
FourCastNet v2 (GFS init)fourcastnet_gfs−1.21n=56−1.61n=56−1.61n=56−0.97n=56 0.64
Aurora (IFS init)aurora_ifs−2.58n=82−1.50n=83−0.87n=83−1.29n=82 1.70
Aurora (GFS init)aurora_gfs−3.28n=56−1.62n=56−0.85n=56−2.34n=56 2.43
Persistence (baseline)persistence+0.22n=89+0.21n=90+0.20n=90+0.19n=89 0.03

B. Bias against lead dayt2, pooled over the four instants

The same instantaneous variable, pooled over all four instants, at every lead day the record covers. A bias that is flat across leads is present in the first forecast hours; one that grows with lead accumulates as the forecast runs. Each line is named where it ends; the two initial-condition variants of one architecture share a colour and are told apart by the dashed stroke. 90d window, 00Z, bilinear.

Bias of the instantaneous 2 m temperature against lead day, one line per model — 90-day window, 00Z initialization, bilinear interpolation-4-20+2d1d2d3d4d5d6d7d8d9lead day°FECMWF IFS HRES d1: -0.64 °FECMWF IFS HRES d2: -0.59 °FECMWF IFS HRES d3: -0.57 °FECMWF IFS HRES d4: -0.6 °FECMWF IFS HRES d5: -0.51 °FECMWF IFS HRES d6: -0.33 °FECMWF IFS HRES d7: -0.31 °FECMWF IFS HRES d8: -0.26 °FECMWF IFS HRES d9: -0.14 °FECMWF AIFS Single d1: -1 °FECMWF AIFS Single d2: -1 °FECMWF AIFS Single d3: -0.96 °FECMWF AIFS Single d4: -0.92 °FECMWF AIFS Single d5: -0.81 °FECMWF AIFS Single d6: -0.85 °FECMWF AIFS Single d7: -1.16 °FECMWF AIFS Single d8: -1.14 °FECMWF AIFS Single d9: -0.51 °FNCEP GFS d1: +0.41 °FNCEP GFS d2: +0.39 °FNCEP GFS d3: +0.49 °FNCEP GFS d4: +0.42 °FNCEP GFS d5: +0.33 °FNCEP GFS d6: +0.41 °FNCEP GFS d7: +0.35 °FNCEP GFS d8: +0.1 °FNCEP GFS d9: -0.6 °FGraphCast (IFS init) d1: -1.64 °FGraphCast (IFS init) d2: -1.71 °FGraphCast (IFS init) d3: -1.68 °FGraphCast (IFS init) d4: -1.67 °FGraphCast (IFS init) d5: -1.7 °FGraphCast (IFS init) d6: -1.63 °FGraphCast (IFS init) d7: -1.83 °FGraphCast (IFS init) d8: -1.95 °FGraphCast (IFS init) d9: -1.88 °FGraphCast (GFS init) d1: -1.97 °FGraphCast (GFS init) d2: -2.13 °FGraphCast (GFS init) d3: -2.24 °FGraphCast (GFS init) d4: -2.32 °FGraphCast (GFS init) d5: -2.18 °FGraphCast (GFS init) d6: -2.16 °FGraphCast (GFS init) d7: -2.16 °FGraphCast (GFS init) d8: -2.31 °FGraphCast (GFS init) d9: -2.45 °FPangu-Weather (IFS init) d1: -1.16 °FPangu-Weather (IFS init) d2: -1.34 °FPangu-Weather (IFS init) d3: -1.47 °FPangu-Weather (IFS init) d4: -1.56 °FPangu-Weather (IFS init) d5: -1.77 °FPangu-Weather (IFS init) d6: -1.86 °FPangu-Weather (IFS init) d7: -2.07 °FPangu-Weather (IFS init) d8: -2.15 °FPangu-Weather (IFS init) d9: -1.71 °FPangu-Weather (GFS init) d1: -0.98 °FPangu-Weather (GFS init) d2: -1.23 °FPangu-Weather (GFS init) d3: -1.4 °FPangu-Weather (GFS init) d4: -1.5 °FPangu-Weather (GFS init) d5: -1.59 °FPangu-Weather (GFS init) d6: -1.58 °FPangu-Weather (GFS init) d7: -1.67 °FPangu-Weather (GFS init) d8: -1.89 °FPangu-Weather (GFS init) d9: -1.66 °FFourCastNet v2 (IFS init) d1: -1.14 °FFourCastNet v2 (IFS init) d2: -1.14 °FFourCastNet v2 (IFS init) d3: -1.15 °FFourCastNet v2 (IFS init) d4: -1.13 °FFourCastNet v2 (IFS init) d5: -1.12 °FFourCastNet v2 (IFS init) d6: -1.18 °FFourCastNet v2 (IFS init) d7: -1.35 °FFourCastNet v2 (IFS init) d8: -1.45 °FFourCastNet v2 (IFS init) d9: -1.35 °FFourCastNet v2 (GFS init) d1: -1.34 °FFourCastNet v2 (GFS init) d2: -1.35 °FFourCastNet v2 (GFS init) d3: -1.32 °FFourCastNet v2 (GFS init) d4: -1.31 °FFourCastNet v2 (GFS init) d5: -1.37 °FFourCastNet v2 (GFS init) d6: -1.35 °FFourCastNet v2 (GFS init) d7: -1.37 °FFourCastNet v2 (GFS init) d8: -1.45 °FFourCastNet v2 (GFS init) d9: -1.37 °FAurora (IFS init) d1: -1.57 °FAurora (IFS init) d2: -1.72 °FAurora (IFS init) d3: -1.8 °FAurora (IFS init) d4: -1.84 °FAurora (IFS init) d5: -1.86 °FAurora (IFS init) d6: -1.66 °FAurora (IFS init) d7: -1.54 °FAurora (IFS init) d8: -1.5 °FAurora (IFS init) d9: -1.16 °FAurora (GFS init) d1: -2.02 °FAurora (GFS init) d2: -2.38 °FAurora (GFS init) d3: -2.67 °FAurora (GFS init) d4: -2.96 °FAurora (GFS init) d5: -3.17 °FAurora (GFS init) d6: -3.33 °FAurora (GFS init) d7: -3.47 °FAurora (GFS init) d8: -3.71 °FAurora (GFS init) d9: -3.82 °FPersistence (baseline) d1: +0.2 °FPersistence (baseline) d2: +0.39 °FPersistence (baseline) d3: +0.6 °FPersistence (baseline) d4: +0.84 °FPersistence (baseline) d5: +1.03 °FPersistence (baseline) d6: +1.21 °FPersistence (baseline) d7: +1.4 °FPersistence (baseline) d8: +1.56 °FPersistence (baseline) d9: +1.79 °FPersistence (baseline)ECMWF IFS HRESECMWF AIFS SingleNCEP GFSAurora (IFS init)FourCastNet v2 (IFS init)FourCastNet v2 (GFS init)Pangu-Weather (GFS init)Pangu-Weather (IFS init)GraphCast (IFS init)GraphCast (GFS init)Aurora (GFS init)

Source: CastCheck 0.3.3, methodology v0.3.1 · data through 2026-10-28 · CC BY 4.0. Hover a point for its value.

Solid: the first initial-condition variant of a family Dashed: the second variant of the same architecture Grey dotted: the persistence baseline Every line is also labelled at its right-hand end

The same figure as a table
Bias in °F at each lead day, with the sample size under each value.
Modeld1d2d3d4d5d6d7d8d9
ECMWF IFS HRESifs_hres−0.64n=87−0.59n=86−0.57n=85−0.60n=84−0.51n=83−0.33n=82−0.31n=81−0.26n=80−0.14n=79
ECMWF AIFS Singleaifs_single−1.00n=87−1.00n=86−0.96n=85−0.92n=84−0.81n=83−0.85n=82−1.16n=81−1.14n=80−0.51n=79
NCEP GFSgfs+0.41n=87+0.39n=86+0.49n=85+0.42n=84+0.33n=83+0.41n=82+0.35n=81+0.10n=80−0.60n=79
GraphCast (IFS init)graphcast_ifs−1.64n=86−1.71n=86−1.68n=86−1.67n=86−1.70n=86−1.63n=86−1.83n=86−1.95n=86−1.88n=86
GraphCast (GFS init)graphcast_gfs−1.97n=56−2.13n=55−2.24n=54−2.32n=55−2.18n=56−2.16n=55−2.16n=55−2.31n=55−2.45n=55
Pangu-Weather (IFS init)pangu_ifs−1.16n=84−1.34n=84−1.47n=84−1.56n=84−1.77n=84−1.86n=84−2.07n=84−2.15n=84−1.71n=84
Pangu-Weather (GFS init)pangu_gfs−0.98n=56−1.23n=55−1.40n=54−1.50n=55−1.59n=56−1.58n=55−1.67n=55−1.89n=55−1.66n=55
FourCastNet v2 (IFS init)fourcastnet_ifs−1.14n=87−1.14n=87−1.15n=87−1.13n=87−1.12n=87−1.18n=87−1.35n=87−1.45n=87−1.35n=87
FourCastNet v2 (GFS init)fourcastnet_gfs−1.34n=56−1.35n=55−1.32n=54−1.31n=55−1.37n=56−1.35n=55−1.37n=55−1.45n=55−1.37n=55
Aurora (IFS init)aurora_ifs−1.57n=82−1.72n=82−1.80n=82−1.84n=81−1.86n=81−1.66n=81−1.54n=81−1.50n=81−1.16n=81
Aurora (GFS init)aurora_gfs−2.02n=56−2.38n=55−2.67n=54−2.96n=55−3.17n=56−3.33n=55−3.47n=55−3.71n=55−3.82n=55
Persistence (baseline)persistence+0.20n=89+0.39n=89+0.60n=89+0.84n=89+1.03n=89+1.21n=89+1.40n=89+1.56n=89+1.79n=89

C. The sampling penalty, model by model

The like-for-like extreme tmax_s scores a model's four forecast samples against the highest of the four observations at the same instants; tmax_cli scores exactly the same four forecast samples against the true NWS daily maximum. The difference is the sampling penalty, in °F, at lead day 1.

How to read the last column. Both terms are formed from the same forecast value, so the forecast cancels and the difference is the gap between the two truth definitions over the days and stations that model was scored on. Read the level of each column for a model's own diurnal behaviour and the sample sizes for why the differences are not identical.

Bias in °F (forecast − observed) at lead day 1, 90d window, 00Z, bilinear, 23 stations pooled. Rows are ordered by the daily-maximum penalty, most negative first. The persistence baseline is shown last and is never ranked.
Modeltmax_s vs tmax_clitmin_s vs tmin_cli
tmax_stmax_cliPenaltyn tmin_stmin_cliPenaltyn
NCEP GFSgfs+0.57−2.17−2.7387cli n=87+0.78+2.38+1.6087cli n=87
ECMWF AIFS Singleaifs_single−0.42−3.15−2.7387cli n=87−1.34+0.26+1.6187cli n=87
ECMWF IFS HRESifs_hres−0.67−3.39−2.7287cli n=87−0.38+1.23+1.6187cli n=87
FourCastNet v2 (IFS init)fourcastnet_ifs−1.41−4.14−2.7287cli n=87−1.08+0.54+1.6287cli n=87
FourCastNet v2 (GFS init)fourcastnet_gfs−1.65−4.37−2.7256cli n=56−1.21+0.37+1.5956cli n=56
Pangu-Weather (IFS init)pangu_ifs−0.39−3.10−2.7184cli n=84−0.83+0.80+1.6384cli n=84
Pangu-Weather (GFS init)pangu_gfs−0.54−3.25−2.7156cli n=56−0.42+1.17+1.5956cli n=56
Aurora (GFS init)aurora_gfs−3.19−5.90−2.7156cli n=56−0.59+0.99+1.5856cli n=56
GraphCast (GFS init)graphcast_gfs−2.93−5.63−2.7156cli n=56−0.63+0.96+1.5856cli n=56
GraphCast (IFS init)graphcast_ifs−1.93−4.64−2.7086cli n=86−0.82+0.79+1.6186cli n=86
Aurora (IFS init)aurora_ifs−2.14−4.85−2.7082cli n=82−0.69+0.92+1.6282cli n=82
Persistence (baseline)persistence+0.20+0.19−0.0189cli n=89+0.20+0.20+0.0189cli n=89

This comparison scores four 6-hourly forecast samples against the true daily extreme, so it includes a sampling penalty. The size of that penalty depends on each model's own diurnal amplitude, which is one of the things this site measures, so these numbers are published for operational relevance and are never used for ranking.

These numbers move

Every figure and table on this page is rebuilt from scratch on each publication, over a rolling 90d window, so the sample behind it grows every day and the ordering of models can change. Nothing here is a fixed result: the record is short, the confidence intervals published on the leaderboard are wide, and a difference visible today may not survive another month of data. The JSON carries the same numbers with their sample sizes, and each row links to the model page where the intervals live. Next rebuild: .