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

data.datasets.gas_neighbours.eGon100RE   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 392
Duplicated Lines 0 %

Importance

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