← Back to Explore
Explore · The open model · Inputs

What the open model is given

The open model

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.
The common reference case: reference technology costs across the board, least constrained expansion, reference flexibility.

What Denmark can build

The generators in DK1 and DK2, with the costs the model weighs them by. For each expandable technology the model chooses the capacity, up to the upper limit; the others are fixed. Everything outside Denmark is fixed too.

TechnologyZoneCapacity
MW
Upper limit
MW
Capital cost
€/kW/yr
Fixed O&M
€/kW/yr
Variable cost
€/MWh
Mean availabilitySource
Nuclearnuclear_new_DK1DK1chosen by the model2,000486.5100.5-2.190.0 %generators.csv, line 55 ↗
Nuclearnuclear_new_DK2DK2chosen by the model2,000486.5100.5-2.190.0 %generators.csv, line 56 ↗
Biomassbiomass_DK1DK1255fixed0.00.038.274.8 %generators.csv, line 59 ↗
Biomassbiomass_DK2DK2446fixed0.00.038.266.3 %generators.csv, line 60 ↗
Wastewaste_DK1DK155fixed0.00.00.0100.0 %generators.csv, line 57 ↗
Wastewaste_DK2DK241fixed0.00.00.0100.0 %generators.csv, line 58 ↗
Wind offshore nearshorewind_offshore_new_DK1DK1chosen by the model4,400182.330.03.052.1 %generators.csv, line 61 ↗
Wind offshore nearshorewind_offshore_new_DK2DK2chosen by the model6,700182.330.03.046.6 %generators.csv, line 63 ↗
Wind offshorewind_offshore_farshore_new_DK1DK1chosen by the model23,000227.830.03.052.1 %generators.csv, line 62 ↗
Wind offshorewind_offshore_farshore_new_DK2DK2chosen by the model1,600227.830.03.046.6 %generators.csv, line 64 ↗
Wind onshorewind_onshore_new_DK1DK16,514fixed109.718.82.238.2 %generators.csv, line 65 ↗
Wind onshorewind_onshore_new_DK2DK2609fixed109.718.82.235.9 %generators.csv, line 66 ↗
Solar utilitysolar_new_DK1DK1chosen by the model50,00030.913.20.011.4 %generators.csv, line 69 ↗
Solar utilitysolar_new_DK2DK2chosen by the model50,00030.913.20.011.4 %generators.csv, line 70 ↗
Solar residentialsolar_existing_DK1DK14,959fixed0.00.00.011.4 %generators.csv, line 67 ↗
Solar residentialsolar_existing_DK2DK22,652fixed0.00.00.011.4 %generators.csv, line 68 ↗

As stored in the network files. For expandable technologies the file also holds a p_nom, which the capacity-expansion step does not use: it chooses the capacity itself. Capital cost is the annualised fixed cost the expansion step weighs (capital_cost); fixed O&M (fom_cost) and variable cost (marginal_cost) as given. For dispatchable plant the variable cost rises with output (marginal_cost_quadratic), a fleet of units of varying cost. Mean availability is the average of the hourly availability profile; wind and solar must produce exactly what the weather allows. Model names are DNA-PyPSA’s; technology names follow the report.

Weather and demand, hour by hour

Wind, sun and temperature-driven demand all come from one weather year, 1991, chosen because its price volatility and capture rates are close to the long-run average of the 33 years in the dataset. Demand peaks and troughs therefore line up with the wind and sun the way they did that year.

West Denmark (DK1): demand and availability, Balanced
Daily averages. Zoom with the slider, or pinch or Ctrl-scroll on the chart; drag to move.
Loading the year’s hours…
Demand categories include their flexible parts, which the model may shift in time.demand/DK1.csv ↗profiles/DK1.csv ↗

Flexibility in Danish demand

Not all demand is fixed. Flexible demand has a buffer: it can buy electricity ahead, in cheaper hours, and hold it until it is needed, but it cannot postpone what it needs. Price-sensitive demand is only served while the price is below what it is willing to pay, and that willingness falls the more of it is served.

Flexible demand
DemandZoneMax draw MWBuffer MWhCharge on all its energy €/MWhSource
Residential & commercialDK1121483100links.csv, line 32 ↗
stores.csv, line 24 ↗
Residential & commercialDK288353100links.csv, line 33 ↗
stores.csv, line 25 ↗
Electric vehiclesDK149911,963100links.csv, line 34 ↗
stores.csv, line 26 ↗
Electric vehiclesDK23688,822100links.csv, line 35 ↗
stores.csv, line 27 ↗
IndustryDK1173691100links.csv, line 36 ↗
stores.csv, line 28 ↗
IndustryDK2101404100links.csv, line 37 ↗
stores.csv, line 29 ↗
ElectrolysersDK11,593458,74550links.csv, line 38 ↗
stores.csv, line 30 ↗
ElectrolysersDK223467,28350links.csv, line 39 ↗
stores.csv, line 31 ↗
Hot waterDK11581,89950links.csv, line 40 ↗
stores.csv, line 32 ↗
Space heatingDK18883,55150links.csv, line 41 ↗
stores.csv, line 33 ↗
Hot waterDK21361,62850links.csv, line 42 ↗
stores.csv, line 34 ↗
Space heatingDK27643,05550links.csv, line 43 ↗
stores.csv, line 35 ↗

Max draw: the most the load can take from the grid in an hour, to use and to fill its buffer. Buffer: how much it can hold; it starts empty, so demand can be brought forward but not postponed. The charge applies to every MWh the load draws, so it comes to the same total whether or not demand is moved.

Price-sensitive demand

Pays up to: what the first MW is willing to pay; the willingness falls in a straight line as more is served (the quadratic cost term), to about 100 €/MWh at full size for the 1,000 €/MWh rows. At most: the most it can consume over the year, from its hourly limits.

Batteries
ZoneCost €/kWhRound-tripLifetime yrDiscount rateSource
DK119181 %158 %stores.csv, line 54 ↗
DK219181 %158 %stores.csv, line 55 ↗

Overnight cost of storage; 90 % each way. The network as published carries no battery capacity in any scenario.

Connections to the neighbours

Transmission between zones is fixed, at capacities based on ENTSO-E plans; the model does not expand it. Each border is two one-way links that lose 5 % of what they carry.

Transmission capacity at Denmark’s borders
3,500 MW1,730 MW1,400 MW715 MW700 MW600 MW1,700 MW1,000 MWDK1DENO125GBSE3NLDK2SE4
Modelled zonesNot modelled600 MW1,700 MW3,500 MWBidding-zone boundaries: electricitymaps-contrib v1.238.0 (web/geo/world.geojson), AGPL-3.0; projected (EPSG:3035), clipped and simplified as in QC's qc-grid-maps transmission maps.
BorderOut of the Danish zone MWInto the Danish zone MWEfficiencySources
DK1 – DE Germany3,5003,50095 %links.csv, line 132 ↗ links.csv, line 133 ↗
DK1 – NO125 Norway South/West1,7301,73095 %links.csv, line 125 ↗ links.csv, line 124 ↗
DK1 – GB Great Britain1,4001,40095 %links.csv, line 154 ↗ links.csv, line 155 ↗
DK1 – SE3 Sweden South-Central71571595 %links.csv, line 123 ↗ links.csv, line 122 ↗
DK1 – NL Netherlands70070095 %links.csv, line 148 ↗ links.csv, line 149 ↗
DK1 – DK2 Denmark East60060095 %links.csv, line 126 ↗ links.csv, line 127 ↗
DK2 – SE4 Sweden South1,7001,70095 %links.csv, line 121 ↗ links.csv, line 120 ↗
DK2 – DE Germany1,0001,00095 %links.csv, line 130 ↗ links.csv, line 131 ↗

The system around Denmark

The other 15 zones have fixed fleets, set by a separate optimisation of the European power system with the Balanced scenario as reference. They give Denmark realistic prices and trade at its borders without being optimised alongside it, since national energy policies are in practice made independently.

Installed capacity in the surrounding zones

Excludes hydropower, modelled through reservoirs and inflows rather than as a fleet of generators. generators.csv ↗

How the run is set up, and how to repeat it

Run settings, Balanced
Modeiterate capacity expansion, then iterative dispatch and capacity adjustment
Pre-solveisland
Price ceiling in Denmark3,000 €/MWh
Price ceiling in importing zones600 €/MWh
Solver usedgurobi HiGHS, which is free, also works

reference_scenario.json ↗ · network files ↗ · hourly profiles ↗ · run modes ↗

Repeat this run
# get the model and its inputs
git clone https://github.com/QuantifiedCarbon/DNA-PyPSA.git
cd DNA-PyPSA && pip install .

# solve the Balanced scenario
python scripts/run_full_scenarios.py --scenario reference

Results are written as CSV and netCDF and can be compared with the published ones in publication_results/reference ↗.