<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>GridSim</title>
<link>https://gridsim.co.uk/notebook/</link>
<atom:link href="https://gridsim.co.uk/notebook/index.xml" rel="self" type="application/rss+xml"/>
<description>Dated, reproducible investigations on the GB electricity system. Each post ships its scenario, its command, its pinned outputs, and a legal path to the data.</description>
<generator>quarto-1.9.38</generator>
<lastBuildDate>Thu, 09 Jul 2026 04:00:00 GMT</lastBuildDate>
<item>
  <title>Reproducing observed 2024 gas burn</title>
  <dc:creator>Richard Lyon</dc:creator>
  <link>https://gridsim.co.uk/notebook/2024-validation-reference/</link>
  <description><![CDATA[ 





<p><span class="gm-eyebrow">INVESTIGATION · GB-TIER REPRODUCTION</span></p>
<section id="research-question" class="level2">
<h2 class="anchored" data-anchor-id="research-question">Research question</h2>
<p>If you hand GridSim the <strong>real</strong> 2024 GB system — the actual fleet, the actual weather, the actual must-take generation and interconnector flows — and ask it to dispatch the one thing left free, <strong>gas</strong>, does it burn the amount the grid actually burned?</p>
</section>
<section id="method" class="level2">
<h2 class="anchored" data-anchor-id="method">Method</h2>
<p>Run <code>scenarios/gb-2024-reference.toml</code>. Every non-gas source (wind, solar, nuclear, biomass, hydro, coal, pumped-storage, net imports) is set to observed 2024 outturn. Gas (CCGT + OCGT) is the residual the engine must dispatch, half-hour by half-hour, to balance the system. We compare the modelled annual gas total against the observed FUELHH total.</p>
</section>
<section id="result" class="level2">
<h2 class="anchored" data-anchor-id="result">Result</h2>
<p>The model dispatches <strong>73.45 TWh</strong> of gas against an observed <strong>72.79 TWh</strong> — a deviation of <strong>+0.91%</strong>, pinned to ±0.01 TWh in the engine’s regression suite.</p>
<figure class="gm-figure figure" aria-labelledby="fig1-cap">
<svg viewbox="0 0 340 230" width="100%" style="max-width:420px" aria-label="Bar chart: modelled 2024 gas 73.45 TWh versus observed 72.79 TWh, a plus 0.91 percent deviation.">
  <!-- baseline -->
  <line x1="55" y1="190" x2="320" y2="190" stroke="var(--gm-hairline)" stroke-width="1"></line>
  <line x1="55" y1="20" x2="320" y2="20" stroke="var(--gm-hairline)" stroke-width="1" stroke-dasharray="3 3"></line>
  <text x="50" y="194" text-anchor="end" font-size="10" fill="var(--gm-muted)" font-family="monospace">0</text>
  <text x="50" y="24" text-anchor="end" font-size="10" fill="var(--gm-muted)" font-family="monospace">80</text>
  <text x="20" y="110" text-anchor="middle" font-size="10" fill="var(--gm-muted)" font-family="monospace" transform="rotate(-90 20 110)">TWh</text>
  <!-- modelled bar (patterned + labelled, never colour-only) -->
  <rect x="80" y="33.9" width="80" height="156.1" fill="var(--gm-accent)"></rect>
  <text x="120" y="27" text-anchor="middle" font-size="12" fill="var(--gm-ink)" font-family="monospace">73.45</text>
  <text x="120" y="205" text-anchor="middle" font-size="11" fill="var(--gm-muted)">Modelled</text>
  <!-- observed bar -->
  <rect x="200" y="35.3" width="80" height="154.7" fill="var(--gm-ink)"></rect>
  <text x="240" y="27" text-anchor="middle" font-size="12" fill="var(--gm-ink)" font-family="monospace">72.79</text>
  <text x="240" y="205" text-anchor="middle" font-size="11" fill="var(--gm-muted)">Observed</text>
  <text x="240" y="220" text-anchor="middle" font-size="11" fill="var(--gm-good)" font-family="monospace">Δ +0.91%</text>
</svg>
<figcaption id="fig1-cap">Modelled versus observed 2024 GB gas generation (CCGT + OCGT).
The data table below is the accessible fallback.</figcaption>
</figure>
<table class="caption-top table">
<colgroup>
<col style="width: 30%">
<col style="width: 40%">
<col style="width: 30%">
</colgroup>
<thead>
<tr class="header">
<th>Quantity</th>
<th style="text-align: right;">TWh</th>
<th>Source (public repo path)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Modelled gas (CCGT + OCGT)</td>
<td style="text-align: right;">73.45</td>
<td><code>grid-cli/tests/regression_2024.rs</code> (<code>PINNED_GAS_TWH</code>)</td>
</tr>
<tr class="even">
<td>Observed gas (FUELHH)</td>
<td style="text-align: right;">72.79</td>
<td><code>docs/notes/2024-validation-pack-report.md</code> §2</td>
</tr>
<tr class="odd">
<td>Deviation</td>
<td style="text-align: right;">+0.91%</td>
<td>derived; pinned counterfactual for a failing ±5% gate: +5.30%</td>
</tr>
</tbody>
</table>
</section>
<section id="reproduce-it" class="level2">
<h2 class="anchored" data-anchor-id="reproduce-it">Reproduce it</h2>
<p>Committed scenario, one command:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">grid-cli</span> run scenarios/gb-2024-reference.toml <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--out</span> runs/2024-reference</span></code></pre></div></div>
<p>The run writes <code>summary.toml</code> with a header carrying the determinism triple (engine git hash · scenario SHA-256 · created-UTC) and a per-file SHA-256 for each data-pack file consumed. CI re-proves the pinned gas total on every push — the living green tick you can watch.</p>
</section>
<section id="regenerate-the-figure" class="level2">
<h2 class="anchored" data-anchor-id="regenerate-the-figure">Regenerate the figure</h2>
<p>The figure above is drawn from the two cited public numbers. This is the rerunnable recipe that redraws it from the committed run output rather than by hand:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Redraw modelled-vs-observed gas from committed artefacts.</span></span>
<span id="cb2-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Modelled: runs/2024-reference/summary.toml (regenerated by the command above).</span></span>
<span id="cb2-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Observed: docs/notes/2024-validation-pack-report.md §2 (72.79 TWh, FUELHH).</span></span>
<span id="cb2-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> tomllib, matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb2-5"></span>
<span id="cb2-6"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"runs/2024-reference/summary.toml"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rb"</span>) <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> f:</span>
<span id="cb2-7">    summary <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tomllib.load(f)</span>
<span id="cb2-8">modelled <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> summary[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gas_ccgt_twh"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> summary[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gas_ocgt_twh"</span>]   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 73.45</span></span>
<span id="cb2-9">observed <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">72.79</span>                                               <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># cited, FUELHH 2024</span></span>
<span id="cb2-10"></span>
<span id="cb2-11">fig, ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>))</span>
<span id="cb2-12">ax.bar([<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Modelled"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Observed"</span>], [modelled, observed])</span>
<span id="cb2-13">ax.set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Gas generation, TWh"</span>)</span>
<span id="cb2-14">ax.set_title(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"2024 gas: Δ </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>(modelled<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>observed)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>observed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:+.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">%"</span>)</span>
<span id="cb2-15">fig.savefig(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gas-2024.svg"</span>, bbox_inches<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tight"</span>)</span></code></pre></div></div>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>The cell is not executed at build time on this scaffold, so <code>quarto render</code> has no Python dependency. At launch, investigation posts run under <code>freeze: auto</code> against their pinned engine tag and committed CSV/TOML.</p>
</div>
</div>
</section>
<section id="discussion" class="level2">
<h2 class="anchored" data-anchor-id="discussion">Discussion</h2>
<p>This is a deliberately narrow claim, and its narrowness is its strength. The model is not being credited for reproducing wind or nuclear — those are inputs. It is being tested on the one quantity it is free to get wrong. Because gas is the marginal balancing fuel in the 2024 GB system, “how much gas” is a demanding, whole-year integral of every dispatch decision the engine makes. It lands within 0.91%.</p>
<p>The gate has teeth: mis-assigning the 3.35 TWh FUELHH “other” wedge onto gas would push the deviation to +5.30% and fail the ±5% tolerance. That failure is pinned as a counterfactual, so widening the tolerance would itself fail a test.</p>
<p>Wind and solar are excluded from this comparison on purpose — under the total-generation convention they include embedded generation the transmission-metered actuals do not, so a naive fuel-by-fuel table would be a category error. See <a href="../../model/limitations.html">Limitations</a>.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>Given the real 2024 non-gas system, GridSim burns the right amount of gas to within 0.91% of what actually happened. That single run is the standing answer to the first question about any model: <em>does it match reality?</em></p>
<div class="provenance">
<span class="provenance-head">Provenance</span>
<dl>
<dt>
Engine
</dt>
<dd>
grid-sim v0.1.0 · github.com/grid-modeller/grid-sim
</dd>
<dt>
Scenario
</dt>
<dd>
<code>scenarios/gb-2024-reference.toml</code>
</dd>
<dt>
Pinned test
</dt>
<dd>
<code>grid-cli/tests/regression_2024.rs</code>
</dd>
<dt>
Run digest
</dt>
<dd>
<code>779d7444…2541abd</code>
</dd>
<dt>
Data pack
</dt>
<dd>
<code>data/packs/2024.sha256</code> · Zenodo DOI: <em>pending Phase-0 record</em>
</dd>
</dl>
</div>
<div class="gm-attribution">
<p>Observed generation and demand: Supported by National Energy SO Open Data. Contains BMRS data © Elexon Limited copyright and database right 2024.</p>
</div>


</section>

 ]]></description>
  <category>validation</category>
  <category>2024</category>
  <category>gas</category>
  <category>GB</category>
  <guid>https://gridsim.co.uk/notebook/2024-validation-reference/</guid>
  <pubDate>Thu, 09 Jul 2026 04:00:00 GMT</pubDate>
</item>
</channel>
</rss>
