diff --git a/README.md b/README.md index 85525911a2..cd53dd0782 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ While multiple TYNDP features are already introduced to the Open-TYNDP model, th |:------------------------------------------------------:|:-------------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:------:| | **Visualizations and workflow automation** | Automated workflow | | ✅ | | | TYNDP plotting routines | [#443](https://github.com/open-energy-transition/open-tyndp/pull/443) | 🔨 | -| **Automated tests and benchmarks** | Automated benchmarking routine | [#73](https://github.com/open-energy-transition/open-tyndp/pull/73), [#117](https://github.com/open-energy-transition/open-tyndp/pull/117), [#281](https://github.com/open-energy-transition/open-tyndp/pull/281), [#467](https://github.com/open-energy-transition/open-tyndp/pull/467), [#543](https://github.com/open-energy-transition/open-tyndp/pull/543), [#574](https://github.com/open-energy-transition/open-tyndp/pull/574), [#607](https://github.com/open-energy-transition/open-tyndp/pull/607), [#615](https://github.com/open-energy-transition/open-tyndp/pull/615) | ✅ | +| **Automated tests and benchmarks** | Automated benchmarking routine | [#73](https://github.com/open-energy-transition/open-tyndp/pull/73), [#117](https://github.com/open-energy-transition/open-tyndp/pull/117), [#281](https://github.com/open-energy-transition/open-tyndp/pull/281), [#467](https://github.com/open-energy-transition/open-tyndp/pull/467), [#543](https://github.com/open-energy-transition/open-tyndp/pull/543), [#574](https://github.com/open-energy-transition/open-tyndp/pull/574), [#607](https://github.com/open-energy-transition/open-tyndp/pull/607), [#615](https://github.com/open-energy-transition/open-tyndp/pull/615), [#604](https://github.com/open-energy-transition/open-tyndp/pull/604) | ✅ | | **TYNDP modelling features** | Perfect foresight optimization | | ⌛ | | | Security of Supply (SoS) loop | | ⌛ | | **Existing infrastructure and associated parameters** | Electricity reference grid | [#18](https://github.com/open-energy-transition/open-tyndp/pull/18), [#340](https://github.com/open-energy-transition/open-tyndp/pull/340), [#489](https://github.com/open-energy-transition/open-tyndp/pull/489), [#496](https://github.com/open-energy-transition/open-tyndp/pull/496), [#527](https://github.com/open-energy-transition/open-tyndp/pull/527) | ✅ | diff --git a/doc/index.rst b/doc/index.rst index 96484ef7c1..2963cade87 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -173,7 +173,7 @@ While multiple TYNDP features are already introduced to the Open-TYNDP model, th - 🔨 * - **Automated tests and benchmarks** - Automated benchmarking routine - - `#73 `__, `#117 `__, `#281 `__, `#467 `__, `#543 `__, `#574 `__, `#607 `__, `#615 `__ + - `#73 `__, `#117 `__, `#281 `__, `#467 `__, `#543 `__, `#574 `__, `#607 `__, `#615 `__, `#604 `__ - ✅ * - **TYNDP modelling features** - Perfect foresight optimization diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 902d60889f..c30a84c82f 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -23,11 +23,14 @@ Upcoming Open-TYNDP Release * Disable OCGT as an extendable carrier and add load shedding for H2 and AC (https://github.com/open-energy-transition/open-tyndp/pull/547). +* Add imports to H2 MM supply benchmark (https://github.com/open-energy-transition/open-tyndp/pull/604). + * Add separate solver option for CBA MSV extraction (`cba.msv_extraction.solving`) and move CBA solve logs to `results/cba/logs/` (https://github.com/open-energy-transition/open-tyndp/pull/627). **Bugfixes and Compatibility** * Improve EU-wide prices with Pan-European values (https://github.com/open-energy-transition/open-tyndp/pull/607). + * Fix flows in balance maps (https://github.com/open-energy-transition/open-tyndp/pull/608). * Adjust ``build_statistics`` to be compatible with not modelling the electricity distribution grid with low voltage buses (https://github.com/open-energy-transition/open-tyndp/pull/634). diff --git a/scripts/sb/clean_tyndp_output_benchmark.py b/scripts/sb/clean_tyndp_output_benchmark.py index 8f279abe1e..edb62a61ca 100644 --- a/scripts/sb/clean_tyndp_output_benchmark.py +++ b/scripts/sb/clean_tyndp_output_benchmark.py @@ -490,6 +490,58 @@ def clean_MM_data_for_benchmarking( return MM_data +def clean_h2_imports_for_benchmarking( + crossborder_h2: pd.DataFrame, + eu27: list[str], +) -> pd.DataFrame: + """ + Extracts H2 imports from external nodes/buses for hydrogen supply benchmarking. + + Filters crossborder H2 exchanges where bus0 starts with "X" + and maps them to benchmark carriers: + - XAmmonia: "ammonia imports" + - Other X-nodes (eg. XDZ): "imports (renewable & low carbon)" + + Parameters + ---------- + crossborder_h2 : pd.DataFrame + H2 crossborder data from load_crossborder_sheet(), with row index + [avg, bus0, bus1, max, min, sum] and border names as columns. + eu27 : list[str] + List of EU27 country codes (2-letter ISO). + + Returns + ------- + pd.DataFrame + dataFrame with columns [carrier, bus, unit, table, value] for each importing country and an EU27 aggregated row. + """ + df = ( + crossborder_h2.loc[["bus0", "bus1", "sum"]] + .rename(index={"bus0": "carrier", "bus1": "bus", "sum": "value"}) + .T.query("carrier.str.startswith('X', na=False)") + .assign( + carrier=lambda x: np.where( + x.carrier == "XAmmonia", + "ammonia imports", + "imports (renewable & low carbon)", + ), + unit=crossborder_h2.loc["sum", "unit"], + bus=lambda df: df.bus + " H2", + table="hydrogen_supply", + ) + .reset_index(drop=True) + ) + + df_eu27 = ( + df[df["bus"].str.extract(r"^(?:IB)?(.{2})")[0].isin(eu27)] + .groupby("carrier")["value"] + .sum() + .reset_index() + .assign(bus="EU27", unit="MWh", table="hydrogen_supply") + ) + return pd.concat([df, df_eu27], ignore_index=True) + + def clean_crossborder_for_benchmarking(df: pd.DataFrame) -> pd.DataFrame: """ Clean crossborder data for benchmarking purposes. @@ -601,6 +653,12 @@ def assign_meta_data(df, planning_horizon, scenario): MM_data = pd.concat([MM_data, clean_crossborder_for_benchmarking(crossborder_agg)]) + # concatenate crossborder H2 imports to MM data for benchmarking + MM_data = pd.concat( + [MM_data, clean_h2_imports_for_benchmarking(crossborder["H2"], eu27)], + ignore_index=True, + ) + # load h2 demand time series logger.info("Processing hourly H2 demand tables") snapshots = get_snapshots(