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

data.datasets.gas_neighbours.eGon100RE   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 450
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 20
eloc 188
dl 0
loc 450
rs 10
c 0
b 0
f 0

6 Functions

Rating   Name   Duplication   Size   Complexity  
A calculate_crossbordering_gas_grid_capacities_eGon100RE() 0 62 3
D define_DE_crossbording_pipes_geom_eGon100RE() 0 159 11
A insert_biogas_generators_abroad() 0 40 1
A insert_gas_neigbours_eGon100RE() 0 9 1
B read_DE_crossbordering_cap_from_pes() 0 83 3
A insert_gas_neigbours_eGon100RE_pipes() 0 40 1
1
"""Module containing code dealing with gas components abroad for eGon100RE
2
3
In this module the missing gas components abroad for eGon100RE are
4
defined and inserted in the database:
5
  * missing crossbording pipelines: the missing crossbordering
6
    pipelines for H2 and CH4,are exclusively between Germany and
7
    its neighbouring countries
8
  * biogas generators
9
10
Dependecies (pipeline)
11
======================
12
  * :dataset: PypsaEurSec, GasNodesandPipes, HydrogenBusEtrago,
13
    ElectricalNeighbours
14
15
Resulting tables
16
================
17
  * grid.egon_etrago_link is completed
18
  * grid.egon_etrago_store is completed
19
  * grid.egon_etrago_generator is modified
20
21
"""
22
23
import pandas as pd
24
25
from egon.data import config, db
26
from egon.data.datasets.gas_neighbours.gas_abroad import (
27
    insert_gas_grid_capacities,
28
    insert_generators,
29
)
30
from egon.data.datasets.pypsaeursec import read_network
31
32
countries = [
33
    "AT",
34
    "BE",
35
    "CH",
36
    "CZ",
37
    "DK",
38
    "FR",
39
    "LU",
40
    "NL",
41
    "NO",
42
    "PL",
43
]
44
45
46
def insert_gas_neigbours_eGon100RE():
47
    """Insert gas components abroad for eGon100RE
48
49
    Insert the missing gas crossbordering grid capacities and the
50
    biogas generators for eGon100RE
51
52
    """
53
    insert_gas_neigbours_eGon100RE_pipes()
54
    insert_generators(insert_biogas_generators_abroad(), scn_name="eGon100RE")
55
56
57
def insert_biogas_generators_abroad():
58
    """Insert biogas generators abroad for eGon100RE
59
60
    This function defines the biogas generators in the neighbouring
61
    countries for the scenario eGon100RE. The capacities arrise from
62
    the pypsa-eur-sec run where the biogas available is modelled as
63
    stores. Therefore, the corresponding stores are deleted and the
64
    capacities inserted as biogas generation potentials.
65
66
    Returns
67
    -------
68
    gen : pandas.DataFrame
69
        Gas production capacities per foreign node
70
71
    """
72
    sources = config.datasets()["gas_neighbours"]["sources"]
73
    scn_name = "eGon100RE"
74
    carrier = "biogas"
75
76
    gen = db.select_dataframe(
77
        f"""
78
        SELECT scn_name, bus, e_initial, marginal_cost
79
        FROM {sources['stores']['schema']}.{sources['stores']['table']}
80
        WHERE scn_name = '{scn_name}'
81
        AND carrier = '{carrier}'
82
        """
83
    )
84
    gen = gen.rename(columns={"e_initial": "p_nom"})
85
    gen["e_nom_max"] = gen["p_nom"]
86
87
    db.execute_sql(
88
        f"""
89
        DELETE FROM
90
        {sources['stores']['schema']}.{sources['stores']['table']}
91
        WHERE scn_name = '{scn_name}'
92
        AND carrier = '{carrier}';
93
        """
94
    )
95
96
    return gen
97
98
99
def insert_gas_neigbours_eGon100RE_pipes():
100
    """Insert missing gas crossbordering grid capacities for eGon100RE
101
102
    This function insert the crossbordering pipelines for H2 and CH4,
103
    exclusively between Germany and its neighbouring countries,
104
    for eGon100RE in the database by executing the following steps:
105
      * call of the the function
106
        :py:func:`define_DE_crossbording_pipes_geom_eGon100RE`, that
107
        defines the crossbordering pipelines (H2 and CH4) between
108
        Germany and its neighbouring countries
109
      * call of the the function
110
        :py:func:`read_DE_crossbordering_cap_from_pes`, that calculates
111
        the crossbordering total exchange capactities for H2 and CH4
112
        between Germany and its neighbouring countries based on the
113
        pypsa-eur-sec results
114
      * call of the the function
115
        :py:func:`calculate_crossbordering_gas_grid_capacities_eGon100RE`,
116
        that attributes to each crossbordering pipeline (H2 and CH4)
117
        between Germany and its neighbouring countries its capacity
118
      * insertion of the H2 and CH4 pipelines between Germany and its
119
        neighbouring countries in the database with function
120
        :py:func:`insert_gas_grid_capacities`
121
122
    Returns
123
    -------
124
    None
125
126
    """
127
128
    DE_pipe_capacities_list = define_DE_crossbording_pipes_geom_eGon100RE()
129
    cap_DE = read_DE_crossbordering_cap_from_pes()
130
131
    Crossbordering_pipe_capacities_list = (
132
        calculate_crossbordering_gas_grid_capacities_eGon100RE(
133
            cap_DE, DE_pipe_capacities_list
134
        )
135
    )
136
137
    insert_gas_grid_capacities(
138
        Crossbordering_pipe_capacities_list, "eGon100RE"
139
    )
140
141
142
def define_DE_crossbording_pipes_geom_eGon100RE(scn_name="eGon100RE"):
143
    """Define the missing crossbordering gas pipelines in eGon100RE
144
145
    This function defines the crossbordering pipelines (for H2 and CH4)
146
    between Germany and its neighbouring countries. These pipelines
147
    are defined as links and there are copied from the corresponding
148
    CH4 crossbering pipelines from eGon2035.
149
150
    Parameters
151
    ----------
152
    scn_name : str
153
        Name of the scenario
154
155
    Returns
156
    -------
157
    gas_pipelines_list_DE : pandas.DataFrame
158
        List of the crossbordering H2 and CH4 pipelines between
159
        Germany and its neighbouring countries in eGon100RE, with
160
        geometry (geom and topo) but no capacity.
161
162
    """
163
    sources = config.datasets()["gas_neighbours"]["sources"]
164
165
    gas_pipelines_list = db.select_geodataframe(
166
        f"""
167
        SELECT * FROM grid.egon_etrago_link
168
        WHERE ("bus0" IN (
169
                        SELECT bus_id FROM 
170
                        {sources['buses']['schema']}.{sources['buses']['table']}
171
                        WHERE country != 'DE'
172
                        AND carrier = 'CH4'
173
                        AND scn_name = 'eGon2035')
174
                    AND "bus1" IN (SELECT bus_id FROM 
175
                        {sources['buses']['schema']}.{sources['buses']['table']}
176
                        WHERE country = 'DE'
177
                        AND carrier = 'CH4' 
178
                        AND scn_name = 'eGon2035'))
179
                OR ("bus0" IN (
180
                        SELECT bus_id FROM 
181
                        {sources['buses']['schema']}.{sources['buses']['table']}
182
                        WHERE country = 'DE'
183
                        AND carrier = 'CH4'
184
                        AND scn_name = 'eGon2035')
185
                AND "bus1" IN (
186
                        SELECT bus_id FROM 
187
                        {sources['buses']['schema']}.{sources['buses']['table']}
188
                        WHERE country != 'DE'
189
                        AND carrier = 'CH4' 
190
                        AND scn_name = 'eGon2035'))
191
        AND scn_name = 'eGon2035'
192
        AND carrier = 'CH4'
193
        """,
194
        epsg=4326,
195
    )
196
197
    # Insert bus0 and bus1
198
    gas_pipelines_list = gas_pipelines_list[
199
        ["bus0", "bus1", "length", "geom", "topo"]
200
    ].rename(columns={"bus0": "bus0_2035", "bus1": "bus1_2035"})
201
202
    gas_nodes_list_2035 = db.select_geodataframe(
203
        f"""
204
        SELECT * FROM {sources['buses']['schema']}.{sources['buses']['table']}
205
        WHERE scn_name = 'eGon2035'
206
        AND carrier = 'CH4'
207
        """,
208
        epsg=4326,
209
    )
210
211
    busID_table = gas_nodes_list_2035[["geom", "bus_id", "country"]].rename(
212
        columns={"bus_id": "bus_id_CH4_2035"}
213
    )
214
    gas_pipelines_list_DE = pd.DataFrame(
215
        columns=["length", "geom", "topo", "bus0", "bus1", "carrier"]
216
    )
217
218
    for carrier in ["H2", "CH4"]:
219
        if carrier == "CH4":
220
            carrier_bus_DE = carrier
221
        elif carrier == "H2":
222
            carrier_bus_DE = "H2_grid"
223
224
        busID_table_DE = db.assign_gas_bus_id(
225
            busID_table[busID_table["country"] == "DE"],
226
            scn_name,
227
            carrier_bus_DE,
0 ignored issues
show
introduced by
The variable carrier_bus_DE does not seem to be defined for all execution paths.
Loading history...
228
        ).set_index("bus_id_CH4_2035")
229
230
        gas_nodes_abroad_100RE = db.select_geodataframe(
231
            f"""
232
            SELECT * FROM grid.egon_etrago_bus
233
            WHERE scn_name = 'eGon100RE'
234
            AND carrier = '{carrier}'
235
            AND country != 'DE'
236
            """,
237
            epsg=4326,
238
        )
239
240
        buses = busID_table[busID_table["country"] != "DE"]
241
        buses["bus_id"] = 0
242
243
        # Select bus_id from db
244
        for i, row in buses.iterrows():
245
            distance = gas_nodes_abroad_100RE.set_index(
246
                "bus_id"
247
            ).geom.distance(row.geom)
248
            buses.loc[i, "bus_id"] = distance[
249
                distance == distance.min()
250
            ].index.values[0]
251
252
        buses = buses.set_index("bus_id_CH4_2035")
253
254
        bus0 = []
255
        bus1 = []
256
        country = []
257
258
        for b0 in gas_pipelines_list["bus0_2035"].to_list():
259
            if b0 in busID_table_DE.index.to_list():
260
                bus0.append(int(busID_table_DE.loc[b0, "bus_id"]))
261
            else:
262
                bus0.append(int(buses.loc[b0, "bus_id"]))
263
                country.append(buses.loc[b0, "country"])
264
        for b1 in gas_pipelines_list["bus1_2035"].to_list():
265
            if b1 in busID_table_DE.index.to_list():
266
                bus1.append(int(busID_table_DE.loc[b1, "bus_id"]))
267
            else:
268
                bus1.append(int(buses.loc[b1, "bus_id"]))
269
                country.append(buses.loc[b1, "country"])
270
271
        gas_pipelines_list["bus0"] = bus0
272
        gas_pipelines_list["bus1"] = bus1
273
        gas_pipelines_list["country"] = country
274
275
        # Insert carrier
276
        if carrier == "CH4":
277
            carrier_pipes = carrier
278
        elif carrier == "H2":
279
            carrier_pipes = "H2_retrofit"
280
        gas_pipelines_list["carrier"] = carrier_pipes
0 ignored issues
show
introduced by
The variable carrier_pipes does not seem to be defined for all execution paths.
Loading history...
281
282
        gas_pipelines_list_DE = gas_pipelines_list_DE.append(
283
            gas_pipelines_list, ignore_index=True
284
        )
285
286
    gas_pipelines_list_DE["scn_name"] = scn_name
287
288
    # Select next id value
289
    new_id = db.next_etrago_id("link")
290
    gas_pipelines_list_DE["link_id"] = range(
291
        new_id, new_id + len(gas_pipelines_list_DE)
292
    )
293
    gas_pipelines_list_DE["link_id"] = gas_pipelines_list_DE["link_id"].astype(
294
        int
295
    )
296
    gas_pipelines_list_DE = gas_pipelines_list_DE.drop(
297
        columns={"bus0_2035", "bus1_2035"}
298
    )
299
300
    return gas_pipelines_list_DE
301
302
303
def read_DE_crossbordering_cap_from_pes():
304
    """Read gas pipelines crossbordering capacities from pes run
305
306
    This function calculates the crossbordering total exchange
307
    capactities for H2 and CH4 between Germany and its neighbouring
308
    countries based on the pypsa-eur-sec results.
309
310
    Returns
311
    -------
312
    DE_pipe_capacities_list : pandas.DataFrame
313
        List of the H2 and CH4 exchange capacity for each neighbouring
314
        country of Germany.
315
316
    """
317
    n = read_network()
318
319
    DE_pipe_capacities_list_H2 = n.links[
320
        (n.links["carrier"] == "H2 pipeline retrofitted")
321
        & ((n.links["bus0"] == "DE0 0 H2") | (n.links["bus1"] == "DE0 0 H2"))
322
    ]
323
324
    DE_pipe_capacities_list_CH4 = n.links[
325
        (n.links["carrier"] == "gas pipeline")
326
        & ((n.links["bus0"] == "DE0 0 gas") | (n.links["bus1"] == "DE0 0 gas"))
327
    ]
328
329
    pipe_capacities_list = pd.DataFrame(
330
        columns=["p_nom", "carrier", "country_code"]
331
    )
332
    for DE_pipe_capacities_list in [
333
        DE_pipe_capacities_list_H2,
334
        DE_pipe_capacities_list_CH4,
335
    ]:
336
337
        DE_pipe_capacities_list = DE_pipe_capacities_list[
338
            ["bus0", "bus1", "p_nom_opt", "carrier"]
339
        ].rename(columns={"p_nom_opt": "p_nom"})
340
341
        DE_pipe_capacities_list[
342
            "country_code"
343
        ] = DE_pipe_capacities_list.apply(
344
            lambda row: str(sorted([row.bus0[:2], row.bus1[:2]])), axis=1
345
        )
346
347
        DE_pipe_capacities_list = DE_pipe_capacities_list.drop(
348
            columns=[
349
                "bus0",
350
                "bus1",
351
            ]
352
        )
353
354
        DE_pipe_capacities_list = DE_pipe_capacities_list.groupby(
355
            ["country_code"], as_index=False
356
        ).agg({"p_nom": "sum", "carrier": "first"})
357
358
        pipe_capacities_list = pipe_capacities_list.append(
359
            DE_pipe_capacities_list, ignore_index=True
360
        )
361
362
    map_countries = {
363
        "['AT', 'DE']": "AT",
364
        "['BE', 'DE']": "BE",
365
        "['CH', 'DE']": "CH",
366
        "['CZ', 'DE']": "CZ",
367
        "['DE', 'DK']": "DK",
368
        "['DE', 'FR']": "FR",
369
        "['DE', 'LU']": "LU",
370
        "['DE', 'NL']": "NL",
371
        "['DE', 'NO']": "NO",
372
        "['DE', 'PL']": "PL",
373
    }
374
375
    pipe_capacities_list["country_code"] = pipe_capacities_list[
376
        "country_code"
377
    ].replace(map_countries)
378
    pipe_capacities_list["carrier"] = pipe_capacities_list["carrier"].replace(
379
        {
380
            "H2 pipeline retrofitted": "H2_retrofit",
381
            "gas pipeline": "CH4",
382
        }
383
    )
384
385
    return pipe_capacities_list
386
387
388
def calculate_crossbordering_gas_grid_capacities_eGon100RE(
389
    cap_DE, DE_pipe_capacities_list
390
):
391
    """Attribute gas crossbordering grid capacities for eGon100RE
392
393
    This function attributes to each crossbordering pipeline (H2 and
394
    CH4) between Germany and its neighbouring countries its capacity.
395
396
    Parameters
397
    ----------
398
    cap_DE : pandas.DataFrame
399
        List of the H2 and CH4 exchange capacity for each neighbouring
400
        country of Germany.
401
    DE_pipe_capacities_list : pandas.DataFrame
402
        List of the crossbordering for H2 and CH4 pipelines between
403
        Germany and its neighbouring countries in eGon100RE, with
404
        geometry (geom and topo) but no capacity.
405
406
    Returns
407
    -------
408
    Crossbordering_pipe_capacities_list : pandas.DataFrame
409
        List of the crossbordering H2 and CH4 pipelines between
410
        Germany and its neighbouring countries in eGon100RE.
411
412
    """
413
414
    Crossbordering_pipe_capacities_list = pd.DataFrame(
415
        columns=[
416
            "length",
417
            "geom",
418
            "topo",
419
            "bus0",
420
            "bus1",
421
            "carrier",
422
            "scn_name",
423
            "link_id",
424
            "p_nom",
425
        ]
426
    )
427
428
    for carrier in ["CH4", "H2_retrofit"]:
429
        p_nom = []
430
        cap = cap_DE[cap_DE["carrier"] == carrier].set_index("country_code")
431
        pipe_capacities_list = DE_pipe_capacities_list[
432
            DE_pipe_capacities_list["carrier"] == carrier
433
        ]
434
435
        for c in pipe_capacities_list["country"].to_list():
436
            n_links = len(
437
                pipe_capacities_list[
438
                    pipe_capacities_list["country"] == c
439
                ].index
440
            )
441
            p_nom.append(cap.at[c, "p_nom"] / n_links)
442
443
        pipe_capacities_list["p_nom"] = p_nom
444
        pipe_capacities_list = pipe_capacities_list.drop(columns={"country"})
445
        Crossbordering_pipe_capacities_list = (
446
            Crossbordering_pipe_capacities_list.append(pipe_capacities_list)
447
        )
448
449
    return Crossbordering_pipe_capacities_list
450