Technical Implementation#
This section provides technical details about GB-specific implementation features.
FES Powerplants Data#
Overview#
The GB model uses powerplant capacity data from the Future Energy Scenarios (FES) workbook, enriched with technical and cost parameters to create a complete dataset ready for PyPSA network composition. This data replaces the default PyPSA-Eur powerplants dataset with GB-specific capacity projections.
Data Pipeline#
The powerplants data flows through two main stages:
Capacity Aggregation (
create_powerplants_table.py)Processes FES workbook data (GB regions)
Processes European supply data (neighboring countries)
Maps technology names to PyPSA carriers
Aggregates capacities by bus, year, carrier, and set
Cost Enrichment (
create_powerplants_table.py)Joins technology cost data (efficiency, VOM, fuel costs, etc.)
Calculates marginal costs
Fills missing values with sensible defaults
Creates unique generator indices
Output Format#
The resulting fes_powerplants.csv contains complete generator data:
Core Attributes:
bus- Network bus ID (string)year- Planning year (integer)carrier- Technology type (CCGT, nuclear, onwind, etc.)set- Generator classification (PP, CHP, Store)p_nom- Nominal capacity in MW (float)build_year- Year of installation (integer)
Technical Parameters:
efficiency- Energy conversion efficiency (0-1)lifetime- Asset lifetime in years (float)
Economic Parameters:
VOM- Variable O&M cost (GBP/MWh)FOM- Fixed O&M cost (€/MW/year)capital_cost- Investment cost (€/MW)fuel- Fuel cost (GBP/MWh_thermal)marginal_cost- Total variable cost (GBP/MWh_el)
Index Format: "{bus} {carrier}-{year}-{counter}"
Example: "GB0 CCGT-2030-0", "GB0 CCGT-2030-1"
Marginal Cost Calculation#
Marginal cost combines variable O&M and fuel costs:
marginal_cost = VOM + fuel / efficiency
Where:
VOM- Variable operations and maintenance (GBP/MWh_el)fuel- Fuel cost (GBP/MWh_thermal)efficiency- Conversion efficiency (MWh_el / MWh_thermal)
Example for CCGT with efficiency=0.55, VOM=2.5, fuel=25.0:
marginal_cost = 2.5 + 25.0/0.55 = 47.95 GBP/MWh
Default Values#
When cost data is unavailable for specific carriers, defaults are applied:
efficiency: 1 (100% conversion efficiency)capital_cost: 0.0 €/MWlifetime: 25.0 yearsmarginal_cost: 0.0 GBP/MWh
These defaults prevent missing data from blocking network composition while logging warnings for review.
Integration with compose_network#
The compose_network rule loads the enriched powerplants data directly:
ppl = pd.read_csv(powerplants_path, index_col=0, dtype={"bus": "str"})
This data is then used by:
attach_conventional_generators()- Adds fossil/nuclear generatorsattach_wind_and_solar()- Adds renewable generatorsattach_hydro()- Adds hydro and storage unitsattach_chp_constraints()- Applies CHP heat demand constraints
No additional preprocessing is required; all necessary attributes are present in the CSV.
Configuration#
The create_powerplants_table rule requires:
Inputs:
gsp_data- GB regional capacity data from FES workbookeur_data- European national capacity datatech_costs- Technology cost assumptions
Parameters:
gb_config- GB technology mapping configurationeur_config- European technology mapping configurationdefault_set- Default generator classification (typically “PP”)
Output:
fes_powerplants.csv- Complete powerplants dataset
File Location#
scripts/gb_model/
└── create_powerplants_table.py # Data processing and enrichment
rules/
└── gb-model.smk # Snakemake rule definitions
results/{run}/resources/gb-model/
└── fes_powerplants.csv # Generated output
Simplified CHP Implementation#
Overview#
Combined Heat and Power (CHP) plants generate both electricity and heat simultaneously, typically for district heating networks or industrial processes. In electricity markets, CHPs must often maintain minimum electricity generation to meet their heat supply obligations, even when electricity prices are low. This creates operational constraints that significantly affect electricity market dispatch and pricing.
The GB model implements a simplified CHP representation suitable for electricity-only market modeling. Rather than explicitly modeling heat networks and sector coupling (as in PyPSA-Eur’s full sector network), CHPs are represented as electricity generators with time-varying minimum generation constraints (p_min_pu) derived from heat demand profiles. This approach captures the key market impact—CHPs’ reduced flexibility due to heat obligations—while avoiding the complexity of multi-sector optimization.
Key Simplification: Instead of modeling CHPs as multi-output Links with explicit heat buses and loads, they are modeled as Generators with minimum operation levels that implicitly represent heat demand obligations. This maintains electricity market realism while keeping the model computationally efficient.
Implementation Components#
CHP Identification#
CHPs are identified from powerplants data using the Set column:
chp_plants = powerplants[powerplants["set"] == "CHP"]
Data Source: The Set column in powerplants CSV distinguishes:
PP- Regular power plantsCHP- Combined Heat and Power plantsStore- Storage facilities (hydro)
Heat Demand Processing#
Heat demand is loaded from the hourly heat demand NetCDF file.
Data Structure:
Dimensions:
snapshots(time),node(buses)Variables:
residential waterresidential spaceservices waterservices space
Processing Steps:
Load heat demand dataset
Sum all heat types to get total heat demand per bus
Normalize by peak demand to create 0-1 profile
Minimum Operation Calculation#
The minimum power output (p_min_pu) is calculated using:
Key Parameters:
heat_to_power_ratio (default: 1.5)
Represents the back-pressure coefficient (\(c_b\))
Typical values: 1.0-2.0 for gas CHPs
Higher values = more heat per unit electricity
Determines how much CHP must run to meet heat demand
min_operation_level (default: 0.3)
Minimum operation when CHP is running (30% of capacity)
Technical constraint - CHPs cannot operate below this level
Applied as an upper bound on p_min_pu
Special Handling:
When heat demand < 10% of peak, CHPs can shut down completely (p_min_pu = 0)
This prevents forcing CHPs to run during very low heat demand periods
Application to Generators#
After conventional generators are attached to the network:
Identify CHP generators by matching:
Bus location with CHP powerplants
Carrier type (typically CCGT)
Apply time series constraint (vectorized):
# For all CHP generators at once n.generators_t.p_min_pu[chp_gen_indices] = p_min_pu_for_gens
Result: CHPs must run at least at p_min_pu level when operational
Configuration#
Add to config/config.gb.default.yaml:
chp:
enable: true # Enable CHP constraints
heat_to_power_ratio: 1.5 # Heat/power ratio (c_b)
min_operation_level: 0.3 # Min operation (30%)
Configuration Options#
enable: Set to
falseto disable CHP constraints (treat as regular generators)heat_to_power_ratio: Adjust based on CHP technology
Gas turbine CHPs: 1.0-1.5
Steam turbine CHPs: 1.5-2.5
Reciprocating engines: 0.8-1.2
min_operation_level: Technical minimum (typically 0.2-0.4)
File Structure#
scripts/gb_model/
├── chp_utils.py # CHP utility functions
└── compose_network.py # Integration point
config/
└── config.gb.default.yaml # CHP configuration
Methodology#
Heat-to-Power Ratio#
The heat_to_power_ratio parameter represents the back-pressure coefficient \(c_b = \eta_{heat} / \eta_{el}\), where \(\eta_{el}\) and \(\eta_{heat}\) are the electrical and thermal efficiencies. For typical gas CHPs with \(\eta_{el}\) ≈ 0.4 and \(\eta_{heat}\) ≈ 0.5, \(c_b\) ≈ 1.25-1.5.
Minimum Operation Logic#
For each time step, the minimum generation constraint is:
if heat_profile[bus, t] < 0.1: # < 10% of peak heat demand
p_min_pu[bus, t] = 0.0 # CHP can shut down
else:
p_min_pu[bus, t] = min(
heat_profile[bus, t] / heat_to_power_ratio,
min_operation_level # Technical minimum (e.g., 0.3)
)
This ensures:
CHPs follow heat demand when significant
CHPs respect technical minimum operation level
CHPs can shut down during very low heat demand
Limitations#
This simplified approach does not model:
Heat network topology and transmission
Thermal storage for decoupling heat and power
Variable heat-to-power operating modes
Heat provision for ancillary services
For applications requiring detailed heat sector modeling, use PyPSA-Eur’s full sector-coupling approach with explicit heat buses and Links.