Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4b8f2a2
feat: add configuration for pecd fill_gaps_method for missing data
daniel-rdt Jul 11, 2025
1224c36
feat: add SolarPV for utility and rooftop with differentiation
daniel-rdt Jul 14, 2025
d501597
fix: adjust config name of solar-pv carrier
daniel-rdt Jul 15, 2025
89a89ad
fix: make LFSolarPV import more generic to differentiation of more nodes
daniel-rdt Jul 15, 2025
148b508
feat: add Exception if no input data for specified PECD tech
daniel-rdt Jul 15, 2025
265b6ac
feat: add onshore wind to tyndp renewable carriers and pecd profiles
daniel-rdt Jul 15, 2025
6afdd2c
fix: check in add existing renwables in case non of the specified car…
daniel-rdt Jul 16, 2025
de41c1b
fix: add back onwind and solar to renewable carriers until tyndp carr…
daniel-rdt Jul 16, 2025
67e2d99
feat: Slightly improve value error message
daniel-rdt Jul 30, 2025
b487dde
feat: add todo for redundant renewable carriers
daniel-rdt Jul 30, 2025
f80ac54
feat: custom fix for skiprows and typo
daniel-rdt Jul 30, 2025
7793eb7
feat: add collect rules for clean_pecd_datas and build_renewable_prof…
daniel-rdt Jul 30, 2025
956939a
feat: add logger warning for missing files
daniel-rdt Jul 30, 2025
090c95e
Merge branch 'master' into feat/47-pecd-complete
daniel-rdt Jul 30, 2025
0b5a298
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 30, 2025
405e4da
feat: introduce safe_pyear helper function
daniel-rdt Jul 30, 2025
96794be
feat: make handling of GB and UK more consistent
daniel-rdt Jul 30, 2025
35e4d45
feat: adjust wording of logger about existing capacities
daniel-rdt Jul 30, 2025
a78fbc5
doc: document compatibility with Solar CSP
daniel-rdt Jul 31, 2025
7bbd23d
doc: document new config option for available pyears in all configs a…
daniel-rdt Jul 31, 2025
2e274a1
doc: add release note
daniel-rdt Jul 31, 2025
27abc95
feat: add verbose option to safe_pyear helper function
daniel-rdt Jul 31, 2025
cf4fc7e
Apply suggestions from code review
daniel-rdt Aug 1, 2025
7e51535
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 1, 2025
67f44ac
fix: remove manual 2050 fallback to 2040 for PECD data
daniel-rdt Aug 1, 2025
7c0a0c0
feat: adjust input and output types in safe_pyear
daniel-rdt Aug 1, 2025
17c880c
Apply suggestions from code review
daniel-rdt Aug 1, 2025
cedc093
feat: refactor input_data_pecd function for easier readability
daniel-rdt Aug 11, 2025
0cb02f8
apply suggestions from code review
daniel-rdt Aug 11, 2025
90616ea
doc: add documentation for retrieve_tyndp_pecd_data rule
daniel-rdt Aug 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/config.default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ electricity:

pecd_renewable_profiles:
enable: false
fill_gaps_method: zero
technologies:
Wind_Offshore:
- offwind-ac-fb-r
Expand Down
11 changes: 9 additions & 2 deletions config/config.tyndp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,12 @@ co2_budget:
electricity:
base_network: tyndp-raw

renewable_carriers: [solar, solar-hsat, onwind, hydro]
tyndp_renewable_carriers: [offwind-ac-fb-r, offwind-ac-fl-r, offwind-dc-fb-r, offwind-dc-fl-r, offwind-dc-fb-oh, offwind-dc-fl-oh, offwind-h2-fb-oh, offwind-h2-fl-oh]
renewable_carriers: [onwind, solar, solar-hsat, hydro]
Comment thread
daniel-rdt marked this conversation as resolved.
tyndp_renewable_carriers: [onwind, solar-pv-utility, solar-pv-rooftop, offwind-ac-fb-r, offwind-ac-fl-r, offwind-dc-fb-r, offwind-dc-fl-r, offwind-dc-fb-oh, offwind-dc-fl-oh, offwind-h2-fb-oh, offwind-h2-fl-oh]
Comment thread
daniel-rdt marked this conversation as resolved.

pecd_renewable_profiles:
enable: true
fill_gaps_method: zero
technologies:
Wind_Offshore:
- offwind-ac-fb-r
Expand All @@ -55,6 +56,12 @@ electricity:
- offwind-dc-fl-oh
- offwind-h2-fb-oh
- offwind-h2-fl-oh
LFSolarPVRooftop:
- solar-pv-rooftop
LFSolarPVUtility:
- solar-pv-utility
Wind_Onshore:
- onwind

estimate_renewable_capacities:
# NOTE: technologies that are covered by TYNDP renewable carriers need to be removed from estimation
Expand Down
11 changes: 9 additions & 2 deletions config/test/config.tyndp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,12 @@ electricity:
Store: [H2]
Link: [H2 pipeline]

renewable_carriers: [solar, solar-hsat, onwind]
tyndp_renewable_carriers: [offwind-ac-fb-r, offwind-ac-fl-r, offwind-dc-fb-r, offwind-dc-fl-r, offwind-dc-fb-oh, offwind-dc-fl-oh, offwind-h2-fb-oh, offwind-h2-fl-oh]
renewable_carriers: [onwind, solar, solar-hsat]
tyndp_renewable_carriers: [onwind, solar-pv-utility, solar-pv-rooftop, offwind-ac-fb-r, offwind-ac-fl-r, offwind-dc-fb-r, offwind-dc-fl-r, offwind-dc-fb-oh, offwind-dc-fl-oh, offwind-h2-fb-oh, offwind-h2-fl-oh]

pecd_renewable_profiles:
enable: true
fill_gaps_method: zero
technologies:
Wind_Offshore:
- offwind-ac-fb-r
Expand All @@ -59,6 +60,12 @@ electricity:
- offwind-dc-fl-oh
- offwind-h2-fb-oh
- offwind-h2-fl-oh
LFSolarPVRooftop:
- solar-pv-rooftop
LFSolarPVUtility:
- solar-pv-utility
Wind_Onshore:
- onwind

estimate_renewable_capacities:
# NOTE: technologies that are covered by TYNDP renewable carriers need to be removed from estimation
Expand Down
3 changes: 2 additions & 1 deletion doc/configtables/electricity.csv
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ conventional_carriers,--,"Any subset of {nuclear, oil, OCGT, CCGT, coal, lignite
renewable_carriers,--,"Any subset of {solar, onwind, offwind-ac, offwind-dc, offwind-float, hydro}",List of renewable generators to include in the model.
tyndp_renewable_carriers,--,"Any subset of {solar-pv, solar-pv-utility, solar-pv-rooftop, onwind, offwind-ac-fb-r, offwind-ac-fl-r, offwind-dc-fb-r, offwind-dc-fl-r, offwind-dc-fb-oh, offwind-dc-fl-oh, offwind-h2-fb-oh, offwind-h2-fl-oh}",List of TYNDP renewable generators to include in the model. Technologies covered by specified TYNDP renewable carriers need to be removed from `estimate_renewable_carriers` technology list.
pecd_renewable_profiles,,,
-- enable,,bool,Activate PECD renewable profiles from 2024 TYNDP instead of default renewable profiles for specified renewable technologies below. Technologies ``pecd_techs`` can be any of {CSP, LFSolarPV, Wind_Offshore, Wind_Onshore}.
-- enable,,bool,Activate PECD renewable profiles from 2024 TYNDP instead of default renewable profiles for specified renewable technologies below. Technologies ``pecd_techs`` can be any of {CSP, LFSolarPVUtility, LFSolarPVRooftop, Wind_Offshore, Wind_Onshore}.
-- fill_gaps_method,,str,The chosen method for filling gaps in the PECD data to the modelled nodes. Can be either `zero` to fill with zero values or any other aggregation method such as `mean`, `median`, `max` or similar.
-- technologies,,,
-- -- {pecd_tech},--,str,The PECD tech whose PECD profile is used. These PECD tech and their profiles are mapped to ``tyndp_renewable_carriers``.
-- -- -- {tyndp_renewable_carriers},--,str,The `tyndp_renewable_carriers` for which the PECD profiles must be used. All `tyndp_renewable_carriers` must be mapped to a PECD profile. Non-TYNDP renewable carriers use the default renewable profiles.
Expand Down
3 changes: 3 additions & 0 deletions rules/build_electricity.smk
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,9 @@ rule clean_pecd_data:
params:
snapshots=config_provider("snapshots"),
drop_leap_day=config_provider("enable", "drop_leap_day"),
fill_gaps_method=config_provider(
"electricity", "pecd_renewable_profiles", "fill_gaps_method"
),
input:
offshore_buses="data/tyndp_2024_bundle/Offshore hubs/NODE.xlsx",
onshore_buses=resources("busmap_base_s_all.csv"),
Expand Down
7 changes: 6 additions & 1 deletion scripts/add_existing_baseyear.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ def add_existing_renewables(

irena = irena.unstack().reset_index()

if not set(tech_map.keys()).intersection(renewable_carriers):
Comment thread
daniel-rdt marked this conversation as resolved.
Outdated
logger.info("No existing capacities to add for specified renewable carriers.")

Comment thread
daniel-rdt marked this conversation as resolved.
Outdated
for carrier, tech in tech_map.items():
if carrier not in renewable_carriers:
continue
Expand Down Expand Up @@ -154,7 +157,9 @@ def add_existing_renewables(
df_agg.at[name, "bus"] = bus
df_agg.at[name, "resource_class"] = bin_id

df_agg["resource_class"] = df_agg["resource_class"].fillna(0)
df_agg["resource_class"] = (
df_agg["resource_class"].fillna(0) if "resource_class" in df_agg.columns else 0
)
Comment thread
daniel-rdt marked this conversation as resolved.


def add_power_capacities_installed_before_baseyear(
Expand Down
36 changes: 24 additions & 12 deletions scripts/clean_pecd_data.py
Comment thread
daniel-rdt marked this conversation as resolved.
Comment thread
daniel-rdt marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
Loads and cleans the available PECD capacity factor generation time series based on PECD weather data.
The script is executed for a given technology, and planning horizon. Technologies can be one of:
Comment thread
daniel-rdt marked this conversation as resolved.
Outdated

* CSP_noStorage,
* CSP_withStorage,
* LFSolarPV,
* LFSolarPVRooftop,
* CSP
Comment thread
daniel-rdt marked this conversation as resolved.
Outdated
* LFSolarPVUtility,
* LFSolarPVRooftop,
* Wind_Offshore,
* Wind_Onshore.

Expand Down Expand Up @@ -46,6 +44,9 @@ def read_pecd_file(
):
fn = Path(dir_pecd, pyear, f"PECD_{technology}_{pyear}_{node}_edition 2023.2.csv")
Comment thread
daniel-rdt marked this conversation as resolved.
Outdated

# PECD only differentiates between utility and rooftop PV for some nodes
if not os.path.isfile(fn) and "LFSolarPV" in technology:
fn = Path(str(fn).replace(technology, "LFSolarPV"))
if not os.path.isfile(fn):
return None
Comment thread
daniel-rdt marked this conversation as resolved.

Comment thread
daniel-rdt marked this conversation as resolved.
Expand Down Expand Up @@ -97,19 +98,20 @@ def read_pecd_file(
# Planning year
pyear = str(snakemake.wildcards.planning_horizons)

# TODO: find solution for solar profiles being differentiated between Utility and Rooftop for Italy
# Technology as in PECD terminology
pecd_tech = snakemake.wildcards.technology

offshore_buses = pd.read_excel(snakemake.input.offshore_buses, index_col=0)
Comment thread
daniel-rdt marked this conversation as resolved.
onshore_buses = pd.read_csv(snakemake.input.onshore_buses, index_col=0)

nodes = (
offshore_buses.index if pecd_tech == "Wind_Offshore" else onshore_buses.index
offshore_buses.index
if pecd_tech == "Wind_Offshore"
else onshore_buses.index.str.replace("GB", "UK", regex=True)
Comment thread
daniel-rdt marked this conversation as resolved.
Outdated
)
dir_pecd = snakemake.input.dir_pecd

# Load and prep electricity demand
# Load and prep pecd data
tqdm_kwargs = {
"ascii": False,
"unit": " nodes",
Expand All @@ -127,16 +129,26 @@ def read_pecd_file(
)

with mp.Pool(processes=snakemake.threads) as pool:
demand = list(tqdm(pool.imap(func, nodes), **tqdm_kwargs))
pecd = list(tqdm(pool.imap(func, nodes), **tqdm_kwargs))

if all(data is None for data in pecd):
raise ValueError(
f"No PECD data found for {pecd_tech}. Please specify a technology covered within the TYNDP PECD data."
Comment thread
daniel-rdt marked this conversation as resolved.
Outdated
)
pecd_df = pd.concat(pecd, axis=1)
Comment thread
daniel-rdt marked this conversation as resolved.
fill_na = (
pd.Series(0.0, index=pecd_df.index)
Comment thread
daniel-rdt marked this conversation as resolved.
if snakemake.params.fill_gaps_method == "zero"
else pecd_df.agg(snakemake.params.fill_gaps_method, axis=1)
)
pecd_df = (
pd.concat(demand, axis=1)
.reindex(
nodes, axis=1, fill_value=0.0
) # include missing node data with empty columns
pecd_df.reindex(nodes, axis=1) # include missing node data with empty columns
.rename(
columns=lambda x: x.replace("UK", "GB")
) # replace UK with GB for naming convention
Comment thread
daniel-rdt marked this conversation as resolved.
Outdated
.where(
lambda df: df.notna(), fill_na, axis=0
) # fill missing node data with configured aggregation method
Comment thread
daniel-rdt marked this conversation as resolved.
)

pecd_df.to_csv(snakemake.output.pecd_data_clean)
Loading