What the open model returns
DNA-PyPSA
The study verified its main model, cGrid, independently with PyPSA, an open-source framework for optimising power systems. The PyPSA model built for the study is open source, for transparency and for work beyond the report.
These two explorers show that model’s own files: what it is given, and what it returns. Every number links to the file and line it comes from.
- Zones
- 17 bidding zones. Capacity is optimised in DK1 and DK2 only; the other 15 zones have fixed fleets.
- Weather
- One weather year, 1991, in 8,760 hourly steps (timestamped 2050).
- Method
- Capacity expansion, then dispatch adjusted step by step until prices and capacities settle (“iterate” mode).
- Licence
- MIT: free to use, change and share.
f0f1761 (2026-07-02) · the repository opens to the public with the study · §3.1.2 PyPSA – open source (p.24)What the model builds, scenario by scenario
In each scenario the model chooses Denmark’s generating capacity for 2050, within the options and limits on the Inputs page, then runs the year hour by hour. Denmark as a whole; all seven scenarios.
| DK | Balanced | Offshore Bal. | Offshore | Solar Bal. | Solar | Nuclear Bal. | Nuclear |
|---|---|---|---|---|---|---|---|
| Demand TWh | 101.9 | 101.8 | 101.8 | 101.9 | 101.9 | 101.9 | 101.9 |
| Net exports TWh | 11.7 | 6.8 | 5.6 | 7.7 | 6.8 | 12.8 | 16.9 |
| Curtailment TWh | 0.00 | 0.04 | 0.10 | 0.01 | 0.02 | 0.00 | 0.00 |
| Unserved demand GWh | 0.1 | 0.2 | 33.0 | 0.2 | 0.0 | 0.2 | 0.2 |
| Average price €/MWh | 81 | 89 | 104 | 87 | 92 | 80 | 75 |
| Hours at or below 0 €/MWh h | 999 | 1,229 | 1,402 | 1,126 | 1,265 | 964 | 625 |
| Hours above 500 €/MWh h | 140 | 266 | 473 | 201 | 287 | 130 | 96 |
| Capture rate, wind onshore % | 67 | 55 | 37 | 60 | 58 | 67 | 73 |
| Capture rate, wind offshore nearshore % | 72 | 66 | 50 | 67 | 64 | 73 | 79 |
| Capture rate, wind offshore % | 75 | 64 | 47 | 69 | 67 | 76 | 80 |
| Capture rate, solar residential % | 48 | 53 | 50 | 54 | 52 | 47 | 43 |
| Capture rate, nuclear % | 114 | 119 | – | 118 | – | 114 | 112 |
| Capacity factor, nuclear % | 82 | 82 | – | 81 | – | 82 | 83 |
| Capacity factor, biomass % | 38 | 41 | 42 | 42 | 41 | 39 | 37 |
| Capacity factor, waste % | 87 | 83 | 82 | 84 | 84 | 87 | 88 |
| Capacity factor, wind offshore nearshore % | 50 | 49 | 49 | 49 | 49 | 50 | 51 |
| Capacity factor, wind offshore % | 52 | 52 | 52 | 52 | 52 | 52 | 52 |
| Capacity factor, wind onshore % | 38 | 38 | 38 | 38 | 38 | 38 | 38 |
| Capacity factor, solar utility % | – | – | 8 | 8 | 8 | – | – |
| Capacity factor, solar residential % | 8 | 8 | 8 | 9 | 8 | 8 | 9 |
Capture rate: the average price a technology earns per MWh, as a share of the average price. Capacity factor: the year’s generation as a share of what the installed capacity could produce running flat out all year. Unserved demand is met by the model’s emergency supply at 3,000 €/MWh.
Danish capacities here are those of the report’s Figure 54 (p.114) (PyPSA) in all seven scenarios. How they compare with cGrid: PyPSA and cGrid compared.
The year, hour by hour
Supply above zero, by source; exports, storage charging and curtailment below it; demand as the green line. Wind and solar produce whatever the 1991 weather gives them; the rest follows the price. Any zone of the model can be shown: outside Denmark the fleets are fixed, but their dispatch is solved with Denmark’s in every scenario.
These are DNA-PyPSA’s own hourly results for one weather year, 1991; the report’s results come from cGrid across 33 weather years. The report compares the two models’ capacity, annual generation and trade (§5.9 Model comparisons (p.111)), not their hourly dispatch.
Trade with the neighbours
Energy exported to and imported from each neighbouring zone over the year, measured at the Danish border; trade between DK1 and DK2 is left out. This is DNA-PyPSA’s trade for one weather year, 1991, not the report’s cGrid results. The report compares Denmark’s net transmission by neighbour in the two models (Figure 58 (p.118)): PyPSA exports 5.5 to 14.9 TWh less than cGrid, depending on the scenario.
DE: Germany · NO125: Norway South/West · GB: Great Britain · SE4: Sweden South · NL: Netherlands · SE3: Sweden South-Central.
Take the results with you
# pip install pypsa — then, in the cloned repository:
import pypsa
n = pypsa.Network("publication_results/reference/pypsa/pypsa_network")
n.statistics.energy_balance()
n.buses_t.marginal_price[["DK1", "DK2"]].describe()Prepared from DNA-PyPSA commit f0f1761 by scripts/build_pypsa_data.py in this site’s repository, which checks that supply and demand balance in every hour.