AI weather models have spent three years closing the gap with physics-based forecasting, but two problems stayed open: resolution too coarse for local terrain, and initialization tied to numerical weather prediction (NWP) analysis that arrives about six hours late. WeatherNext 3, released by Google DeepMind and Google Research, attacks both. It takes a live global geostationary satellite mosaic as a direct model input, re-initializes every hour, and emits forecasts down to 0.05° (~5 km) while training against raw weather station measurements rather than reanalysis grids alone. According to Google AI, independent live evaluations from Brightband rank it as the most accurate global weather model to date.
Is it deployable? Partially. Forecast data is available now through BigQuery, Earth Engine and Cloud Storage after an allowlist request, but WeatherNext 3 weights are not open source and on-demand custom inference still runs WeatherNext 2.
Architecture and inputs
WeatherNext 3 is a Functional Generative Network (FGN) mesh transformer, the same probabilistic family introduced with WeatherNext 2, scaled to multi-resolution output. Inputs are a live geostationary satellite mosaic plus ECMWF HRES analysis. Training draws on ERA5/HRES-fc0, NASA’s IMERG, station observations and satellite mosaics.
Most AI forecasters learn from NWP reanalysis, which smooths away the local variation that coastlines, valleys and mountains actually produce. WeatherNext 3 trains dedicated observational heads directly on raw station measurements, so its 0.05° temperature and dew point outputs are calibrated to what instruments record rather than to a model’s representation of the atmosphere.
<div class="wn-body" id="p1" role="tabpanel" aria-labelledby="t1" hidden>
<div class="wn-stage"><canvas id="c1" width="640" height="330"></canvas></div>
<div class="wn-side">
<h3>From 25 km blocks to 5 km detail</h3>
<p>WeatherNext 2 produced 0.25° (~25 km) fields in six-hour steps. WeatherNext 3 emits 0.05° station-trained temperature and dew point, 0.1° gridded surface variables and 0.25° pressure levels from a single forward pass. Drag the slider across the same temperature field.</p>
<div class="wn-ctrl">
<label for="r1">Grid spacing: <span id="s1a">25 km</span></label>
<input type="range" id="r1" min="5" max="25" step="1" value="25">
<div class="wn-readout">
<div class="wn-stat"><b id="s1b">0.25°</b><span>Degrees</span></div>
<div class="wn-stat"><b id="s1c">1.0M</b><span>Global cells</span></div>
<div class="wn-stat"><b id="s1d">0.25°</b><span>WeatherNext 3 tier</span></div>
</div>
</div>
</div>
</div>
<div class="wn-body" id="p2" role="tabpanel" aria-labelledby="t2" hidden>
<div class="wn-stage"><canvas id="c2" width="640" height="330"></canvas></div>
<div class="wn-side">
<h3>Sixty-four futures, one forecast</h3>
<p>WeatherNext 3 runs a 64-member probabilistic ensemble. Synoptic cycles at 00, 06, 12 and 18 UTC reach 15 days; the interim hourly runs cover 48 hours. Add members and watch the uncertainty band fill in.</p>
<div class="wn-ctrl">
<label for="r2">Ensemble members drawn: <span id="s2a">64</span></label>
<input type="range" id="r2" min="1" max="64" step="1" value="64">
<button class="wn-btn" id="b2a">Redraw forecast</button>
<div class="wn-readout">
<div class="wn-stat"><b id="s2b">15 d</b><span>Horizon</span></div>
<div class="wn-stat"><b id="s2c">±0.0°</b><span>Day-15 spread</span></div>
</div>
</div>
</div>
</div>
<div class="wn-body" id="p3" role="tabpanel" aria-labelledby="t3" hidden>
<div class="wn-stage"><canvas id="c3" width="640" height="330"></canvas></div>
<div class="wn-side">
<h3>Rain bands with edges</h3>
<p>Coarse models smear rain into a diffuse blob. Trained against ECMWF reanalysis, NASA’s IMERG and Google’s satellite-radar precipitation reanalysis, WeatherNext 3 keeps convective bands sharp. Drag the divider left and right.</p>
<div class="wn-ctrl">
<label for="r3">Wipe: coarse 25 km on the left, WeatherNext 3 on the right</label>
<input type="range" id="r3" min="0" max="100" step="1" value="50">
<button class="wn-btn" id="b3a" aria-pressed="true">Animate storm</button>
<div class="wn-readout">
<div class="wn-stat"><b>up to 60%</b><span>CRPS gain vs IMERG, early lead times</span></div>
<div class="wn-stat"><b>up to 50%</b><span>Better rain forecasts in Google products, a day-plus ahead</span></div>
</div>
</div>
</div>
</div>
<p class="wn-note">Panels are illustrative renderings of published model behaviour, not live WeatherNext 3 output. For live fields, see Weather Lab. WeatherNext forecasts are experimental and are not official warnings.</p>
<div class="wn-foot">
<span>Sources: Google DeepMind blog, WeatherNext developer docs, WeatherNext 3 paper.</span>
<span class="wn-brand">Built by Marktechpost</span>
</div>
</div>
<script>
(function(){
"use strict";
var reduce = window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
/* ———- shared helpers ———- */
function hash(x, y){
var n = Math.sin(x * 127.1 + y * 311.7) * 43758.5453;
return n – Math.floor(n);
}
function smooth(t){ return t * t * (3 – 2 * t); }
function noise(x, y){
var xi = Math.floor(x), yi = Math.floor(y);
var xf = x – xi, yf = y – yi;
var u = smooth(xf), v = smooth(yf);
var a = hash(xi, yi), b = hash(xi + 1, yi), c = hash(xi, yi + 1), d = hash(xi + 1, yi + 1);
return (a * (1 – u) + b * u) * (1 – v) + (c * (1 – u) + d * u) * v;
}
function fbm(x, y, oct){
var s = 0, amp = 0.5, f = 1;
for (var i = 0; i < oct; i++){ s += amp * noise(x * f, y * f); f *= 2.07; amp *= 0.5; }
return s;
}
function fit(cv){
var ratio = window.devicePixelRatio || 1;
var w = cv.clientWidth || 640;
var h = Math.round(w * (cv.height / cv.width));
if (cv.dataset.cssw === String(w)) return;
cv.dataset.cssw = String(w);
cv.width = Math.round(w * ratio);
cv.height = Math.round(h * ratio);
cv.style.height = h + "px";
var ctx = cv.getContext("2d");
ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
cv.dataset.w = String(w);
cv.dataset.h = String(h);
}
function dims(cv){ return { w: parseFloat(cv.dataset.w) || 640, h: parseFloat(cv.dataset.h) || 330 }; }
/* ———- tabs ———- */
var tabs = [].slice.call(document.querySelectorAll(".wn-tab"));
var panels = [document.getElementById("p0"), document.getElementById("p1"), document.getElementById("p2"), document.getElementById("p3")];
var active = 0;
function select(i){
active = i;
tabs.forEach(function(t, k){ t.setAttribute("aria-selected", k === i ? "true" : "false"); });
panels.forEach(function(p, k){ if (k === i){ p.removeAttribute("hidden"); } else { p.setAttribute("hidden", ""); } });
redrawAll();
sendHeight();
}
tabs.forEach(function(t, i){ t.addEventListener("click", function(){ select(i); }); });
/* ———- panel 0: hourly intake ———- */
var c0 = document.getElementById("c0"), x0 = c0.getContext("2d");
var hour = 0, playing = !reduce, t0acc = 0;
var s0a = document.getElementById("s0a"), s0b = document.getElementById("s0b"), s0c = document.getElementById("s0c");
var b0a = document.getElementById("b0a"), b0b = document.getElementById("b0b");
b0a.setAttribute("aria-pressed", playing ? "true" : "false");
b0a.textContent = playing ? "Pause" : "Play";
b0a.addEventListener("click", function(){
playing = !playing;
b0a.setAttribute("aria-pressed", playing ? "true" : "false");
b0a.textContent = playing ? "Pause" : "Play";
});
b0b.addEventListener("click", function(){ hour = (hour + 1) % 24; drawP0(); });
function pad(n){ return (n < 10 ? "0" : "") + n; }
function drawP0(){
fit(c0);
var d = dims(c0), w = d.w, h = d.h;
x0.clearRect(0, 0, w, h);
x0.fillStyle = "#04101F"; x0.fillRect(0, 0, w, h);
var mono = "600 11px -apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif";
/* —- lower zone: earth limb —- */
var cx = w * 0.5, cy = h * 2.05, R = h * 1.45;
x0.save();
x0.beginPath(); x0.arc(cx, cy, R, Math.PI * 1.15, Math.PI * 1.85); x0.lineTo(w, h); x0.lineTo(0, h); x0.closePath();
var g = x0.createLinearGradient(0, h * 0.55, 0, h);
g.addColorStop(0, "#15467F"); g.addColorStop(1, "#06182D");
x0.fillStyle = g; x0.fill();
x0.strokeStyle = "rgba(66,133,244,.9)"; x0.lineWidth = 1.2;
x0.beginPath(); x0.arc(cx, cy, R, Math.PI * 1.15, Math.PI * 1.85); x0.stroke();
x0.restore();
/* —- satellite sweeping the limb —- */
var sx = w * 0.14 + (hour / 23) * w * 0.72;
var sy = h * 0.63;
var dx = sx – cx;
var gy = cy – Math.sqrt(Math.max(1, R * R – dx * dx));
x0.save();
var beam = x0.createLinearGradient(sx, sy, sx, gy);
beam.addColorStop(0, "rgba(251,188,4,.55)"); beam.addColorStop(1, "rgba(251,188,4,.05)");
x0.beginPath(); x0.moveTo(sx, sy); x0.lineTo(sx – 42, gy + 26); x0.lineTo(sx + 42, gy + 26); x0.closePath();
x0.fillStyle = beam; x0.fill();
x0.restore();
x0.fillStyle = "#FBBC04";
x0.beginPath(); x0.arc(sx, sy, 5.5, 0, Math.PI * 2); x0.fill();
x0.fillStyle = "rgba(4,16,31,.55)"; x0.fillRect(0, h – 24, w, 24);
x0.fillStyle = "rgba(232,239,250,.92)"; x0.textAlign = "center";
x0.font = w < 430 ? "600 10px -apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif" : mono;
x0.fillText(w < 430 ? "live geostationary satellite mosaic" : "live geostationary satellite mosaic, ingested as a direct model input", w / 2, h – 8);
x0.textAlign = "left";
/* —- upper zone: two cadences —- */
var padL = 26, padR = 22, tw = w – padL – padR;
var rows = [
{ y: h * 0.17, label: "WeatherNext 3 – initialised every hour", col: "#4285F4", every: 1 },
{ y: h * 0.37, label: "6-hourly NWP-analysis baseline", col: "#EA4335", every: 6 }
];
x0.font = mono;
for (var r = 0; r < rows.length; r++){
var row = rows[r];
x0.fillStyle = "rgba(232,239,250,.85)";
x0.fillText(row.label, padL, row.y – 11);
x0.strokeStyle = "rgba(29,60,102,.95)"; x0.lineWidth = 2;
x0.beginPath(); x0.moveTo(padL, row.y); x0.lineTo(padL + tw, row.y); x0.stroke();
for (var i = 0; i < 24; i++){
var px = padL + (i / 23) * tw;
var on = (i % row.every === 0) && i <= hour;
x0.beginPath();
x0.arc(px, row.y, on ? 4.2 : 2, 0, Math.PI * 2);
x0.fillStyle = on ? row.col : "rgba(147,169,200,.32)";
x0.fill();
}
if (r === 1){
var last = Math.floor(hour / 6) * 6;
var lx = padL + (last / 23) * tw;
var lw = Math.min((6 / 23) * tw, padL + tw – lx);
x0.fillStyle = "rgba(234,67,53,.20)";
x0.fillRect(lx, row.y + 6, lw, 8);
x0.fillStyle = "rgba(234,67,53,.95)";
x0.fillText("six-hour data lag", lx + 4, row.y + 28);
}
}
var phx = padL + (hour / 23) * tw;
x0.strokeStyle = "rgba(251,188,4,.7)"; x0.lineWidth = 1.4;
x0.beginPath(); x0.moveTo(phx, h * 0.06); x0.lineTo(phx, h * 0.47); x0.stroke();
s0a.textContent = String(hour + 1);
s0b.textContent = String(Math.floor(hour / 6) + 1);
s0c.textContent = pad(hour) + ":00";
}
/* ———- panel 1: resolution ———- */
var c1 = document.getElementById("c1"), x1 = c1.getContext("2d");
var r1 = document.getElementById("r1");
var s1a = document.getElementById("s1a"), s1b = document.getElementById("s1b"), s1c = document.getElementById("s1c"), s1d = document.getElementById("s1d");
function tempColor(v){
var stops = [[8,48,99],[66,133,244],[138,180,248],[251,188,4],[234,67,53]];
var t = Math.max(0, Math.min(0.999, v)) * (stops.length – 1);
var i = Math.floor(t), f = t – i;
var a = stops[i], b = stops[i + 1] || stops[i];
return "rgb(" + Math.round(a[0] + (b[0] – a[0]) * f) + "," + Math.round(a[1] + (b[1] – a[1]) * f) + "," + Math.round(a[2] + (b[2] – a[2]) * f) + ")";
}
function field(u, v){
var base = fbm(u * 3.4, v * 3.4, 5);
var ridge = Math.abs(fbm(u * 7.2 + 11.3, v * 7.2 + 7.7, 4) – 0.5);
var val = (base – 0.30) / 0.42 – ridge * 0.62;
return Math.max(0, Math.min(1, val));
}
function drawP1(){
fit(c1);
var d = dims(c1), w = d.w, h = d.h;
var km = parseFloat(r1.value);
var cell = Math.max(2, (km / 25) * 26);
x1.clearRect(0, 0, w, h);
for (var y = 0; y < h; y += cell){
for (var x = 0; x < w; x += cell){
var u = (x + cell / 2) / w, v = (y + cell / 2) / h;
x1.fillStyle = tempColor(field(u, v));
x1.fillRect(x, y, Math.ceil(cell), Math.ceil(cell));
}
}
x1.strokeStyle = "rgba(4,16,31,.28)"; x1.lineWidth = 0.6;
if (cell > 6){
for (var gy = 0; gy <= h; gy += cell){ x1.beginPath(); x1.moveTo(0, gy); x1.lineTo(w, gy); x1.stroke(); }
for (var gx = 0; gx <= w; gx += cell){ x1.beginPath(); x1.moveTo(gx, 0); x1.lineTo(gx, h); x1.stroke(); }
}
x1.fillStyle = "rgba(4,16,31,.88)"; x1.fillRect(0, h – 30, w, 30);
x1.fillStyle = "#E8EFFA";
x1.font = "600 " + (w < 430 ? 10 : 12) + "px -apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif";
x1.fillText(w < 430 ? ("2 m temperature at " + km + " km cells") : ("2 m temperature field, same forecast, redrawn at " + km + " km cells"), 12, h – 11);
var deg = (km / 100).toFixed(2);
var cells = (360 / (km / 100)) * (180 / (km / 100));
s1a.textContent = km + " km";
s1b.textContent = deg + "u00B0";
s1c.textContent = cells >= 1e6 ? (cells / 1e6).toFixed(1) + "M" : Math.round(cells / 1e3) + "K";
s1d.textContent = km <= 6 ? "0.05u00B0 stations" : (km <= 12 ? "0.1u00B0 surface" : "0.25u00B0 levels");
}
r1.addEventListener("input", drawP1);
/* ———- panel 2: ensemble ———- */
var c2 = document.getElementById("c2"), x2 = c2.getContext("2d");
var r2 = document.getElementById("r2"), b2a = document.getElementById("b2a");
var s2a = document.getElementById("s2a"), s2c = document.getElementById("s2c");
var seed = 3, members = [];
function buildMembers(){
members = [];
var steps = 60;
for (var m = 0; m < 64; m++){
var path = [0.5], val = 0.5;
for (var s = 1; s <= steps; s++){
var drift = (fbm(s * 0.11, m * 1.7 + seed, 3) – 0.5) * 0.085;
val += drift + (0.5 – val) * 0.010;
path.push(Math.max(0.05, Math.min(0.95, val)));
}
members.push(path);
}
}
buildMembers();
function drawP2(){
fit(c2);
var d = dims(c2), w = d.w, h = d.h;
var n = parseInt(r2.value, 10);
var padL = 34, padB = 26, padT = 16, padR = 30;
var pw = w – padL – padR, ph = h – padB – padT;
x2.clearRect(0, 0, w, h);
x2.fillStyle = "#04101F"; x2.fillRect(0, 0, w, h);
/* percentile band from drawn members */
var steps = members[0].length;
var lo = [], hi = [];
for (var s = 0; s < steps; s++){
var col = [];
for (var m = 0; m < n; m++) col.push(members[m][s]);
col.sort(function(a, b){ return a – b; });
lo.push(col[Math.floor(col.length * 0.1)]);
hi.push(col[Math.min(col.length – 1, Math.floor(col.length * 0.9))]);
}
x2.beginPath();
for (var i = 0; i < steps; i++){ var px = padL + (i / (steps – 1)) * pw; var py = padT + (1 – hi[i]) * ph; if (i === 0) x2.moveTo(px, py); else x2.lineTo(px, py); }
for (var j = steps – 1; j >= 0; j–){ var qx = padL + (j / (steps – 1)) * pw; var qy = padT + (1 – lo[j]) * ph; x2.lineTo(qx, qy); }
x2.closePath(); x2.fillStyle = "rgba(66,133,244,.22)"; x2.fill();
for (var m2 = 0; m2 < n; m2++){
x2.beginPath();
for (var k = 0; k < steps; k++){
var ax = padL + (k / (steps – 1)) * pw, ay = padT + (1 – members[m2][k]) * ph;
if (k === 0) x2.moveTo(ax, ay); else x2.lineTo(ax, ay);
}
x2.strokeStyle = "rgba(138,180,248," + (n > 20 ? 0.28 : 0.6) + ")";
x2.lineWidth = 1;
x2.stroke();
}
/* median */
x2.beginPath();
for (var q = 0; q < steps; q++){
var mid = (lo[q] + hi[q]) / 2;
var mx = padL + (q / (steps – 1)) * pw, my = padT + (1 – mid) * ph;
if (q === 0) x2.moveTo(mx, my); else x2.lineTo(mx, my);
}
x2.strokeStyle = "#FBBC04"; x2.lineWidth = 2; x2.stroke();
/* 48h marker */
var mark = padL + (2 / 15) * pw;
x2.setLineDash([4, 4]); x2.strokeStyle = "rgba(234,67,53,.85)"; x2.lineWidth = 1.2;
x2.beginPath(); x2.moveTo(mark, padT); x2.lineTo(mark, padT + ph); x2.stroke();
x2.setLineDash([]);
x2.fillStyle = "rgba(234,67,53,.95)";
x2.font = "600 11px -apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif";
x2.fillText("48 h: interim hourly runs end", mark + 6, padT + 14);
/* axes */
x2.strokeStyle = "rgba(29,60,102,.9)"; x2.lineWidth = 1;
x2.beginPath(); x2.moveTo(padL, padT + ph); x2.lineTo(padL + pw, padT + ph); x2.stroke();
x2.fillStyle = "rgba(147,169,200,.9)";
x2.font = "500 11px -apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif";
for (var t = 0; t <= 15; t += 5){
var tx = padL + (t / 15) * pw;
x2.textAlign = t === 15 ? "right" : (t === 0 ? "left" : "center");
x2.fillText("day " + t, t === 15 ? tx + 14 : tx, padT + ph + 16);
}
x2.textAlign = "left";
x2.save(); x2.translate(12, padT + ph / 2); x2.rotate(-Math.PI / 2);
x2.fillText("forecast value", -38, 0); x2.restore();
s2a.textContent = String(n);
var spread = (hi[steps – 1] – lo[steps – 1]) * 18;
s2c.textContent = "u00B1" + spread.toFixed(1) + "u00B0";
}
r2.addEventListener("input", drawP2);
b2a.addEventListener("click", function(){ seed += 4.7; buildMembers(); drawP2(); });
/* ———- panel 3: precipitation ———- */
var c3 = document.getElementById("c3"), x3 = c3.getContext("2d");
var r3 = document.getElementById("r3"), b3a = document.getElementById("b3a");
var storm = 0, animating = !reduce;
b3a.setAttribute("aria-pressed", animating ? "true" : "false");
b3a.textContent = animating ? "Pause storm" : "Animate storm";
b3a.addEventListener("click", function(){
animating = !animating;
b3a.setAttribute("aria-pressed", animating ? "true" : "false");
b3a.textContent = animating ? "Pause storm" : "Animate storm";
});
function rainAt(u, v, t){
var band = fbm(u * 2.4 + t, v * 1.8 – t * 0.30, 5);
var fine = fbm(u * 8.0 + t * 1.4, v * 6.0 + 4.2, 4);
var val = (band – 0.50) * 3.1 + (fine – 0.5) * 0.55;
return Math.max(0, Math.min(1, val));
}
function rainColor(p){
if (p <= 0.03) return null;
if (p < 0.34) return "rgba(52,168,83," + (0.22 + p * 0.7) + ")";
if (p < 0.62) return "rgba(66,133,244," + (0.34 + p * 0.5) + ")";
if (p < 0.85) return "rgba(251,188,4," + (0.42 + p * 0.4) + ")";
return "rgba(234,67,53," + (0.55 + p * 0.35) + ")";
}
function drawP3(){
fit(c3);
var d = dims(c3), w = d.w, h = d.h;
var split = (parseFloat(r3.value) / 100) * w;
x3.clearRect(0, 0, w, h);
x3.fillStyle = "#061A2F"; x3.fillRect(0, 0, w, h);
var coarse = 24, fine = 5;
/* left: coarse */
for (var y = 0; y < h; y += coarse){
for (var x = 0; x < split; x += coarse){
var cu = (x + coarse / 2) / w, cv2 = (y + coarse / 2) / h;
var p = (rainAt(cu, cv2, storm) + rainAt(cu + 0.035, cv2, storm) + rainAt(cu – 0.035, cv2, storm) + rainAt(cu, cv2 + 0.06, storm) + rainAt(cu, cv2 – 0.06, storm)) / 5;
var col = rainColor(p * 0.9);
if (col){ x3.fillStyle = col; x3.fillRect(x, y, Math.min(coarse, split – x), coarse); }
}
}
/* right: fine */
for (var y2 = 0; y2 < h; y2 += fine){
for (var x2c = Math.floor(split / fine) * fine; x2c < w; x2c += fine){
var p2 = rainAt((x2c + fine / 2) / w, (y2 + fine / 2) / h, storm);
var col2 = rainColor(p2);
if (col2){
x3.fillStyle = col2;
var sx = Math.max(x2c, split);
x3.fillRect(sx, y2, x2c + fine – sx, fine);
}
}
}
/* divider */
x3.strokeStyle = "#FBBC04"; x3.lineWidth = 2;
x3.beginPath(); x3.moveTo(split, 0); x3.lineTo(split, h); x3.stroke();
x3.fillStyle = "#FBBC04";
x3.beginPath(); x3.arc(split, h / 2, 7, 0, Math.PI * 2); x3.fill();
var fs = w < 430 ? 10 : 12;
x3.font = "600 " + fs + "px -apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif";
var lw1 = x3.measureText("25 km, smeared").width + 18;
var lw2 = x3.measureText("5 km, sharp bands").width + 18;
x3.fillStyle = "rgba(4,16,31,.78)";
x3.fillRect(0, 0, lw1, 22); x3.fillRect(w – lw2, 0, lw2, 22);
x3.fillStyle = "#E8EFFA";
x3.fillText("25 km, smeared", 9, 15);
x3.fillText("5 km, sharp bands", w – lw2 + 9, 15);
}
r3.addEventListener("input", drawP3);
/* ———- loop ———- */
function redrawAll(){
if (active === 0) drawP0();
else if (active === 1) drawP1();
else if (active === 2) drawP2();
else drawP3();
}
var last = 0;
function loop(ts){
if (!last) last = ts;
var dt = ts – last;
if (active === 0 && playing && dt > 620){ hour = (hour + 1) % 24; last = ts; drawP0(); }
else if (active === 3 && animating && dt > 60){ storm += 0.012; last = ts; drawP3(); }
else if (dt > 900){ last = ts; }
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
/* ———- resize + height reporting ———- */
var lastH = 0;
function sendHeight(){
var hgt = document.querySelector(".wn").offsetHeight + 40;
if (Math.abs(hgt – lastH) > 2){
lastH = hgt;
if (window.parent !== window) window.parent.postMessage({ wn3Height: hgt }, "*");
}
}
window.addEventListener("resize", function(){
[c0, c1, c2, c3].forEach(function(cv){ cv.dataset.cssw = ""; });
redrawAll(); sendHeight();
});
redrawAll();
sendHeight();
setTimeout(function(){ [c0, c1, c2, c3].forEach(function(cv){ cv.dataset.cssw = ""; }); redrawAll(); sendHeight(); }, 220);
setInterval(sendHeight, 1200);
})();
</script>
</body>
</html>
“>
Resolution and cadence
A single forward pass produces three tiers: 0.05° (~5 km) station-trained 2 m temperature and dew point; 0.1° (~10 km) gridded surface wind at 10 m and 100 m, pressure, sea surface temperature, cloud layers, solar radiation and 1-hour precipitation; and 0.25° (~25 km) atmospheric fields across 13 pressure levels. WeatherNext 2 produced 0.25° fields in 6-hour increments, which is where the roughly 5x sharper claim comes from.
Cadence is the second change. The model initializes 24 times a day. The 00, 06, 12 and 18 UTC synoptic cycles run out to 15 days (360 hours) with 64 ensemble members; interim hourly runs cover 48 hours. For fast-developing convection, an hourly refresh grounded in current satellite observations is meaningfully different from a six-hourly cycle anchored to lagged analysis.
Precipitation and clean energy variables
Precipitation is where global models historically fail, producing blurred fields that miss storm boundaries. WeatherNext 3 trains against three precipitation sources: ECMWF reanalysis, NASA’s IMERG satellite retrievals, and Google’s own satellite-radar precipitation reanalysis. Google reports CRPS improvements over baselines of up to 60% against IMERG, 30% against MRMS and 10% against rain gauges at early lead times; the research separately states up to a 50% reduction in Brier score and CRPS versus NWP baselines when evaluated against IMERG.
For renewables, the model outputs 100 m wind speed at approximate turbine hub height, full low/medium/high cloud distributions, and both solar irradiance components (SSRD and FDIR). That combination is what grid operators need to forecast wind and solar output against demand, and it is the clearest sign that this release is aimed at operational buyers, not only at benchmark tables.
Key Takeaways
- Hourly initialization from live geostationary satellite data replaces the six-hour NWP analysis lag.
- Multi-resolution output: 0.05° station variables, 0.1° gridded surface, 0.25° pressure levels, one forward pass.
- 64-member ensemble; 15-day horizon on 00/06/12/18 UTC cycles, 48 hours on interim hourly runs.
- Precipitation CRPS improves up to 60% against IMERG at early lead times, per Google’s evaluations.
- Data access is open by request; the model itself is not open weights.
Check out the Paper and Technical details. Also, feel free to follow us on Twitter and don’t forget to join our 150k+ML SubReddit and Subscribe to our Newsletter. Wait! are you on telegram? now you can join us on telegram as well.
Need to partner with us for promoting your GitHub Repo OR Hugging Face Page OR Product Release OR Webinar etc.? Connect with us
The post Google DeepMind’s WeatherNext 3 Trains on Weather Station Observations to Deliver 5 km Global Forecasts, Refreshed Every Hour appeared first on MarkTechPost.