diff --git a/etrago/appl.py b/etrago/appl.py old mode 100644 new mode 100755 index 7693bf8d1..e0b747e97 --- a/etrago/appl.py +++ b/etrago/appl.py @@ -76,6 +76,7 @@ # Scenario variations: "scn_extension": None, # None or array of extension scenarios "scn_decommissioning": None, # None or decommissioning scenario + "H2_vol_share": 15, # in % [50/20/15/10/5/2/1/0] allowed H2 volumetric share for feedin # Export options: "lpfile": False, # save pyomo's lp file: False or /path/to/lpfile.lp "csv_export": "results", # save results as csv: False or /path/tofolder @@ -249,6 +250,13 @@ def run_etrago(args, json_path): 'nep2035_b2' includes all lines that will be replaced in NEP-scenario 2035 B2 + H2_vol_share : int + 15, + Allowed H2 volumetric share of the CH4 loads that could be fed + into the CH4 grid if H2_feedin links are present in the network + Possible values are: [50/20/15/10/5/2/1/0] + If 0 is set, the H2_feedin links are deleted of the network. + lpfile : obj False, State if and where you want to save pyomo's lp file. Options: diff --git a/etrago/args.json b/etrago/args.json index 08f707c58..5d802f1e2 100644 --- a/etrago/args.json +++ b/etrago/args.json @@ -19,6 +19,7 @@ "scn_name": "eGon2035", "scn_extension": null, "scn_decommissioning": null, + "H2_vol_share": 15, "lpfile": false, "csv_export": "results", "extendable": { diff --git a/etrago/cluster/gas.py b/etrago/cluster/gas.py old mode 100644 new mode 100755 index 74f2518f6..d497d957c --- a/etrago/cluster/gas.py +++ b/etrago/cluster/gas.py @@ -16,11 +16,14 @@ busmap_by_kmeans, ) from six import iteritems + import numpy as np + import pandas as pd + import pypsa.io as io from etrago.cluster.spatial import ( - sum_with_inf, group_links, kmedoids_dijkstra_clustering, + sum_with_inf, ) from etrago.tools.utilities import * @@ -317,31 +320,67 @@ def gas_postprocessing(etrago, busmap, medoid_idx=None): network_gasgrid_c ) - # Overwrite p_nom of links with carrier "H2_feedin" (eGon2035 only) - if etrago.args["scn_name"] == "eGon2035": - H2_energy_share = 0.05053 # H2 energy share via volumetric share outsourced in a mixture of H2 and CH4 with 15 %vol share - feed_in = network_gasgrid_c.links.loc[ - network_gasgrid_c.links.carrier == "H2_feedin" - ] - pipeline_capacities = network_gasgrid_c.links.loc[ - network_gasgrid_c.links.carrier == "CH4" + # Overwrite p_nom of links with carrier "H2_feedin" + if "H2_feedin" in network_gasgrid_c.links.carrier.to_list(): + + H2_vol_share = etrago.args["H2_vol_share"] + + def att_H2_energy_share(H2_vol_share): + """ + Return the fraction of H2 with respect to energy in a H2 CH4 mixture + + The calculation of the values in the dictionary has been + made using the function H2_CH4_mix_energy_fractions of + https://github.com/openego/eGon-data/blob/dev/src/egon/data/datasets/hydrogen_etrago/h2_to_ch4.py + with T=25 (°C) and p=50 (bar). + + Parameters + ---------- + H2_vol_share : float + Volumetric fraction of H2 in the mixture + + Returns + ------- + H2_vol2en[H2_vol_share] : float + Fraction of H2 in mixture with respect to energy (LHV) + + """ + H2_vol2en = { + 1: 0.00304, + 2: 0.00612, + 5: 0.01562, + 10: 0.03242, + 15: 0.05053, + 20: 0.07011, + 50: 0.23170, + } + return H2_vol2en[H2_vol_share] + + rel_ch4_loads_carriers = ["rural_gas_boiler", "CH4_for_industry"] + ch4_loads = network_gasgrid_c.loads.loc[ + network_gasgrid_c.loads.carrier.isin(rel_ch4_loads_carriers) ] - for bus in feed_in["bus1"].values: - # calculate the total pipeline capacity connected to a specific bus - nodal_capacity = pipeline_capacities.loc[ - (pipeline_capacities["bus0"] == bus) - | (pipeline_capacities["bus1"] == bus), - "p_nom", - ].sum() - # multiply total pipeline capacity with H2 energy share corresponding to volumetric share + for bus in ch4_loads["bus"].unique(): + # Calculate the sum of the CH4 loads at each CH4 bus (this sum is a time series) + load_names = ch4_loads.loc[ch4_loads["bus"].values == bus].index + ch4_loads_set = network_gasgrid_c.loads_t.p_set.loc[ + :, load_names + ].sum(axis=1) + # Overwrite the "p_nom" values of the H2_link with a share of the CH4 total load + feedin_link = network_gasgrid_c.links.loc[ + (network_gasgrid_c.links["carrier"].values == "H2_feedin") + & (network_gasgrid_c.links["bus1"].values == bus) + ] + # p_nom is the max of the share of the CH4 total load network_gasgrid_c.links.loc[ - (network_gasgrid_c.links["bus1"].values == bus) - & (network_gasgrid_c.links["carrier"].values == "H2_feedin"), - "p_nom", - ] = ( - nodal_capacity * H2_energy_share - ) + feedin_link.index, "p_nom" + ] = ch4_loads_set.max() * att_H2_energy_share(H2_vol_share) + # and p_max_pu the time serie of the total CH4 load, normalized by its max value + network_gasgrid_c.links_t.p_max_pu.loc[ + ch4_loads_set.index, feedin_link.index + ] = (ch4_loads_set / ch4_loads_set.max()) + # Insert components not related to the gas clustering other_components = ["Line", "StorageUnit", "ShuntImpedance", "Transformer"] diff --git a/etrago/tools/network.py b/etrago/tools/network.py old mode 100644 new mode 100755 index fa215352e..598cf5284 --- a/etrago/tools/network.py +++ b/etrago/tools/network.py @@ -70,6 +70,7 @@ convert_capital_costs, crossborder_capacity, delete_dispensable_ac_buses, + delete_h2_feedin, drop_sectors, export_to_csv, filter_links_by_carrier, @@ -281,6 +282,8 @@ def __init__( delete_dispensable_ac_buses = delete_dispensable_ac_buses + delete_h2_feedin = delete_h2_feedin + get_clustering_data = get_clustering_data adjust_CH4_gen_carriers = adjust_CH4_gen_carriers @@ -367,5 +370,7 @@ def adjust_network(self): self.delete_dispensable_ac_buses() + self.delete_h2_feedin() + def _ts_weighted(self, timeseries): return timeseries.mul(self.network.snapshot_weightings, axis=0) diff --git a/etrago/tools/utilities.py b/etrago/tools/utilities.py index 36cedb51c..0a29286d4 100755 --- a/etrago/tools/utilities.py +++ b/etrago/tools/utilities.py @@ -1162,6 +1162,15 @@ def count(bus): return +def delete_h2_feedin(self): + """Delete H2_feedin links if H2_vol_share = 0""" + + if self.args["H2_vol_share"] == 0: + self.network.links = self.network.links[ + self.network.links.carrier != "H2_feedin" + ] + + def set_line_costs(self, cost110=230, cost220=290, cost380=85, costDC=375): """Set capital costs for extendable lines in respect to PyPSA [€/MVA]