Source code for egon.data.datasets.hydrogen_etrago.h2_to_ch4
# -*- coding: utf-8 -*-
"""
Module containing the definition of the links between H2 and CH4 buses
In this module the functions used to define and insert the links between
H2 and CH4 buses into the database are to be found.
These links are modelling:
* Methanisation (carrier name: 'H2_to_CH4'): technology to produce CH4
from H2
* H2_feedin: Injection of H2 into the CH4 grid
* Steam Methane Reaction (SMR, carrier name: 'CH4_to_H2'): techonology
to produce CH4 from H2
"""
from geoalchemy2.types import Geometry
from egon.data import db
from egon.data.datasets.etrago_helpers import copy_and_modify_links
from egon.data.datasets.etrago_setup import link_geom_from_buses
from egon.data.datasets.scenario_parameters import get_sector_parameters
[docs]def insert_h2_to_ch4_to_h2():
"""
Inserts methanisation, feedin and SMR links into the database
Define the potentials for methanisation and Steam Methane Reaction
(SMR) modelled as extendable links as well as the H2 feedin
capacities modelled as non extendable links and insert all of them
into the database.
These tree technologies are connecting CH4 and H2_grid buses only.
The capacity of the H2_feedin links is considerated as constant and
calculated as the sum of the capacities of the CH4 links connected
to the CH4 bus multiplied by the H2 energy share allowed to be fed in.
This share is calculated in the function :py:func:`H2_CH4_mix_energy_fractions`.
Returns
-------
None
"""
# Connect to local database
engine = db.engine()
scn_name = "eGon2035"
# Select CH4 and corresponding H2 buses
# No geometry required in this case!
buses = db.select_dataframe(
f"""
SELECT * FROM grid.egon_etrago_ch4_h2 WHERE scn_name = '{scn_name}'
"""
)
methanation = buses.copy().rename(
columns={"bus_H2": "bus0", "bus_CH4": "bus1"}
)
SMR = buses.copy().rename(columns={"bus_H2": "bus1", "bus_CH4": "bus0"})
feed_in = methanation.copy()
# Delete old entries
db.execute_sql(
f"""
DELETE FROM grid.egon_etrago_link WHERE "carrier" IN
('H2_to_CH4', 'H2_feedin', 'CH4_to_H2') AND scn_name = '{scn_name}'
AND bus0 NOT IN (
SELECT bus_id FROM grid.egon_etrago_bus
WHERE scn_name = '{scn_name}' AND country != 'DE'
) AND bus1 NOT IN (
SELECT bus_id FROM grid.egon_etrago_bus
WHERE scn_name = '{scn_name}' AND country != 'DE'
);
"""
)
scn_params = get_sector_parameters("gas", scn_name)
pipeline_capacities = db.select_dataframe(
f"""
SELECT bus0, bus1, p_nom FROM grid.egon_etrago_link
WHERE scn_name = '{scn_name}' AND carrier = 'CH4'
AND (
bus0 IN (
SELECT bus_id FROM grid.egon_etrago_bus
WHERE scn_name = '{scn_name}' AND country = 'DE'
) OR bus1 IN (
SELECT bus_id FROM grid.egon_etrago_bus
WHERE scn_name = '{scn_name}' AND country = 'DE'
)
);
"""
)
feed_in["p_nom"] = 0
feed_in["p_nom_extendable"] = False
# calculation of H2 energy share via volumetric share outsourced
# in a mixture of H2 and CH4 with 15 %vol share
H2_share = scn_params["H2_feedin_volumetric_fraction"]
H2_energy_share = H2_CH4_mix_energy_fractions(H2_share)
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
feed_in.loc[feed_in["bus1"] == bus, "p_nom"] = (
nodal_capacity * H2_energy_share
)
# Write new entries
for table, carrier in zip(
[methanation, SMR, feed_in], ["H2_to_CH4", "CH4_to_H2", "H2_feedin"]
):
# set parameters according to carrier name
table["carrier"] = carrier
table["efficiency"] = scn_params["efficiency"][carrier]
if carrier != "H2_feedin":
table["p_nom_extendable"] = True
table["capital_cost"] = scn_params["capital_cost"][carrier]
table["lifetime"] = scn_params["lifetime"][carrier]
new_id = db.next_etrago_id("link")
table["link_id"] = range(new_id, new_id + len(table))
table = link_geom_from_buses(table, scn_name)
table.to_postgis(
"egon_etrago_link",
engine,
schema="grid",
index=False,
if_exists="append",
dtype={"topo": Geometry()},
)
[docs]def insert_h2_to_ch4_eGon100RE():
"""Copy H2/CH4 links from the eGon2035 to the eGon100RE scenario."""
copy_and_modify_links(
"eGon2035", "eGon100RE", ["H2_to_CH4", "CH4_to_H2"], "gas"
)
[docs]def H2_CH4_mix_energy_fractions(x, T=25, p=50):
"""
Calculate the fraction of H2 with respect to energy in a H2 CH4 mixture.
Given the volumetric fraction of H2 in a H2 and CH4 mixture, the fraction
of H2 with respect to energy is calculated with the ideal gas mixture law.
Beware, that changing the fraction of H2 changes the overall energy within
a specific volume of the mixture. If H2 is fed into CH4, the pipeline
capacity (based on energy) therefore decreases if the volumetric flow
does not change. This effect is neglected in eGon. At 15 vol% H2 the
decrease in capacity equals about 10 % if volumetric flow does not change.
Parameters
----------
x : float
Volumetric fraction of H2 in the mixture
T : int, optional
Temperature of the mixture in °C, by default 25
p : int, optional
Pressure of the mixture in bar, by default 50
Returns
-------
float
Fraction of H2 in mixture with respect to energy (LHV)
"""
# molar masses
M_H2 = 0.00201588
M_CH4 = 0.0160428
# universal gas constant (fluid independent!)
R_u = 8.31446261815324
# individual gas constants
R_H2 = R_u / M_H2
R_CH4 = R_u / M_CH4
# volume is fixed: 1m^3, use ideal gas law at 25 °C, 50 bar
V = 1
T += 273.15
p *= 1e5
# volumetric shares of gases (specify share of H2)
V_H2 = x
V_CH4 = 1 - x
# calculate data of mixture
M_mix = V_H2 * M_H2 + V_CH4 * M_CH4
R_mix = R_u / M_mix
m_mix = p * V / (R_mix * T)
# calulate masses with volumetric shares at mixture pressure
m_H2 = p * V_H2 / (R_H2 * T)
m_CH4 = p * V_CH4 / (R_CH4 * T)
msg = (
"Consistency check faild, individual masses are not equal to sum of "
"masses. Residual is: " + str(m_mix - m_H2 - m_CH4)
)
assert round(m_mix - m_H2 - m_CH4, 6) == 0.0, msg
LHV = {"CH4": 50e6, "H2": 120e6}
return m_H2 * LHV["H2"] / (m_H2 * LHV["H2"] + m_CH4 * LHV["CH4"])