Passed
Pull Request — dev (#917)
by
unknown
01:35
created

insert_gas_neigbours_eGon100RE()   A

Complexity

Conditions 3

Size

Total Lines 50
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 14
dl 0
loc 50
rs 9.7
c 0
b 0
f 0
cc 3
nop 0
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 country != 'RU'
124
                        AND carrier = 'CH4'
125
                        AND scn_name = 'eGon2035')
126
                    AND "bus1" IN (SELECT bus_id FROM 
127
                        {sources['buses']['schema']}.{sources['buses']['table']}
128
                        WHERE country = 'DE'
129
                        AND carrier = 'CH4' 
130
                        AND scn_name = 'eGon2035'))
131
                OR ("bus0" IN (
132
                        SELECT bus_id FROM 
133
                        {sources['buses']['schema']}.{sources['buses']['table']}
134
                        WHERE country = 'DE'
135
                        AND carrier = 'CH4'
136
                        AND scn_name = 'eGon2035')
137
                AND "bus1" IN (
138
                        SELECT bus_id FROM 
139
                        {sources['buses']['schema']}.{sources['buses']['table']}
140
                        WHERE country != 'DE'
141
                        AND country != 'RU'
142
                        AND carrier = 'CH4' 
143
                        AND scn_name = 'eGon2035'))
144
        AND scn_name = 'eGon2035'
145
        AND carrier = 'CH4'
146
        """,
147
        epsg=4326,
148
    )
149
150
    # Insert bus0 and bus1
151
    gas_pipelines_list = gas_pipelines_list[
152
        ["bus0", "bus1", "length", "geom", "topo"]
153
    ].rename(columns={"bus0": "bus0_2035", "bus1": "bus1_2035"})
154
155
    gas_nodes_list_2035 = db.select_geodataframe(
156
        f"""
157
        SELECT * FROM {sources['buses']['schema']}.{sources['buses']['table']}
158
        WHERE scn_name = 'eGon2035'
159
        AND carrier = 'CH4'
160
        """,
161
        epsg=4326,
162
    )
163
164
    busID_table = gas_nodes_list_2035[["geom", "bus_id", "country"]].rename(
165
        columns={"bus_id": "bus_id_CH4_2035"}
166
    )
167
    gas_pipelines_list_DE = pd.DataFrame(
168
        columns=["length", "geom", "topo", "bus0", "bus1", "carrier"]
169
    )
170
171
    for carrier in ["H2", "CH4"]:
172
        if carrier == "CH4":
173
            carrier_bus_DE = carrier
174
        elif carrier == "H2":
175
            carrier_bus_DE = "H2_grid"
176
177
        busID_table_DE = db.assign_gas_bus_id(
178
            busID_table[busID_table["country"] == "DE"],
179
            scn_name,
180
            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...
181
        ).set_index("bus_id_CH4_2035")
182
183
        gas_nodes_abroad_100RE = db.select_geodataframe(
184
            f"""
185
            SELECT * FROM grid.egon_etrago_bus
186
            WHERE scn_name = 'eGon100RE'
187
            AND carrier = '{carrier}'
188
            AND country != 'DE'
189
            """,
190
            epsg=4326,
191
        )
192
193
        buses = busID_table[busID_table["country"] != "DE"]
194
        buses["bus_id"] = 0
195
196
        # Select bus_id from db
197
        for i, row in buses.iterrows():
198
            distance = gas_nodes_abroad_100RE.set_index(
199
                "bus_id"
200
            ).geom.distance(row.geom)
201
            buses.loc[i, "bus_id"] = distance[
202
                distance == distance.min()
203
            ].index.values[0]
204
205
        buses = buses.set_index("bus_id_CH4_2035")
206
207
        bus0 = []
208
        bus1 = []
209
        country = []
210
211
        for b0 in gas_pipelines_list["bus0_2035"].to_list():
212
            if b0 in busID_table_DE.index.to_list():
213
                bus0.append(int(busID_table_DE.loc[b0, "bus_id"]))
214
            else:
215
                bus0.append(int(buses.loc[b0, "bus_id"]))
216
                country.append(buses.loc[b0, "country"])
217
        for b1 in gas_pipelines_list["bus1_2035"].to_list():
218
            if b1 in busID_table_DE.index.to_list():
219
                bus1.append(int(busID_table_DE.loc[b1, "bus_id"]))
220
            else:
221
                bus1.append(int(buses.loc[b1, "bus_id"]))
222
                country.append(buses.loc[b1, "country"])
223
224
        gas_pipelines_list["bus0"] = bus0
225
        gas_pipelines_list["bus1"] = bus1
226
        gas_pipelines_list["country"] = country
227
228
        # Insert carrier
229
        if carrier == "CH4":
230
            carrier_pipes = carrier
231
        elif carrier == "H2":
232
            carrier_pipes = "H2_retrofit"
233
        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...
234
235
        gas_pipelines_list_DE = gas_pipelines_list_DE.append(
236
            gas_pipelines_list, ignore_index=True
237
        )
238
239
    gas_pipelines_list_DE["scn_name"] = scn_name
240
241
    # Select next id value
242
    new_id = db.next_etrago_id("link")
243
    gas_pipelines_list_DE["link_id"] = range(
244
        new_id, new_id + len(gas_pipelines_list_DE)
245
    )
246
    gas_pipelines_list_DE["link_id"] = gas_pipelines_list_DE["link_id"].astype(
247
        int
248
    )
249
    gas_pipelines_list_DE = gas_pipelines_list_DE.drop(
250
        columns={"bus0_2035", "bus1_2035"}
251
    )
252
253
    return gas_pipelines_list_DE
254
255
256
def read_DE_crossbordering_cap_from_pes():
257
    """Read gas pipelines crossbordering capacities from pes run
258
259
    This function calculates the crossbordering total exchange
260
    capactities for H2 and CH4 between Germany and its neighbouring
261
    countries based on the pypsa-eur-sec results.
262
263
    Returns
264
    -------
265
    DE_pipe_capacities_list : pandas.DataFrame
266
        List of the H2 and CH4 exchange capacity for each neighbouring
267
        country of Germany.
268
269
    """
270
    n = read_network()
271
272
    DE_pipe_capacities_list_H2 = n.links[
273
        (n.links["carrier"] == "H2 pipeline retrofitted")
274
        & ((n.links["bus0"] == "DE0 0 H2") | (n.links["bus1"] == "DE0 0 H2"))
275
    ]
276
277
    DE_pipe_capacities_list_CH4 = n.links[
278
        (n.links["carrier"] == "gas pipeline")
279
        & ((n.links["bus0"] == "DE0 0 gas") | (n.links["bus1"] == "DE0 0 gas"))
280
    ]
281
282
    pipe_capacities_list = pd.DataFrame(
283
        columns=["p_nom", "carrier", "country_code"]
284
    )
285
    for DE_pipe_capacities_list in [
286
        DE_pipe_capacities_list_H2,
287
        DE_pipe_capacities_list_CH4,
288
    ]:
289
290
        DE_pipe_capacities_list = DE_pipe_capacities_list[
291
            ["bus0", "bus1", "p_nom_opt", "carrier"]
292
        ].rename(columns={"p_nom_opt": "p_nom"})
293
294
        DE_pipe_capacities_list[
295
            "country_code"
296
        ] = DE_pipe_capacities_list.apply(
297
            lambda row: str(sorted([row.bus0[:2], row.bus1[:2]])), axis=1
298
        )
299
300
        DE_pipe_capacities_list = DE_pipe_capacities_list.drop(
301
            columns=[
302
                "bus0",
303
                "bus1",
304
            ]
305
        )
306
307
        DE_pipe_capacities_list = DE_pipe_capacities_list.groupby(
308
            ["country_code"], as_index=False
309
        ).agg({"p_nom": "sum", "carrier": "first"})
310
311
        pipe_capacities_list = pipe_capacities_list.append(
312
            DE_pipe_capacities_list, ignore_index=True
313
        )
314
315
    map_countries = {
316
        "['AT', 'DE']": "AT",
317
        "['BE', 'DE']": "BE",
318
        "['CH', 'DE']": "CH",
319
        "['CZ', 'DE']": "CZ",
320
        "['DE', 'DK']": "DK",
321
        "['DE', 'FR']": "FR",
322
        "['DE', 'LU']": "LU",
323
        "['DE', 'NL']": "NL",
324
        "['DE', 'NO']": "NO",
325
        "['DE', 'PL']": "PL",
326
    }
327
328
    pipe_capacities_list["country_code"] = pipe_capacities_list[
329
        "country_code"
330
    ].replace(map_countries)
331
    pipe_capacities_list["carrier"] = pipe_capacities_list["carrier"].replace(
332
        {
333
            "H2 pipeline retrofitted": "H2_retrofit",
334
            "gas pipeline": "CH4",
335
        }
336
    )
337
338
    return pipe_capacities_list
339
340
341
def calculate_crossbordering_gas_grid_capacities_eGon100RE(
342
    cap_DE, DE_pipe_capacities_list
343
):
344
    """Attribute gas crossbordering grid capacities for eGon100RE
345
346
    This function attributes to each crossbordering pipeline (H2 and
347
    CH4) between Germany and its neighbouring countries its capacity.
348
349
    Parameters
350
    ----------
351
    cap_DE : pandas.DataFrame
352
        List of the H2 and CH4 exchange capacity for each neighbouring
353
        country of Germany.
354
    DE_pipe_capacities_list : pandas.DataFrame
355
        List of the crossbordering for H2 and CH4 pipelines between
356
        Germany and its neighbouring countries in eGon100RE, with
357
        geometry (geom and topo) but no capacity.
358
359
    Returns
360
    -------
361
    Crossbordering_pipe_capacities_list : pandas.DataFrame
362
        List of the crossbordering H2 and CH4 pipelines between
363
        Germany and its neighbouring countries in eGon100RE.
364
365
    """
366
367
    Crossbordering_pipe_capacities_list = pd.DataFrame(
368
        columns=[
369
            "length",
370
            "geom",
371
            "topo",
372
            "bus0",
373
            "bus1",
374
            "carrier",
375
            "scn_name",
376
            "link_id",
377
            "p_nom",
378
        ]
379
    )
380
381
    for carrier in ["CH4", "H2_retrofit"]:
382
        p_nom = []
383
        cap = cap_DE[cap_DE["carrier"] == carrier].set_index("country_code")
384
        pipe_capacities_list = DE_pipe_capacities_list[
385
            DE_pipe_capacities_list["carrier"] == carrier
386
        ]
387
388
        for c in pipe_capacities_list["country"].to_list():
389
            n_links = len(
390
                pipe_capacities_list[
391
                    pipe_capacities_list["country"] == c
392
                ].index
393
            )
394
            p_nom.append(cap.at[c, "p_nom"] / n_links)
395
396
        pipe_capacities_list["p_nom"] = p_nom
397
        pipe_capacities_list = pipe_capacities_list.drop(columns={"country"})
398
        Crossbordering_pipe_capacities_list = (
399
            Crossbordering_pipe_capacities_list.append(pipe_capacities_list)
400
        )
401
402
    return Crossbordering_pipe_capacities_list
403