Your First Custom Scenario#
This tutorial walks you through creating and running a custom scenario.
Understanding Scenarios#
A scenario in PyPSA-GB defines:
The modelled year (historical or future)
Which FES pathway to use
Network model type (ETYS, Reduced, Zonal)
Solve settings and time period
Scenarios are defined in config/scenarios.yaml and activated in config/config.yaml.
Step 1: View Existing Scenarios#
Open config/scenarios.yaml to see example scenarios:
# Example scenario definition
HT35:
description: "Holistic Transition 2035"
modelled_year: 2035
renewables_year: 2019
demand_year: 2035
network_model: "ETYS"
FES_year: 2024
FES_scenario: "Holistic Transition"
solve_period:
enabled: true
start: "2035-01-01 00:00"
end: "2035-01-07 23:00"
Step 2: Create Your Scenario#
Add a new scenario to config/scenarios.yaml:
# My custom scenario
MyScenario_2040:
description: "Custom 2040 analysis - winter week"
modelled_year: 2040
renewables_year: 2018 # Weather year for renewables
demand_year: 2040
network_model: "Reduced" # Use 32-bus for faster solving
FES_year: 2024
FES_scenario: "Electric Engagement"
solve_period:
enabled: true
start: "2040-01-13 00:00" # A winter week
end: "2040-01-19 23:00"
solver:
name: "gurobi"
method: 2 # Barrier method
Key Configuration Options#
Parameter |
Description |
Options |
|---|---|---|
|
Target year to model |
2010-2050 |
|
Weather data year |
2010-2024 (auto-download from Zenodo) |
|
Network resolution |
|
|
FES release year |
2021, 2022, 2023, 2024, 2025 |
|
FES pathway name |
Varies by FES release |
|
Time window to solve |
Any date range |
Available FES Years and Scenarios#
FES releases are updated annually by NESO. You can use different FES release years to:
Compare scenario projections across different releases
Access historical FES assumptions from earlier releases
Model the evolution of capacity expectations over time
Note: Different newer FES releases may have different scenario names and parameters. Check available data before running.
Step 3: Activate Your Scenario#
Edit config/config.yaml to add your scenario:
scenarios:
- MyScenario_2040
# - HT35 # Comment out others if not needed
Step 4: Validate Configuration#
Check your scenario is valid:
python scripts/validate_scenarios.py
This checks:
All required fields are present
FES data exists for the specified year
Weather cutouts are available
Step 5: Run Your Scenario#
# Dry run first to see what will execute
snakemake resources/network/MyScenario_2040_solved.nc -n -p
# Full run
snakemake resources/network/MyScenario_2040_solved.nc -j 4
Step 6: Analyze Results#
Load and analyze your results:
import pypsa
import pandas as pd
import matplotlib.pyplot as plt
# Load network
n = pypsa.Network("resources/network/MyScenario_2040_solved.nc")
# Generation dispatch over time
gen = n.generators_t.p.groupby(n.generators.carrier, axis=1).sum()
gen.plot.area(figsize=(12, 6), title="Generation Dispatch")
plt.ylabel("Power (MW)")
plt.tight_layout()
plt.savefig("my_scenario_dispatch.png")
# Curtailment analysis
renewable_carriers = ['wind_onshore', 'wind_offshore', 'solar_pv']
for carrier in renewable_carriers:
gens = n.generators[n.generators.carrier == carrier]
if len(gens) > 0:
available = n.generators_t.p_max_pu[gens.index].sum(axis=1) * gens.p_nom.sum()
dispatched = n.generators_t.p[gens.index].sum(axis=1)
curtailment = (available - dispatched) / available * 100
print(f"{carrier}: {curtailment.mean():.1f}% average curtailment")
Scenario Variations#
Historical Scenario#
For historical validation (uses real data, not FES):
Historical_2022:
description: "Historical year 2022 validation"
modelled_year: 2022
renewables_year: 2022
demand_year: 2022
network_model: "ETYS"
# No FES_scenario needed for historical years
High-Resolution Solve#
For detailed analysis of specific events:
StormAnalysis_2035:
description: "Storm period analysis"
modelled_year: 2035
solve_period:
enabled: true
start: "2035-02-01 00:00"
end: "2035-02-03 23:00" # 3-day detailed analysis
timestep_minutes: 30 # Half-hourly resolution
Clustered Network#
For faster solving with reasonable accuracy:
HT35_clustered:
description: "Holistic Transition 2035 - clustered"
modelled_year: 2035
network_model: "ETYS"
clustering:
enabled: true
n_clusters: 100 # Reduce to 100 buses
Comparing FES Releases#
Compare how projections change across FES releases:
HT35_FES2024:
description: "HT scenario 2035 - FES 2024"
modelled_year: 2035
FES_year: 2024
FES_scenario: "Holistic Transition"
network_model: "Reduced"
HT35_FES2023:
description: "HT scenario 2035 - FES 2023"
modelled_year: 2035
FES_year: 2023 # Different FES release
FES_scenario: "Holistic Transition"
network_model: "Reduced"
Run both scenarios to compare results and understand how NESO’s capacity expectations evolved between releases.
Common Issues#
“Cutout not found”#
For years 2010-2024, cutouts are automatically downloaded from Zenodo when needed. If you get this error:
Check if cutout workflow was run:
ls resources/atlite/cutouts/Generate missing cutouts (will auto-download from Zenodo for 2010-2024):
# Configure the year first nano config/cutouts_config.yaml # Set: years_to_generate: [2018] # Run cutout workflow snakemake -s Snakefile_cutouts --cores 1
For years outside 2010-2024, you’ll need CDS API credentials (see Installation).
“Infeasible optimization”#
Check that generation capacity meets demand:
n = pypsa.Network("resources/network/MyScenario_unsolved.nc")
print(f"Generation: {n.generators.p_nom.sum()/1000:.1f} GW")
print(f"Peak demand: {n.loads_t.p_set.sum(axis=1).max()/1000:.1f} GW")
Next Steps#
Configuration Reference - Full configuration reference
Scenario Design - Advanced scenario design
Data Sources - Understanding input data