This dashboard estimates hourly solar panel generation from weather-model shortwave radiation and air temperature. It starts with a normal residential-style default so nobody has to fill in a full PV design form: Denver, a 6 kW DC array, a fixed-tilt array-geometry proxy, 14 percent total PV losses, 96 percent inverter efficiency, and a 1.2 DC/AC ratio.
The forecast uses GFS, HRRR,
or NBM data through the standard GribStream
/api/v2/[dataset]/timeseries endpoint. The core weather input is
DSWRF at the surface, NOAA's downward shortwave radiation flux field, combined with 2 m air temperature
for a simple panel-temperature derate. The dashboard keeps the lead window to 24 or 36 hours so the returned rows stay
hourly across the available model choices.
The math is intentionally lightweight. It is useful for comparing weather-driven production patterns, screening a proposed install, and explaining how GribStream expressions can turn forecast fields into application metrics. It is not a bankable PV design model and it does not replace PVWatts, SAM, site shade modeling, measured soiling, or an engineering-grade plane-of-array irradiance model.
The array-geometry control is deliberately conservative. A real tilt and azimuth calculation needs solar position,
direct normal irradiance, diffuse horizontal irradiance, albedo, module orientation, row geometry, and shading. This
dashboard only requests DSWRF and 2 m temperature from GribStream, so it exposes the geometry assumption
as a named multiplier instead of hiding a fake precision model behind a tilt field.
The dashboard computes every derived field in GribStream expressions. With the default controls, the equations are:
temp_c = temp_k - 273.15poa_wm2 = ghi_wm2 * 1.0800cell_temp_c = temp_c + (poa_wm2 / 800.0) * 25.0000temperature_factor = max(0, 1 + (-0.3500 / 100) * (cell_temp_c - 25.0))loss_factor = max(0, 1 - 14.0000 / 100)dc_power_kw = 6.0000 * poa_wm2 / 1000.0 * temperature_factor * loss_factorac_limit_kw = 6.0000 / 1.2000ac_power_kw = min(dc_power_kw * 96.0000 / 100, ac_limit_kw)hourly_energy_kwh = ac_power_kw, because the dashboard limits the query to hourly rows.The most important constants are:
6.0000 is the default DC array size in kW. It is user-editable.1.0800 is the default array-geometry multiplier, a fixed-tilt proxy applied to horizontal DSWRF. Other exposed scenarios use 1.0000, 0.9300, and 1.1800.800.0 W/m2 and 25.0000 C form the simple cell-temperature rise estimate. They are hidden defaults, not a site-calibrated module thermal model.-0.3500 is the hidden power temperature coefficient in percent per C, applied relative to the 25.0 C reference temperature.14.0000 is the default total non-weather loss percentage. It is user-selectable.1.2000 is the default DC/AC ratio, so a 6 kW DC array has a 5 kW AC limit. It is user-selectable.96.0000 is the hidden inverter efficiency percentage.1000.0 W/m2 normalizes irradiance to a PV nameplate-style reference level.These constants make the forecast explainable and easy to vary, but they are not a replacement for a module datasheet, measured albedo, measured soiling, shade geometry, or a full PVWatts/SAM model run.
This example uses the default 6 kW fixed-tilt proxy at Denver with GFS. The dashboard fills the
numeric defaults from Grafana variables and computes the PV estimates in one standard GribStream
/timeseries call.
curl -X POST 'https://gribstream.com/api/v2/gfs/timeseries' \
-H 'Content-Type: application/json' \
-H 'Accept: text/csv' \
-H 'Authorization: Bearer [API_TOKEN]' \
-d '{
"fromTime": "2026-05-03T12:00:00Z",
"untilTime": "2026-05-05T00:00:00Z",
"minLeadTime": "0h",
"maxLeadTime": "36h",
"coordinates": [
{ "lat": 39.7392, "lon": -104.9903, "name": "Denver, CO" }
],
"variables": [
{ "name": "DSWRF", "level": "surface", "alias": "ghi_wm2" },
{ "name": "TMP", "level": "2 m above ground", "alias": "temp_k" }
],
"expressions": [
{ "expression": "temp_k - 273.15", "alias": "temp_c" },
{ "expression": "ghi_wm2 * 1.0800", "alias": "poa_wm2" },
{ "expression": "temp_c + (poa_wm2 / 800.0) * 25.0000", "alias": "cell_temp_c" },
{ "expression": "func.Max(0.0, 1 + (-0.3500 / 100.0) * (cell_temp_c - 25.0))", "alias": "temperature_factor" },
{ "expression": "func.Max(0.0, 1 - 14.0000 / 100.0)", "alias": "loss_factor" },
{ "expression": "6.0000 * poa_wm2 / 1000.0 * temperature_factor * loss_factor", "alias": "dc_power_kw" },
{ "expression": "6.0000 / 1.2000", "alias": "ac_limit_kw" },
{ "expression": "func.Min(dc_power_kw * 96.0000 / 100.0, ac_limit_kw)", "alias": "ac_power_kw" },
{ "expression": "ac_power_kw", "alias": "hourly_energy_kwh" },
{ "expression": "func.Max(0.0, (6.0000 - ac_power_kw) / 6.0000 * 100.0)", "alias": "unused_capacity_pct" }
]
}'
DSWRF is a horizontal radiation field.Background and references: GribStream expressions · GFS model inventory · HRRR model inventory · NBM model inventory · NOAA GRIB2 shortwave radiation table · PVWatts V8 API · SAM irradiance definitions · Grafana variables.