Passed
Pull Request — dev (#917)
by
unknown
02:04
created

data.datasets.gas_neighbours.eGon100RE   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 401
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 20
eloc 179
dl 0
loc 401
rs 10
c 0
b 0
f 0

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