Passed
Pull Request — dev (#936)
by
unknown
01:44
created

data.datasets.gas_stores_germany   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 336
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 16
eloc 146
dl 0
loc 336
rs 10
c 0
b 0
f 0

4 Functions

Rating   Name   Duplication   Size   Complexity  
B import_installed_ch4_storages() 0 116 4
B import_gas_grid_capacity() 0 64 7
A insert_gas_stores_DE() 0 18 1
A insert_gas_stores_germany() 0 84 3

1 Method

Rating   Name   Duplication   Size   Complexity  
A GasStores.__init__() 0 6 1
1
# -*- coding: utf-8 -*-
2
"""
3
The central module containing all code dealing with importing gas stores
4
5
In this module, the non extendable H2 and CH4 stores in Germany are
6
defined and inserted to the database.
7
8
Dependecies (pipeline)
9
======================
10
* :dataset: GasAreaseGon2035, HydrogenBusEtrago, GasAreaseGon100RE
11
12
Resulting tables
13
================
14
* grid.egon_etrago_store is completed
15
16
"""
17
from pathlib import Path
18
from telnetlib import GA
19
import ast
20
21
import geopandas
22
import numpy as np
23
import pandas as pd
24
25
from egon.data import config, db
26
from egon.data.config import settings
27
from egon.data.datasets import Dataset
28
from egon.data.datasets.gas_grid import (
29
    ch4_nodes_number_G,
30
    define_gas_nodes_list,
31
)
32
from egon.data.datasets.scenario_parameters import get_sector_parameters
33
34
35
class GasStores(Dataset):
36
    "Insert the non extendable gas stores in Germany in the database"
37
38
    def __init__(self, dependencies):
39
        super().__init__(
40
            name="GasStores",
41
            version="0.0.3",
42
            dependencies=dependencies,
43
            tasks=(insert_gas_stores_DE),
44
        )
45
46
47
def import_installed_ch4_storages(scn_name):
48
    """Define list of CH4 stores (caverns) from the SciGRID_gas data
49
50
    This function define the dataframe containing the CH4 cavern stores
51
    in Germany from the SciGRID_gas data for both scenarios.
52
53
    Parameters
54
    ----------
55
    scn_name : str
56
        Name of the scenario
57
58
    Returns
59
    -------
60
    Gas_storages_list :
61
        Dataframe containing the CH4 cavern stores units in Germany
62
63
    """
64
    target_file = (
65
        Path(".") / "datasets" / "gas_data" / "data" / "IGGIELGN_Storages.csv"
66
    )
67
68
    Gas_storages_list = pd.read_csv(
69
        target_file,
70
        delimiter=";",
71
        decimal=".",
72
        usecols=["lat", "long", "country_code", "param"],
73
    )
74
75
    Gas_storages_list = Gas_storages_list[
76
        Gas_storages_list["country_code"].str.match("DE")
77
    ]
78
79
    # Define new columns
80
    max_workingGas_M_m3 = []
81
    NUTS1 = []
82
    end_year = []
83
    for index, row in Gas_storages_list.iterrows():
84
        param = ast.literal_eval(row["param"])
85
        NUTS1.append(param["nuts_id_1"])
86
        end_year.append(param["end_year"])
87
        max_workingGas_M_m3.append(param["max_workingGas_M_m3"])
88
89
    Gas_storages_list = Gas_storages_list.assign(NUTS1=NUTS1)
90
91
    # Calculate e_nom
92
    conv_factor = 10830  # gross calorific value = 39 MJ/m3 (eurogas.org)
93
    Gas_storages_list["e_nom"] = [conv_factor * i for i in max_workingGas_M_m3]
94
95
    end_year = [float("inf") if x == None else x for x in end_year]
96
    Gas_storages_list = Gas_storages_list.assign(end_year=end_year)
97
98
    # Cut data to federal state if in testmode
99
    boundary = settings()["egon-data"]["--dataset-boundary"]
100
    if boundary != "Everything":
101
        map_states = {
102
            "Baden-Württemberg": "DE1",
103
            "Nordrhein-Westfalen": "DEA",
104
            "Hessen": "DE7",
105
            "Brandenburg": "DE4",
106
            "Bremen": "DE5",
107
            "Rheinland-Pfalz": "DEB",
108
            "Sachsen-Anhalt": "DEE",
109
            "Schleswig-Holstein": "DEF",
110
            "Mecklenburg-Vorpommern": "DE8",
111
            "Thüringen": "DEG",
112
            "Niedersachsen": "DE9",
113
            "Sachsen": "DED",
114
            "Hamburg": "DE6",
115
            "Saarland": "DEC",
116
            "Berlin": "DE3",
117
            "Bayern": "DE2",
118
        }
119
120
        Gas_storages_list = Gas_storages_list[
121
            Gas_storages_list["NUTS1"].isin([map_states[boundary], np.nan])
122
        ]
123
124
    # Remove unused storage units
125
    Gas_storages_list = Gas_storages_list[
126
        Gas_storages_list["end_year"] >= 2035
127
    ]
128
129
    Gas_storages_list = Gas_storages_list.rename(
130
        columns={"lat": "y", "long": "x"}
131
    )
132
    Gas_storages_list = geopandas.GeoDataFrame(
133
        Gas_storages_list,
134
        geometry=geopandas.points_from_xy(
135
            Gas_storages_list["x"], Gas_storages_list["y"]
136
        ),
137
    )
138
    Gas_storages_list = Gas_storages_list.rename(
139
        columns={"geometry": "geom"}
140
    ).set_geometry("geom", crs=4326)
141
142
    # Match to associated gas bus
143
    Gas_storages_list = Gas_storages_list.reset_index(drop=True)
144
    Gas_storages_list = db.assign_gas_bus_id(
145
        Gas_storages_list, scn_name, "CH4"
146
    )
147
148
    # Remove useless columns
149
    Gas_storages_list = Gas_storages_list.drop(
150
        columns=[
151
            "x",
152
            "y",
153
            "param",
154
            "country_code",
155
            "NUTS1",
156
            "end_year",
157
            "geom",
158
            "bus_id",
159
        ]
160
    )
161
162
    return Gas_storages_list
163
164
165
def import_gas_grid_capacity(scn_name, carrier):
166
    """Define the gas stores modelling the store capacity of the grid
167
168
    Define dataframe containing the modelling of the grid storage
169
    capacity. The whole storage capacity of the grid (130000 MWh,
170
    estimation of the Bundesnetzagentur) is split uniformly between
171
    all the german gas nodes of the grid (without consideration of the
172
    capacities of the pipes).
173
    In eGon100RE, the storage capacity of the grid is split between H2
174
    and CH4 stores, with the same share than the pipes capacity (value
175
    calculated in the p-e-s run).
176
177
    Parameters
178
    ----------
179
    scn_name : str
180
        Name of the scenario
181
    carrier : str
182
        Name of the carrier
183
184
    Returns
185
    -------
186
    Gas_storages_list :
187
        List of gas stores in Germany modelling the gas grid storage capacity
188
189
    """
190
    scn_params = get_sector_parameters("gas", scn_name)
191
    # Select source from dataset configuration
192
    source = config.datasets()["gas_stores"]["source"]
193
194
    Gas_grid_capacity = 130000  # Storage capacity of the CH4 grid - G.Volk "Die Herauforderung an die Bundesnetzagentur die Energiewende zu meistern" Berlin, Dec 2012
195
    N_ch4_nodes_G = ch4_nodes_number_G(
196
        define_gas_nodes_list()
197
    )  # Number of nodes in Germany
198
    Store_capacity = (
199
        Gas_grid_capacity / N_ch4_nodes_G
200
    )  # Storage capacity associated to each CH4 node of the german grid
201
202
    sql_gas = f"""SELECT bus_id, geom
203
                FROM {source['buses']['schema']}.{source['buses']['table']}
204
                WHERE carrier = '{carrier}' AND scn_name = '{scn_name}'
205
                AND country = 'DE';"""
206
    Gas_storages_list = db.select_geodataframe(sql_gas, epsg=4326)
207
208
    # Add missing column
209
    Gas_storages_list["bus"] = Gas_storages_list["bus_id"]
210
211
    if scn_name == "eGon100RE" and carrier == "CH4":
212
        Gas_storages_list["e_nom"] = Store_capacity * (
213
            1
214
            - get_sector_parameters("gas", scn_name)[
215
                "retrofitted_CH4pipeline-to-H2pipeline_share"
216
            ]
217
        )
218
    elif scn_name == "eGon2035" and carrier == "CH4":
219
        Gas_storages_list["e_nom"] = Store_capacity
220
    elif scn_name == "eGon100RE" and carrier == "H2_grid":
221
        Gas_storages_list["e_nom"] = Store_capacity * (
222
            scn_params["retrofitted_CH4pipeline-to-H2pipeline_share"]
223
        )
224
225
    # Remove useless columns
226
    Gas_storages_list = Gas_storages_list.drop(columns=["bus_id", "geom"])
227
228
    return Gas_storages_list
229
230
231
def insert_gas_stores_germany(scn_name, carrier):
232
    """Insert gas stores for specific scenario
233
234
    Insert non extendable gas stores for specific scenario in Germany
235
    by executing the following steps:
236
      * Clean the database
237
      * For CH4 stores, call the functions
238
        :py:func:`import_installed_ch4_storages` to receive the CH4
239
        cavern stores and :py:func:`import_gas_grid_capacity` to
240
        receive the CH4 stores modelling the storage capacity of the
241
        grid.
242
      * For H2 stores, call only the function
243
        :py:func:`import_gas_grid_capacity` to receive the H2 stores
244
        modelling the storage capacity of the grid.
245
      * Aggregate of the stores attached to the same bus
246
      * Add the missing columns: store_id, scn_name, carrier, e_cyclic
247
      * Insert the stores in the database
248
249
    Parameters
250
    ----------
251
    scn_name : str
252
        Name of the scenario
253
    carrier: str
254
        Name of the carrier
255
256
    Returns
257
    -------
258
    None
259
260
    """
261
    # Connect to local database
262
    engine = db.engine()
263
264
    # Select target from dataset configuration
265
    source = config.datasets()["gas_stores"]["source"]
266
    target = config.datasets()["gas_stores"]["target"]
267
268
    # Clean table
269
    db.execute_sql(
270
        f"""
271
        DELETE FROM {target['stores']['schema']}.{target['stores']['table']}  
272
        WHERE "carrier" = '{carrier}'
273
        AND scn_name = '{scn_name}'
274
        AND bus IN (
275
            SELECT bus_id FROM {source['buses']['schema']}.{source['buses']['table']}
276
            WHERE scn_name = '{scn_name}' 
277
            AND country = 'DE'
278
            );
279
        """
280
    )
281
282
    if carrier == "CH4":
283
        gas_storages_list = pd.concat(
284
            [
285
                import_installed_ch4_storages(scn_name),
286
                import_gas_grid_capacity(scn_name, carrier),
287
            ]
288
        )
289
    elif carrier == "H2":
290
        gas_storages_list = import_gas_grid_capacity(scn_name, "H2_grid")
291
292
    # Aggregate ch4 stores with same properties at the same bus
293
    gas_storages_list = (
294
        gas_storages_list.groupby(["bus"])
0 ignored issues
show
introduced by
The variable gas_storages_list does not seem to be defined for all execution paths.
Loading history...
295
        .agg({"e_nom": "sum"})
296
        .reset_index(drop=False)
297
    )
298
299
    # Add missing columns
300
    c = {"scn_name": scn_name, "carrier": carrier, "e_cyclic": True}
301
    gas_storages_list = gas_storages_list.assign(**c)
302
303
    new_id = db.next_etrago_id("store")
304
    gas_storages_list["store_id"] = range(
305
        new_id, new_id + len(gas_storages_list)
306
    )
307
308
    # Insert data to db
309
    gas_storages_list.to_sql(
310
        target["stores"]["table"],
311
        engine,
312
        schema=target["stores"]["schema"],
313
        index=False,
314
        if_exists="append",
315
    )
316
317
318
def insert_gas_stores_DE():
319
    """Overall function to import non extendable gas stores in Germany
320
321
    This function calls :py:func:`insert_gas_stores_germany` three
322
    times to insert the corresponding non extendable gas stores in the
323
    database:
324
      * The CH4 stores for eGon2035: caverns from SciGRID_gas data and
325
        modelling of the storage grid capacity
326
      * The CH4 stores for eGon100RE: caverns from SciGRID_gas data and
327
        modelling of the storage grid capacity (split with H2)
328
      * The H2 stores for eGon100RE: caverns from SciGRID_gas data and
329
        modelling of the storage grid capacity (split with CH4)
330
    This function has no return.
331
332
    """
333
    insert_gas_stores_germany("eGon2035", "CH4")
334
    insert_gas_stores_germany("eGon100RE", "CH4")
335
    insert_gas_stores_germany("eGon100RE", "H2")
336