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

data.datasets.gas_stores_germany   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 337
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 16
eloc 147
dl 0
loc 337
rs 10
c 0
b 0
f 0

4 Functions

Rating   Name   Duplication   Size   Complexity  
B import_gas_grid_capacity() 0 65 7
B import_installed_ch4_storages() 0 116 4
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.
172
    In eGon100RE, the storage capacity of the grid is slip between H2
173
    and CH4 stores, with the same share than the pipes capacity (value
174
    calculated in the p-e-s run).
175
    The capacities of the pipes are not considerated.
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
            * scn_params["retrofitted_capacity_share"]
224
        )
225
226
    # Remove useless columns
227
    Gas_storages_list = Gas_storages_list.drop(columns=["bus_id", "geom"])
228
229
    return Gas_storages_list
230
231
232
def insert_gas_stores_germany(scn_name, carrier):
233
    """Insert gas stores for specific scenario
234
235
    Insert non extendable gas stores for specific scenario in Germany
236
    by executing the following steps:
237
      * Clean the database
238
      * For CH4 stores, call the functions
239
        :py:func:`import_installed_ch4_storages` to receive the CH4
240
        cavern stores and :py:func:`import_gas_grid_capacity` to
241
        receive the CH4 stores modelling the storage capacity of the
242
        grid.
243
      * For H2 stores, call only the function
244
        :py:func:`import_gas_grid_capacity` to receive the H2 stores
245
        modelling the storage capacity of the grid.
246
      * Aggregate of the stores attached to the same bus
247
      * Add the missing columns: store_id, scn_name, carrier, e_cyclic
248
      * Insert the stores in the database
249
250
    Parameters
251
    ----------
252
    scn_name : str
253
        Name of the scenario
254
    carrier: str
255
        Name of the carrier
256
257
    Returns
258
    -------
259
    None
260
261
    """
262
    # Connect to local database
263
    engine = db.engine()
264
265
    # Select target from dataset configuration
266
    source = config.datasets()["gas_stores"]["source"]
267
    target = config.datasets()["gas_stores"]["target"]
268
269
    # Clean table
270
    db.execute_sql(
271
        f"""
272
        DELETE FROM {target['stores']['schema']}.{target['stores']['table']}  
273
        WHERE "carrier" = '{carrier}'
274
        AND scn_name = '{scn_name}'
275
        AND bus IN (
276
            SELECT bus_id FROM {source['buses']['schema']}.{source['buses']['table']}
277
            WHERE scn_name = '{scn_name}' 
278
            AND country = 'DE'
279
            );
280
        """
281
    )
282
283
    if carrier == "CH4":
284
        gas_storages_list = pd.concat(
285
            [
286
                import_installed_ch4_storages(scn_name),
287
                import_gas_grid_capacity(scn_name, carrier),
288
            ]
289
        )
290
    elif carrier == "H2":
291
        gas_storages_list = import_gas_grid_capacity(scn_name, "H2_grid")
292
293
    # Aggregate ch4 stores with same properties at the same bus
294
    gas_storages_list = (
295
        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...
296
        .agg({"e_nom": "sum"})
297
        .reset_index(drop=False)
298
    )
299
300
    # Add missing columns
301
    c = {"scn_name": scn_name, "carrier": carrier, "e_cyclic": True}
302
    gas_storages_list = gas_storages_list.assign(**c)
303
304
    new_id = db.next_etrago_id("store")
305
    gas_storages_list["store_id"] = range(
306
        new_id, new_id + len(gas_storages_list)
307
    )
308
309
    # Insert data to db
310
    gas_storages_list.to_sql(
311
        target["stores"]["table"],
312
        engine,
313
        schema=target["stores"]["schema"],
314
        index=False,
315
        if_exists="append",
316
    )
317
318
319
def insert_gas_stores_DE():
320
    """Overall function to import non extendable gas stores in Germany
321
322
    This function calls :py:func:`insert_gas_stores_germany` three
323
    times to insert the corresponding non extendable gas stores in the
324
    database:
325
      * The CH4 stores for eGon2035: caverns from SciGRID_gas data and
326
        modelling of the storage grid capacity
327
      * The CH4 stores for eGon100RE: caverns from SciGRID_gas data and
328
        modelling of the storage grid capacity (split with H2)
329
      * The H2 stores for eGon100RE: caverns from SciGRID_gas data and
330
        modelling of the storage grid capacity (split with CH4)
331
    This function has no return.
332
333
    """
334
    insert_gas_stores_germany("eGon2035", "CH4")
335
    insert_gas_stores_germany("eGon100RE", "CH4")
336
    insert_gas_stores_germany("eGon100RE", "H2")
337