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

insert_generators()   A

Complexity

Conditions 1

Size

Total Lines 80
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 34
dl 0
loc 80
rs 9.064
c 0
b 0
f 0
cc 1
nop 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
"""Central module containing code dealing with gas neighbours for eGon2035
2
"""
3
4
from pathlib import Path
5
from urllib.request import urlretrieve
6
import ast
7
import zipfile
8
9
from shapely.geometry import LineString, MultiLineString
10
import geopandas as gpd
11
import pandas as pd
12
import pypsa
13
14
from egon.data import config, db
15
from egon.data.datasets.electrical_neighbours import (
16
    get_foreign_bus_id,
17
    get_map_buses,
18
)
19
from egon.data.datasets.gas_neighbours.gas_abroad import (
20
    get_foreign_gas_bus_id,
21
    insert_ch4_stores,
22
    insert_gas_grid_capacities,
23
    insert_generators,
24
)
25
from egon.data.datasets.scenario_parameters import get_sector_parameters
26
27
countries = [
28
    "AT",
29
    "BE",
30
    "CH",
31
    "CZ",
32
    "DK",
33
    "FR",
34
    "GB",
35
    "LU",
36
    "NL",
37
    "NO",
38
    "PL",
39
    "RU",
40
    "SE",
41
    "UK",
42
]
43
44
45
def read_LNG_capacities():
46
    """Read LNG import capacities from Scigrid gas data
47
48
    Returns
49
    -------
50
    IGGIELGN_LNGs: pandas.Series
51
        LNG terminal capacities per foreign country node (in GWh/d)
52
53
    """
54
    lng_file = "datasets/gas_data/data/IGGIELGN_LNGs.csv"
55
    IGGIELGN_LNGs = gpd.read_file(lng_file)
56
57
    map_countries_scigrid = {
58
        "BE": "BE00",
59
        "EE": "EE00",
60
        "EL": "GR00",
61
        "ES": "ES00",
62
        "FI": "FI00",
63
        "FR": "FR00",
64
        "GB": "UK00",
65
        "IT": "ITCN",
66
        "LT": "LT00",
67
        "LV": "LV00",
68
        "MT": "MT00",
69
        "NL": "NL00",
70
        "PL": "PL00",
71
        "PT": "PT00",
72
        "SE": "SE01",
73
    }
74
75
    conversion_factor = 437.5  # MCM/day to MWh/h
76
    c2 = 24 / 1000  # MWh/h to GWh/d
77
    p_nom = []
78
79
    for index, row in IGGIELGN_LNGs.iterrows():
80
        param = ast.literal_eval(row["param"])
81
        p_nom.append(
82
            param["max_cap_store2pipe_M_m3_per_d"] * conversion_factor * c2
83
        )
84
85
    IGGIELGN_LNGs["LNG max_cap_store2pipe_M_m3_per_d (in GWh/d)"] = p_nom
86
87
    IGGIELGN_LNGs.drop(
88
        [
89
            "uncertainty",
90
            "method",
91
            "param",
92
            "comment",
93
            "tags",
94
            "source_id",
95
            "lat",
96
            "long",
97
            "geometry",
98
            "id",
99
            "name",
100
            "node_id",
101
        ],
102
        axis=1,
103
        inplace=True,
104
    )
105
106
    IGGIELGN_LNGs["Country"] = IGGIELGN_LNGs["country_code"].map(
107
        map_countries_scigrid
108
    )
109
    IGGIELGN_LNGs = (
110
        IGGIELGN_LNGs.groupby(["Country"])[
111
            "LNG max_cap_store2pipe_M_m3_per_d (in GWh/d)"
112
        ]
113
        .sum()
114
        .sort_index()
115
    )
116
117
    return IGGIELGN_LNGs
118
119
120
def calc_capacities():
121
    """Calculates gas production capacities of neighbouring countries
122
123
    For each neigbouring country, this function calculates the gas
124
    generation capacity in 2035 using the function
125
    :py:func:`calc_capacity_per_year` for 2030 and 2040 and
126
    interpolating the results. These capacities include LNG import, as
127
    well as conventional and biogas production.
128
    Two conventional gas generators for are added for Norway and Russia
129
    interpolating the supply potential (min) values from the TYNPD 2020
130
    for 2030 and 2040.
131
132
    Returns
133
    -------
134
    grouped_capacities: pandas.DataFrame
135
        Gas production capacities per foreign node
136
137
    """
138
139
    sources = config.datasets()["gas_neighbours"]["sources"]
140
141
    # insert installed capacities
142
    file = zipfile.ZipFile(f"tyndp/{sources['tyndp_capacities']}")
143
    df0 = pd.read_excel(
144
        file.open("TYNDP-2020-Scenario-Datafile.xlsx").read(),
145
        sheet_name="Gas Data",
146
    )
147
148
    df = (
149
        df0.query(
150
            'Scenario == "Distributed Energy" &'
151
            ' (Case == "Peak" | Case == "Average") &'
152
            # Case: 2 Week/Average/DF/Peak
153
            ' Category == "Production"'
154
        )
155
        .drop(
156
            columns=[
157
                "Generator_ID",
158
                "Climate Year",
159
                "Simulation_ID",
160
                "Node 1",
161
                "Path",
162
                "Direct/Indirect",
163
                "Sector",
164
                "Note",
165
                "Category",
166
                "Scenario",
167
            ]
168
        )
169
        .set_index("Node/Line")
170
        .sort_index()
171
    )
172
173
    lng = read_LNG_capacities()
174
    df_2030 = calc_capacity_per_year(df, lng, 2030)
175
    df_2040 = calc_capacity_per_year(df, lng, 2040)
176
177
    # Conversion GWh/d to MWh/h
178
    conversion_factor = 1000 / 24
179
180
    df_2035 = pd.concat([df_2040, df_2030], axis=1)
181
    df_2035 = df_2035.drop(
182
        columns=[
183
            "Value_conv_2040",
184
            "Value_conv_2030",
185
            "Value_bio_2040",
186
            "Value_bio_2030",
187
        ]
188
    )
189
    df_2035["cap_2035"] = (df_2035["CH4_2030"] + df_2035["CH4_2040"]) / 2
190
    df_2035["e_nom_max"] = (
191
        ((df_2035["e_nom_max_2030"] + df_2035["e_nom_max_2040"]) / 2)
192
        * conversion_factor
193
        * 8760
194
    )
195
    df_2035["share_LNG_2035"] = (
196
        df_2035["share_LNG_2030"] + df_2035["share_LNG_2040"]
197
    ) / 2
198
    df_2035["share_conv_pipe_2035"] = (
199
        df_2035["share_conv_pipe_2030"] + df_2035["share_conv_pipe_2040"]
200
    ) / 2
201
    df_2035["share_bio_2035"] = (
202
        df_2035["share_bio_2030"] + df_2035["share_bio_2040"]
203
    ) / 2
204
205
    grouped_capacities = df_2035.drop(
206
        columns=[
207
            "share_LNG_2030",
208
            "share_LNG_2040",
209
            "share_conv_pipe_2030",
210
            "share_conv_pipe_2040",
211
            "share_bio_2030",
212
            "share_bio_2040",
213
            "CH4_2040",
214
            "CH4_2030",
215
            "e_nom_max_2030",
216
            "e_nom_max_2040",
217
        ]
218
    ).reset_index()
219
220
    grouped_capacities["cap_2035"] = (
221
        grouped_capacities["cap_2035"] * conversion_factor
222
    )
223
224
    # Add generators in Norway and Russia
225
    df_conv = (
226
        df0.query('Case == "Min" & Category == "Supply Potential"')
227
        .drop(
228
            columns=[
229
                "Generator_ID",
230
                "Climate Year",
231
                "Simulation_ID",
232
                "Node 1",
233
                "Path",
234
                "Direct/Indirect",
235
                "Sector",
236
                "Note",
237
                "Category",
238
                "Scenario",
239
                "Parameter",
240
                "Case",
241
            ]
242
        )
243
        .set_index("Node/Line")
244
        .sort_index()
245
    )
246
247
    df_conv_2030 = df_conv[df_conv["Year"] == 2030].rename(
248
        columns={"Value": "Value_2030"}
249
    )
250
    df_conv_2040 = df_conv[df_conv["Year"] == 2040].rename(
251
        columns={"Value": "Value_2040"}
252
    )
253
    df_conv_2035 = pd.concat([df_conv_2040, df_conv_2030], axis=1)
254
255
    df_conv_2035["cap_2035"] = (
256
        (df_conv_2035["Value_2030"] + df_conv_2035["Value_2040"]) / 2
257
    ) * conversion_factor
258
    df_conv_2035["e_nom_max"] = df_conv_2035["cap_2035"] * 8760
259
    df_conv_2035["share_LNG_2035"] = 0
260
    df_conv_2035["share_conv_pipe_2035"] = 1
261
    df_conv_2035["share_bio_2035"] = 0
262
263
    df_conv_2035 = df_conv_2035.drop(
264
        columns=[
265
            "Year",
266
            "Value_2030",
267
            "Value_2040",
268
        ]
269
    ).reset_index()
270
    df_conv_2035 = df_conv_2035.rename(columns={"Node/Line": "index"})
271
    grouped_capacities = grouped_capacities.append(df_conv_2035)
272
273
    # choose capacities for considered countries
274
    grouped_capacities = grouped_capacities[
275
        grouped_capacities["index"].str[:2].isin(countries)
276
    ]
277
    return grouped_capacities
278
279
280
def calc_capacity_per_year(df, lng, year):
281
    """Calculates gas production capacities for a specified year
282
283
    For a specified year and for the foreign country nodes this function
284
    calculates the gas production capacity, considering the gas
285
    (conventional and bio) production capacity from TYNDP data and the
286
    LGN import capacity from Scigrid gas data.
287
288
    The columns of the returned dataframe are the following:
289
      * Value_bio_year: biogas capacity prodution (in GWh/d)
290
      * Value_conv_year: conventional gas capacity prodution including
291
        LNG imports (in GWh/d)
292
      * CH4_year: total gas production capacity (in GWh/d). This value
293
        is calculated using the peak production value from the TYNDP.
294
      * e_nom_max_year: total gas production capacity representative
295
        for the whole year (in GWh/d). This value is calculated using
296
        the average production value from the TYNDP and will then be
297
        used to limit the energy that can be generated in one year.
298
      * share_LNG_year: share of LGN import capacity in the total gas
299
        production capacity
300
      * share_conv_pipe_year: share of conventional gas extraction
301
        capacity in the total gas production capacity
302
      * share_bio_year: share of biogas production capacity in the
303
        total gas production capacity
304
305
    Parameters
306
    ----------
307
    df : pandas.DataFrame
308
        Gas (conventional and bio) production capacities from TYNDP (in GWh/d)
309
310
    lng : pandas.Series
311
        LNG terminal capacities per foreign country node (in GWh/d)
312
313
    year : int
314
        Year to calculate gas production capacity for.
315
316
    Returns
317
    -------
318
    df_year : pandas.DataFrame
319
        Gas production capacities (in GWh/d) per foreign country node
320
321
    """
322
    df_conv_peak = (
323
        df[
324
            (df["Parameter"] == "Conventional")
325
            & (df["Year"] == year)
326
            & (df["Case"] == "Peak")
327
        ]
328
        .rename(columns={"Value": f"Value_conv_{year}_peak"})
329
        .drop(columns=["Parameter", "Year", "Case"])
330
    )
331
    df_conv_average = (
332
        df[
333
            (df["Parameter"] == "Conventional")
334
            & (df["Year"] == year)
335
            & (df["Case"] == "Average")
336
        ]
337
        .rename(columns={"Value": f"Value_conv_{year}_average"})
338
        .drop(columns=["Parameter", "Year", "Case"])
339
    )
340
    df_bioch4 = (
341
        df[
342
            (df["Parameter"] == "Biomethane")
343
            & (df["Year"] == year)
344
            & (df["Case"] == "Peak")
345
            # Peak and Average have the same values for biogas
346
            # production in 2030 and 2040
347
        ]
348
        .rename(columns={"Value": f"Value_bio_{year}"})
349
        .drop(columns=["Parameter", "Year", "Case"])
350
    )
351
352
    # Some values are duplicated (DE00 in 2030)
353
    df_conv_peak = df_conv_peak[~df_conv_peak.index.duplicated(keep="first")]
354
    df_conv_average = df_conv_average[
355
        ~df_conv_average.index.duplicated(keep="first")
356
    ]
357
358
    df_year = pd.concat(
359
        [df_conv_peak, df_conv_average, df_bioch4, lng], axis=1
360
    ).fillna(0)
361
    df_year = df_year[
362
        ~(
363
            (df_year[f"Value_conv_{year}_peak"] == 0)
364
            & (df_year[f"Value_bio_{year}"] == 0)
365
            & (df_year["LNG max_cap_store2pipe_M_m3_per_d (in GWh/d)"] == 0)
366
        )
367
    ]
368
    df_year[f"Value_conv_{year}"] = (
369
        df_year[f"Value_conv_{year}_peak"]
370
        + df_year["LNG max_cap_store2pipe_M_m3_per_d (in GWh/d)"]
371
    )
372
    df_year[f"CH4_{year}"] = (
373
        df_year[f"Value_conv_{year}"] + df_year[f"Value_bio_{year}"]
374
    )
375
    df_year[f"e_nom_max_{year}"] = (
376
        df_year[f"Value_conv_{year}_average"]
377
        + df_year[f"Value_bio_{year}"]
378
        + df_year["LNG max_cap_store2pipe_M_m3_per_d (in GWh/d)"]
379
    )
380
    df_year[f"share_LNG_{year}"] = (
381
        df_year["LNG max_cap_store2pipe_M_m3_per_d (in GWh/d)"]
382
        / df_year[f"e_nom_max_{year}"]
383
    )
384
    df_year[f"share_conv_pipe_{year}"] = (
385
        df_year[f"Value_conv_{year}_average"] / df_year[f"e_nom_max_{year}"]
386
    )
387
    df_year[f"share_bio_{year}"] = (
388
        df_year[f"Value_bio_{year}"] / df_year[f"e_nom_max_{year}"]
389
    )
390
391
    df_year = df_year.drop(
392
        columns=[
393
            "LNG max_cap_store2pipe_M_m3_per_d (in GWh/d)",
394
            f"Value_conv_{year}_average",
395
            f"Value_conv_{year}_peak",
396
        ]
397
    )
398
399
    return df_year
400
401
402
def calc_global_ch4_demand(Norway_global_demand_1y):
403
    """Calculates global CH4 demands abroad for eGon2035 scenario
404
405
    The data comes from TYNDP 2020 according to NEP 2021 from the
406
    scenario 'Distributed Energy', linear interpolate between 2030
407
    and 2040.
408
409
    Returns
410
    -------
411
    pandas.DataFrame
412
        Global (yearly) CH4 final demand per foreign node
413
414
    """
415
416
    sources = config.datasets()["gas_neighbours"]["sources"]
417
418
    file = zipfile.ZipFile(f"tyndp/{sources['tyndp_capacities']}")
419
    df = pd.read_excel(
420
        file.open("TYNDP-2020-Scenario-Datafile.xlsx").read(),
421
        sheet_name="Gas Data",
422
    )
423
424
    df = (
425
        df.query(
426
            'Scenario == "Distributed Energy" & '
427
            'Case == "Average" &'
428
            'Category == "Demand"'
429
        )
430
        .drop(
431
            columns=[
432
                "Generator_ID",
433
                "Climate Year",
434
                "Simulation_ID",
435
                "Node 1",
436
                "Path",
437
                "Direct/Indirect",
438
                "Sector",
439
                "Note",
440
                "Category",
441
                "Case",
442
                "Scenario",
443
            ]
444
        )
445
        .set_index("Node/Line")
446
    )
447
448
    df_2030 = (
449
        df[(df["Parameter"] == "Final demand") & (df["Year"] == 2030)]
450
        .rename(columns={"Value": "Value_2030"})
451
        .drop(columns=["Parameter", "Year"])
452
    )
453
454
    df_2040 = (
455
        df[(df["Parameter"] == "Final demand") & (df["Year"] == 2040)]
456
        .rename(columns={"Value": "Value_2040"})
457
        .drop(columns=["Parameter", "Year"])
458
    )
459
460
    # Conversion GWh/d to MWh/y
461
    conversion_factor = 1000 * 365
462
463
    df_2035 = pd.concat([df_2040, df_2030], axis=1)
464
    df_2035["GlobD_2035"] = (
465
        (df_2035["Value_2030"] + df_2035["Value_2040"]) / 2
466
    ) * conversion_factor
467
    df_2035.loc["NOS0"] = [
468
        0,
469
        0,
470
        Norway_global_demand_1y,
471
    ]  # Manually add Norway demand
472
    grouped_demands = df_2035.drop(
473
        columns=["Value_2030", "Value_2040"]
474
    ).reset_index()
475
476
    # choose demands for considered countries
477
    return grouped_demands[
478
        grouped_demands["Node/Line"].str[:2].isin(countries)
479
    ]
480
481
482
def import_ch4_demandTS():
483
    """Calculate global CH4 demand in Norway and CH4 demand profile
484
485
    Import from the PyPSA-eur-sec run the timeseries of residential
486
    rural heat per neighbor country. This timeserie is used to
487
    calculate:
488
      * the global (yearly) heat demand of Norway
489
        (that will be supplied by CH4)
490
      * the normalized CH4 hourly resolved demand profile
491
492
    Parameters
493
    ----------
494
    None.
495
496
    Returns
497
    -------
498
    Norway_global_demand: Float
499
        Yearly heat demand of Norway in MWh
500
    neighbor_loads_t: pandas.DataFrame
501
        Normalized CH4 hourly resolved demand profiles per neighbor country
502
503
    """
504
505
    cwd = Path(".")
506
    target_file = (
507
        cwd
508
        / "data_bundle_egon_data"
509
        / "pypsa_eur_sec"
510
        / "2022-07-26-egondata-integration"
511
        / "postnetworks"
512
        / "elec_s_37_lv2.0__Co2L0-1H-T-H-B-I-dist1_2050.nc"
513
    )
514
515
    network = pypsa.Network(str(target_file))
516
517
    # Set country tag for all buses
518
    network.buses.country = network.buses.index.str[:2]
519
    neighbors = network.buses[network.buses.country != "DE"]
520
    neighbors = neighbors[
521
        (neighbors["country"].isin(countries))
522
        & (neighbors["carrier"] == "residential rural heat")
523
    ].drop_duplicates(subset="country")
524
525
    neighbor_loads = network.loads[network.loads.bus.isin(neighbors.index)]
526
    neighbor_loads_t_index = neighbor_loads.index[
527
        neighbor_loads.index.isin(network.loads_t.p_set.columns)
528
    ]
529
    neighbor_loads_t = network.loads_t["p_set"][neighbor_loads_t_index]
530
    Norway_global_demand = neighbor_loads_t[
531
        "NO3 0 residential rural heat"
532
    ].sum()
533
534
    for i in neighbor_loads_t.columns:
535
        neighbor_loads_t[i] = neighbor_loads_t[i] / neighbor_loads_t[i].sum()
536
537
    return Norway_global_demand, neighbor_loads_t
538
539
540
def insert_ch4_demand(global_demand, normalized_ch4_demandTS):
541
    """Insert CH4 demands abroad in the database for eGon2035
542
543
    Parameters
544
    ----------
545
    global_demand : pandas.DataFrame
546
        Global CH4 demand per foreign node in 1 year
547
    gas_demandTS : pandas.DataFrame
548
        Normalized time serie of the demand per foreign country
549
550
    Returns
551
    -------
552
    None.
553
554
    """
555
    sources = config.datasets()["gas_neighbours"]["sources"]
556
    targets = config.datasets()["gas_neighbours"]["targets"]
557
    map_buses = get_map_buses()
558
559
    scn_name = "eGon2035"
560
    carrier = "CH4"
561
562
    # Delete existing data
563
    db.execute_sql(
564
        f"""
565
        DELETE FROM
566
        {targets['load_timeseries']['schema']}.{targets['load_timeseries']['table']}
567
        WHERE "load_id" IN (
568
            SELECT load_id FROM
569
            {targets['loads']['schema']}.{targets['loads']['table']}
570
            WHERE bus IN (
571
                SELECT bus_id FROM
572
                {sources['buses']['schema']}.{sources['buses']['table']}
573
                WHERE country != 'DE'
574
                AND scn_name = '{scn_name}')
575
            AND scn_name = '{scn_name}'
576
            AND carrier = '{carrier}'
577
        );
578
        """
579
    )
580
581
    db.execute_sql(
582
        f"""
583
        DELETE FROM
584
        {targets['loads']['schema']}.{targets['loads']['table']}
585
        WHERE bus IN (
586
            SELECT bus_id FROM
587
            {sources['buses']['schema']}.{sources['buses']['table']}
588
            WHERE country != 'DE'
589
            AND scn_name = '{scn_name}')
590
        AND scn_name = '{scn_name}'
591
        AND carrier = '{carrier}'
592
        """
593
    )
594
595
    # Set bus_id
596
    global_demand.loc[
597
        global_demand[global_demand["Node/Line"].isin(map_buses.keys())].index,
598
        "Node/Line",
599
    ] = global_demand.loc[
600
        global_demand[global_demand["Node/Line"].isin(map_buses.keys())].index,
601
        "Node/Line",
602
    ].map(
603
        map_buses
604
    )
605
    global_demand.loc[:, "bus"] = (
606
        get_foreign_gas_bus_id().loc[global_demand.loc[:, "Node/Line"]].values
607
    )
608
609
    # Add missing columns
610
    c = {"scn_name": scn_name, "carrier": carrier}
611
    global_demand = global_demand.assign(**c)
612
613
    new_id = db.next_etrago_id("load")
614
    global_demand["load_id"] = range(new_id, new_id + len(global_demand))
615
616
    ch4_demand_TS = global_demand.copy()
617
    # Remove useless columns
618
    global_demand = global_demand.drop(columns=["Node/Line", "GlobD_2035"])
619
620
    # Insert data to db
621
    global_demand.to_sql(
622
        targets["loads"]["table"],
623
        db.engine(),
624
        schema=targets["loads"]["schema"],
625
        index=False,
626
        if_exists="append",
627
    )
628
629
    # Insert time series
630
    ch4_demand_TS["Node/Line"] = ch4_demand_TS["Node/Line"].replace(
631
        ["UK00"], "GB"
632
    )
633
634
    p_set = []
635
    for index, row in ch4_demand_TS.iterrows():
636
        normalized_TS_df = normalized_ch4_demandTS.loc[
637
            :,
638
            normalized_ch4_demandTS.columns.str.contains(row["Node/Line"][:2]),
639
        ]
640
        p_set.append(
641
            (
642
                normalized_TS_df[normalized_TS_df.columns[0]]
643
                * row["GlobD_2035"]
644
            ).tolist()
645
        )
646
647
    ch4_demand_TS["p_set"] = p_set
648
    ch4_demand_TS["temp_id"] = 1
649
    ch4_demand_TS = ch4_demand_TS.drop(
650
        columns=["Node/Line", "GlobD_2035", "bus", "carrier"]
651
    )
652
653
    # Insert data to DB
654
    ch4_demand_TS.to_sql(
655
        targets["load_timeseries"]["table"],
656
        db.engine(),
657
        schema=targets["load_timeseries"]["schema"],
658
        index=False,
659
        if_exists="append",
660
    )
661
662
663
def calc_ch4_storage_capacities():
664
    target_file = (
665
        Path(".") / "datasets" / "gas_data" / "data" / "IGGIELGN_Storages.csv"
666
    )
667
668
    ch4_storage_capacities = pd.read_csv(
669
        target_file,
670
        delimiter=";",
671
        decimal=".",
672
        usecols=["country_code", "param"],
673
    )
674
675
    ch4_storage_capacities = ch4_storage_capacities[
676
        ch4_storage_capacities["country_code"].isin(countries)
677
    ]
678
679
    map_countries_scigrid = {
680
        "AT": "AT00",
681
        "BE": "BE00",
682
        "CZ": "CZ00",
683
        "DK": "DKE1",
684
        "EE": "EE00",
685
        "EL": "GR00",
686
        "ES": "ES00",
687
        "FI": "FI00",
688
        "FR": "FR00",
689
        "GB": "UK00",
690
        "IT": "ITCN",
691
        "LT": "LT00",
692
        "LV": "LV00",
693
        "MT": "MT00",
694
        "NL": "NL00",
695
        "PL": "PL00",
696
        "PT": "PT00",
697
        "SE": "SE01",
698
    }
699
700
    # Define new columns
701
    max_workingGas_M_m3 = []
702
    end_year = []
703
704
    for index, row in ch4_storage_capacities.iterrows():
705
        param = ast.literal_eval(row["param"])
706
        end_year.append(param["end_year"])
707
        max_workingGas_M_m3.append(param["max_workingGas_M_m3"])
708
709
    end_year = [float("inf") if x is None else x for x in end_year]
710
    ch4_storage_capacities = ch4_storage_capacities.assign(end_year=end_year)
711
    ch4_storage_capacities = ch4_storage_capacities[
712
        ch4_storage_capacities["end_year"] >= 2035
713
    ]
714
715
    # Calculate e_nom
716
    conv_factor = (
717
        10830  # M_m3 to MWh - gross calorific value = 39 MJ/m3 (eurogas.org)
718
    )
719
    ch4_storage_capacities["e_nom"] = [
720
        conv_factor * i for i in max_workingGas_M_m3
721
    ]
722
723
    ch4_storage_capacities.drop(
724
        ["param", "end_year"],
725
        axis=1,
726
        inplace=True,
727
    )
728
729
    ch4_storage_capacities["Country"] = ch4_storage_capacities[
730
        "country_code"
731
    ].map(map_countries_scigrid)
732
    ch4_storage_capacities = ch4_storage_capacities.groupby(
733
        ["country_code"]
734
    ).agg(
735
        {
736
            "e_nom": "sum",
737
            "Country": "first",
738
        },
739
    )
740
741
    ch4_storage_capacities = ch4_storage_capacities.drop(["RU"])
742
    ch4_storage_capacities.loc[:, "bus"] = (
743
        get_foreign_gas_bus_id()
744
        .loc[ch4_storage_capacities.loc[:, "Country"]]
745
        .values
746
    )
747
748
    ch4_storage_capacities.drop(
749
        ["Country"],
750
        axis=1,
751
        inplace=True,
752
    )
753
    return ch4_storage_capacities
754
755
756
def calc_global_power_to_h2_demand():
757
    """Calculates H2 demand abroad for eGon2035 scenario
758
759
    Calculates global power demand abroad linked to H2 production.
760
    The data comes from TYNDP 2020 according to NEP 2021 from the
761
    scenario 'Distributed Energy', linear interpolate between 2030
762
    and 2040.
763
764
    Returns
765
    -------
766
    global_power_to_h2_demand : pandas.DataFrame
767
        Global hourly power-to-h2 demand per foreign node
768
769
    """
770
    sources = config.datasets()["gas_neighbours"]["sources"]
771
772
    file = zipfile.ZipFile(f"tyndp/{sources['tyndp_capacities']}")
773
    df = pd.read_excel(
774
        file.open("TYNDP-2020-Scenario-Datafile.xlsx").read(),
775
        sheet_name="Gas Data",
776
    )
777
778
    df = (
779
        df.query(
780
            'Scenario == "Distributed Energy" & '
781
            'Case == "Average" &'
782
            'Parameter == "P2H2"'
783
        )
784
        .drop(
785
            columns=[
786
                "Generator_ID",
787
                "Climate Year",
788
                "Simulation_ID",
789
                "Node 1",
790
                "Path",
791
                "Direct/Indirect",
792
                "Sector",
793
                "Note",
794
                "Category",
795
                "Case",
796
                "Scenario",
797
                "Parameter",
798
            ]
799
        )
800
        .set_index("Node/Line")
801
    )
802
803
    df_2030 = (
804
        df[df["Year"] == 2030]
805
        .rename(columns={"Value": "Value_2030"})
806
        .drop(columns=["Year"])
807
    )
808
    df_2040 = (
809
        df[df["Year"] == 2040]
810
        .rename(columns={"Value": "Value_2040"})
811
        .drop(columns=["Year"])
812
    )
813
814
    # Conversion GWh/d to MWh/h
815
    conversion_factor = 1000 / 24
816
817
    df_2035 = pd.concat([df_2040, df_2030], axis=1)
818
    df_2035["GlobD_2035"] = (
819
        (df_2035["Value_2030"] + df_2035["Value_2040"]) / 2
820
    ) * conversion_factor
821
822
    global_power_to_h2_demand = df_2035.drop(
823
        columns=["Value_2030", "Value_2040"]
824
    )
825
826
    # choose demands for considered countries
827
    global_power_to_h2_demand = global_power_to_h2_demand[
828
        (global_power_to_h2_demand.index.str[:2].isin(countries))
829
        & (global_power_to_h2_demand["GlobD_2035"] != 0)
830
    ]
831
832
    # Split in two the demands for DK and UK
833
    global_power_to_h2_demand.loc["DKW1"] = (
834
        global_power_to_h2_demand.loc["DKE1"] / 2
835
    )
836
    global_power_to_h2_demand.loc["DKE1"] = (
837
        global_power_to_h2_demand.loc["DKE1"] / 2
838
    )
839
    global_power_to_h2_demand.loc["UKNI"] = (
840
        global_power_to_h2_demand.loc["UK00"] / 2
841
    )
842
    global_power_to_h2_demand.loc["UK00"] = (
843
        global_power_to_h2_demand.loc["UK00"] / 2
844
    )
845
    global_power_to_h2_demand = global_power_to_h2_demand.reset_index()
846
847
    return global_power_to_h2_demand
848
849
850
def insert_power_to_h2_demand(global_power_to_h2_demand):
851
    """Insert H2 demands into database for eGon2035
852
853
    Detailled description
854
    This function inserts data in the database and has no return.
855
856
    Parameters
857
    ----------
858
    global_power_to_h2_demand : pandas.DataFrame
859
        Global hourly power-to-h2 demand per foreign node
860
861
    """
862
    sources = config.datasets()["gas_neighbours"]["sources"]
863
    targets = config.datasets()["gas_neighbours"]["targets"]
864
    map_buses = get_map_buses()
865
866
    scn_name = "eGon2035"
867
    carrier = "H2_for_industry"
868
869
    db.execute_sql(
870
        f"""
871
        DELETE FROM
872
        {targets['loads']['schema']}.{targets['loads']['table']}
873
        WHERE bus IN (
874
            SELECT bus_id FROM
875
            {sources['buses']['schema']}.{sources['buses']['table']}
876
            WHERE country != 'DE'
877
            AND scn_name = '{scn_name}')
878
        AND scn_name = '{scn_name}'
879
        AND carrier = '{carrier}'
880
        """
881
    )
882
883
    # Set bus_id
884
    global_power_to_h2_demand.loc[
885
        global_power_to_h2_demand[
886
            global_power_to_h2_demand["Node/Line"].isin(map_buses.keys())
887
        ].index,
888
        "Node/Line",
889
    ] = global_power_to_h2_demand.loc[
890
        global_power_to_h2_demand[
891
            global_power_to_h2_demand["Node/Line"].isin(map_buses.keys())
892
        ].index,
893
        "Node/Line",
894
    ].map(
895
        map_buses
896
    )
897
    global_power_to_h2_demand.loc[:, "bus"] = (
898
        get_foreign_bus_id()
899
        .loc[global_power_to_h2_demand.loc[:, "Node/Line"]]
900
        .values
901
    )
902
903
    # Add missing columns
904
    c = {"scn_name": scn_name, "carrier": carrier}
905
    global_power_to_h2_demand = global_power_to_h2_demand.assign(**c)
906
907
    new_id = db.next_etrago_id("load")
908
    global_power_to_h2_demand["load_id"] = range(
909
        new_id, new_id + len(global_power_to_h2_demand)
910
    )
911
912
    global_power_to_h2_demand = global_power_to_h2_demand.rename(
913
        columns={"GlobD_2035": "p_set"}
914
    )
915
916
    # Remove useless columns
917
    global_power_to_h2_demand = global_power_to_h2_demand.drop(
918
        columns=["Node/Line"]
919
    )
920
921
    # Insert data to db
922
    global_power_to_h2_demand.to_sql(
923
        targets["loads"]["table"],
924
        db.engine(),
925
        schema=targets["loads"]["schema"],
926
        index=False,
927
        if_exists="append",
928
    )
929
930
931
def calculate_ch4_grid_capacities():
932
    """Calculates CH4 grid capacities for foreign countries based on TYNDP-data
933
934
    Parameters
935
    ----------
936
    None.
937
938
    Returns
939
    -------
940
    Neighbouring_pipe_capacities_list : pandas.DataFrame
941
942
    """
943
    sources = config.datasets()["gas_neighbours"]["sources"]
944
945
    # Download file
946
    basename = "ENTSOG_TYNDP_2020_Annex_C2_Capacities_per_country.xlsx"
947
    url = "https://www.entsog.eu/sites/default/files/2021-07/" + basename
948
    target_file = Path(".") / "datasets" / "gas_data" / basename
949
950
    urlretrieve(url, target_file)
951
    map_pipelines = {
952
        "NORDSTREAM": "RU00",
953
        "NORDSTREAM 2": "RU00",
954
        "OPAL": "DE",
955
        "YAMAL (BY)": "RU00",
956
        "Denmark": "DKE1",
957
        "Belgium": "BE00",
958
        "Netherlands": "NL00",
959
        "Norway": "NOM1",
960
        "Switzerland": "CH00",
961
        "Poland": "PL00",
962
        "United Kingdom": "UK00",
963
        "Germany": "DE",
964
        "Austria": "AT00",
965
        "France": "FR00",
966
        "Czechia": "CZ00",
967
        "Russia": "RU00",
968
        "Luxemburg": "LUB1",
969
    }
970
971
    grid_countries = [
972
        "NORDSTREAM",
973
        "NORDSTREAM 2",
974
        "OPAL",
975
        "YAMAL (BY)",
976
        "Denmark",
977
        "Belgium",
978
        "Netherlands",
979
        "Norway",
980
        "Switzerland",
981
        "Poland",
982
        "United Kingdom",
983
        "Germany",
984
        "Austria",
985
        "France",
986
        "Czechia",
987
        "Russia",
988
        "Luxemburg",
989
    ]
990
991
    # Read-in data from csv-file
992
    pipe_capacities_list = pd.read_excel(
993
        target_file,
994
        sheet_name="Transmission Peak Capacity",
995
        skiprows=range(4),
996
    )
997
    pipe_capacities_list = pipe_capacities_list[
998
        ["To Country", "Unnamed: 3", "From Country", 2035]
999
    ].rename(
1000
        columns={
1001
            "Unnamed: 3": "Scenario",
1002
            "To Country": "To_Country",
1003
            "From Country": "From_Country",
1004
        }
1005
    )
1006
    pipe_capacities_list["To_Country"] = pd.Series(
1007
        pipe_capacities_list["To_Country"]
1008
    ).fillna(method="ffill")
1009
    pipe_capacities_list["From_Country"] = pd.Series(
1010
        pipe_capacities_list["From_Country"]
1011
    ).fillna(method="ffill")
1012
    pipe_capacities_list = pipe_capacities_list[
1013
        pipe_capacities_list["Scenario"] == "Advanced"
1014
    ].drop(columns={"Scenario"})
1015
    pipe_capacities_list = pipe_capacities_list[
1016
        (
1017
            (pipe_capacities_list["To_Country"].isin(grid_countries))
1018
            & (pipe_capacities_list["From_Country"].isin(grid_countries))
1019
        )
1020
        & (pipe_capacities_list[2035] != 0)
1021
    ]
1022
    pipe_capacities_list["To_Country"] = pipe_capacities_list[
1023
        "To_Country"
1024
    ].map(map_pipelines)
1025
    pipe_capacities_list["From_Country"] = pipe_capacities_list[
1026
        "From_Country"
1027
    ].map(map_pipelines)
1028
    pipe_capacities_list["countrycombination"] = pipe_capacities_list[
1029
        ["To_Country", "From_Country"]
1030
    ].apply(
1031
        lambda x: tuple(sorted([str(x.To_Country), str(x.From_Country)])),
1032
        axis=1,
1033
    )
1034
1035
    pipeline_strategies = {
1036
        "To_Country": "first",
1037
        "From_Country": "first",
1038
        2035: sum,
1039
    }
1040
1041
    pipe_capacities_list = pipe_capacities_list.groupby(
1042
        ["countrycombination"]
1043
    ).agg(pipeline_strategies)
1044
1045
    # Add manually DK-SE and AT-CH pipes (Scigrid gas data)
1046
    pipe_capacities_list.loc["(DKE1, SE02)"] = ["DKE1", "SE02", 651]
1047
    pipe_capacities_list.loc["(AT00, CH00)"] = ["AT00", "CH00", 651]
1048
1049
    # Conversion GWh/d to MWh/h
1050
    pipe_capacities_list["p_nom"] = pipe_capacities_list[2035] * (1000 / 24)
1051
1052
    # Border crossing CH4 pipelines between foreign countries
1053
1054
    Neighbouring_pipe_capacities_list = pipe_capacities_list[
1055
        (pipe_capacities_list["To_Country"] != "DE")
1056
        & (pipe_capacities_list["From_Country"] != "DE")
1057
    ].reset_index()
1058
1059
    Neighbouring_pipe_capacities_list.loc[:, "bus0"] = (
1060
        get_foreign_gas_bus_id()
1061
        .loc[Neighbouring_pipe_capacities_list.loc[:, "To_Country"]]
1062
        .values
1063
    )
1064
    Neighbouring_pipe_capacities_list.loc[:, "bus1"] = (
1065
        get_foreign_gas_bus_id()
1066
        .loc[Neighbouring_pipe_capacities_list.loc[:, "From_Country"]]
1067
        .values
1068
    )
1069
1070
    # Adjust columns
1071
    Neighbouring_pipe_capacities_list = Neighbouring_pipe_capacities_list.drop(
1072
        columns=[
1073
            "To_Country",
1074
            "From_Country",
1075
            "countrycombination",
1076
            2035,
1077
        ]
1078
    )
1079
1080
    new_id = db.next_etrago_id("link")
1081
    Neighbouring_pipe_capacities_list["link_id"] = range(
1082
        new_id, new_id + len(Neighbouring_pipe_capacities_list)
1083
    )
1084
1085
    # Border crossing CH4 pipelines between DE and neighbouring countries
1086
    DE_pipe_capacities_list = pipe_capacities_list[
1087
        (pipe_capacities_list["To_Country"] == "DE")
1088
        | (pipe_capacities_list["From_Country"] == "DE")
1089
    ].reset_index()
1090
1091
    dict_cross_pipes_DE = {
1092
        ("AT00", "DE"): "AT",
1093
        ("BE00", "DE"): "BE",
1094
        ("CH00", "DE"): "CH",
1095
        ("CZ00", "DE"): "CZ",
1096
        ("DE", "DKE1"): "DK",
1097
        ("DE", "FR00"): "FR",
1098
        ("DE", "LUB1"): "LU",
1099
        ("DE", "NL00"): "NL",
1100
        ("DE", "NOM1"): "NO",
1101
        ("DE", "PL00"): "PL",
1102
        ("DE", "RU00"): "RU",
1103
    }
1104
1105
    DE_pipe_capacities_list["country_code"] = DE_pipe_capacities_list[
1106
        "countrycombination"
1107
    ].map(dict_cross_pipes_DE)
1108
    DE_pipe_capacities_list = DE_pipe_capacities_list.set_index("country_code")
1109
1110
    schema = sources["buses"]["schema"]
1111
    table = sources["buses"]["table"]
1112
    for country_code in [e for e in countries if e not in ("GB", "SE", "UK")]:
1113
1114
        # Select cross-bording links
1115
        cap_DE = db.select_dataframe(
1116
            f"""SELECT link_id, bus0, bus1
1117
                FROM {sources['links']['schema']}.{sources['links']['table']}
1118
                    WHERE scn_name = 'eGon2035'
1119
                    AND carrier = 'CH4'
1120
                    AND (("bus0" IN (
1121
                        SELECT bus_id FROM {schema}.{table}
1122
                            WHERE country = 'DE'
1123
                            AND carrier = 'CH4'
1124
                            AND scn_name = 'eGon2035')
1125
                        AND "bus1" IN (SELECT bus_id FROM {schema}.{table}
1126
                            WHERE country = '{country_code}'
1127
                            AND carrier = 'CH4'
1128
                            AND scn_name = 'eGon2035')
1129
                    )
1130
                    OR ("bus0" IN (
1131
                        SELECT bus_id FROM {schema}.{table}
1132
                            WHERE country = '{country_code}'
1133
                            AND carrier = 'CH4'
1134
                            AND scn_name = 'eGon2035')
1135
                        AND "bus1" IN (SELECT bus_id FROM {schema}.{table}
1136
                            WHERE country = 'DE'
1137
                            AND carrier = 'CH4'
1138
                            AND scn_name = 'eGon2035'))
1139
                    )
1140
            ;"""
1141
        )
1142
1143
        cap_DE["p_nom"] = DE_pipe_capacities_list.at[
1144
            country_code, "p_nom"
1145
        ] / len(cap_DE.index)
1146
        Neighbouring_pipe_capacities_list = (
1147
            Neighbouring_pipe_capacities_list.append(cap_DE)
1148
        )
1149
1150
    # Add topo, geom and length
1151
    bus_geom = db.select_geodataframe(
1152
        """SELECT bus_id, geom
1153
        FROM grid.egon_etrago_bus
1154
        WHERE scn_name = 'eGon2035'
1155
        AND carrier = 'CH4'
1156
        """,
1157
        epsg=4326,
1158
    ).set_index("bus_id")
1159
1160
    coordinates_bus0 = []
1161
    coordinates_bus1 = []
1162
1163
    for index, row in Neighbouring_pipe_capacities_list.iterrows():
1164
        coordinates_bus0.append(bus_geom["geom"].loc[int(row["bus0"])])
1165
        coordinates_bus1.append(bus_geom["geom"].loc[int(row["bus1"])])
1166
1167
    Neighbouring_pipe_capacities_list["coordinates_bus0"] = coordinates_bus0
1168
    Neighbouring_pipe_capacities_list["coordinates_bus1"] = coordinates_bus1
1169
1170
    Neighbouring_pipe_capacities_list[
1171
        "topo"
1172
    ] = Neighbouring_pipe_capacities_list.apply(
1173
        lambda row: LineString(
1174
            [row["coordinates_bus0"], row["coordinates_bus1"]]
1175
        ),
1176
        axis=1,
1177
    )
1178
    Neighbouring_pipe_capacities_list[
1179
        "geom"
1180
    ] = Neighbouring_pipe_capacities_list.apply(
1181
        lambda row: MultiLineString([row["topo"]]), axis=1
1182
    )
1183
    Neighbouring_pipe_capacities_list[
1184
        "length"
1185
    ] = Neighbouring_pipe_capacities_list.apply(
1186
        lambda row: row["topo"].length, axis=1
1187
    )
1188
1189
    # Remove useless columns
1190
    Neighbouring_pipe_capacities_list = Neighbouring_pipe_capacities_list.drop(
1191
        columns=[
1192
            "coordinates_bus0",
1193
            "coordinates_bus1",
1194
        ]
1195
    )
1196
1197
    # Add missing columns
1198
    c = {"scn_name": "eGon2035", "carrier": "CH4", "p_min_pu": -1.0}
1199
    Neighbouring_pipe_capacities_list = (
1200
        Neighbouring_pipe_capacities_list.assign(**c)
1201
    )
1202
1203
    Neighbouring_pipe_capacities_list = (
1204
        Neighbouring_pipe_capacities_list.set_geometry("geom", crs=4326)
1205
    )
1206
1207
    return Neighbouring_pipe_capacities_list
1208
1209
1210
def tyndp_gas_generation():
1211
    """Insert data from TYNDP 2020 accordning to NEP 2021
1212
    Scenario 'Distributed Energy', linear interpolate between 2030 and 2040
1213
1214
    Returns
1215
    -------
1216
    None.
1217
    """
1218
    capacities = calc_capacities()
1219
    insert_generators(capacities, "eGon2035")
1220
1221
    ch4_storage_capacities = calc_ch4_storage_capacities()
1222
    insert_ch4_stores(ch4_storage_capacities, "eGon2035")
1223
1224
1225
def tyndp_gas_demand():
1226
    """Insert gas demands abroad for eGon2035
1227
1228
    Insert CH4 and H2 demands abroad for eGon2035 by executing the
1229
    following steps:
1230
      * CH4
1231
          * Calculation of the global CH4 demand in Norway and of the
1232
            CH4 demand profile by executing the function
1233
            :py:func:`import_ch4_demandTS`
1234
          * Calculation of the global CH4 demands by executing the
1235
            function :py:func:`calc_global_ch4_demand`
1236
          * Insertion the CH4 loads and their associated time series
1237
            in the database by executing the function
1238
            :py:func:`insert_ch4_demand`
1239
      * H2
1240
          * Calculation of the global power demand abroad linked
1241
            to H2 production by executing the function
1242
            :py:func:`calc_global_power_to_h2_demand`
1243
          * Insertion of these loads in the database by executing the
1244
            function :py:func:`insert_power_to_h2_demand`
1245
    This function insert data in the database and has no return.
1246
1247
    """
1248
    Norway_global_demand_1y, normalized_ch4_demandTS = import_ch4_demandTS()
1249
    global_ch4_demand = calc_global_ch4_demand(Norway_global_demand_1y)
1250
    insert_ch4_demand(global_ch4_demand, normalized_ch4_demandTS)
1251
1252
    global_power_to_h2_demand = calc_global_power_to_h2_demand()
1253
    insert_power_to_h2_demand(global_power_to_h2_demand)
1254
1255
1256
def grid():
1257
    """Insert data from TYNDP 2020 accordning to NEP 2021
1258
    Scenario 'Distributed Energy', linear interpolate between 2030 and 2040
1259
1260
    Returns
1261
    -------
1262
    None.
1263
    """
1264
    Neighbouring_pipe_capacities_list = calculate_ch4_grid_capacities()
1265
    insert_gas_grid_capacities(
1266
        Neighbouring_pipe_capacities_list, scn_name="eGon2035"
1267
    )
1268
1269
1270
def calculate_ocgt_capacities():
1271
    """Calculate gas turbine capacities abroad for eGon2035
1272
1273
    Calculate gas turbine capacities abroad for eGon2035 based on TYNDP
1274
    2020, scenario "Distributed Energy", interpolated between 2030 and 2040
1275
1276
    Returns
1277
    -------
1278
    df_ocgt: pandas.DataFrame
1279
        Gas turbine capacities per foreign node
1280
1281
    """
1282
    sources = config.datasets()["gas_neighbours"]["sources"]
1283
1284
    # insert installed capacities
1285
    file = zipfile.ZipFile(f"tyndp/{sources['tyndp_capacities']}")
1286
    df = pd.read_excel(
1287
        file.open("TYNDP-2020-Scenario-Datafile.xlsx").read(),
1288
        sheet_name="Capacity",
1289
    )
1290
1291
    df_ocgt = df[
1292
        [
1293
            "Node/Line",
1294
            "Scenario",
1295
            "Climate Year",
1296
            "Generator_ID",
1297
            "Year",
1298
            "Value",
1299
        ]
1300
    ]
1301
    df_ocgt = df_ocgt[
1302
        (df_ocgt["Scenario"] == "Distributed Energy")
1303
        & (df_ocgt["Climate Year"] == 1984)
1304
    ]
1305
    df_ocgt = df_ocgt[df_ocgt["Generator_ID"].str.contains("Gas")]
1306
    df_ocgt = df_ocgt[df_ocgt["Year"].isin([2030, 2040])]
1307
1308
    df_ocgt = (
1309
        df_ocgt.groupby(["Node/Line", "Year"])["Value"].sum().reset_index()
1310
    )
1311
    df_ocgt = df_ocgt.groupby([df_ocgt["Node/Line"], "Year"]).sum()
1312
    df_ocgt = df_ocgt.groupby("Node/Line")["Value"].mean()
1313
    df_ocgt = pd.DataFrame(df_ocgt, columns=["Value"]).rename(
1314
        columns={"Value": "p_nom"}
1315
    )
1316
1317
    # Choose capacities for considered countries
1318
    df_ocgt = df_ocgt[df_ocgt.index.str[:2].isin(countries)]
1319
1320
    # Attribute bus0 and bus1
1321
    df_ocgt["bus0"] = get_foreign_gas_bus_id()[df_ocgt.index]
1322
    df_ocgt["bus1"] = get_foreign_bus_id()[df_ocgt.index]
1323
    df_ocgt = df_ocgt.groupby(by=["bus0", "bus1"], as_index=False).sum()
1324
1325
    return df_ocgt
1326
1327
1328
def insert_ocgt_abroad():
1329
    """Insert gas turbine capicities abroad for eGon2035 in the database
1330
1331
    This function inserts data in the database and has no return.
1332
1333
    Parameters
1334
    ----------
1335
    df_ocgt: pandas.DataFrame
1336
        Gas turbine capacities per foreign node
1337
1338
    """
1339
    scn_name = "eGon2035"
1340
    carrier = "OCGT"
1341
1342
    # Connect to local database
1343
    engine = db.engine()
1344
1345
    df_ocgt = calculate_ocgt_capacities()
1346
1347
    df_ocgt["p_nom_extendable"] = False
1348
    df_ocgt["carrier"] = carrier
1349
    df_ocgt["scn_name"] = scn_name
1350
1351
    buses = tuple(
1352
        db.select_dataframe(
1353
            f"""SELECT bus_id FROM grid.egon_etrago_bus
1354
            WHERE scn_name = '{scn_name}' AND country != 'DE';
1355
        """
1356
        )["bus_id"]
1357
    )
1358
1359
    # Delete old entries
1360
    db.execute_sql(
1361
        f"""
1362
        DELETE FROM grid.egon_etrago_link WHERE "carrier" = '{carrier}'
1363
        AND scn_name = '{scn_name}'
1364
        AND bus0 IN {buses} AND bus1 IN {buses};
1365
        """
1366
    )
1367
1368
    # read carrier information from scnario parameter data
1369
    scn_params = get_sector_parameters("gas", scn_name)
1370
    df_ocgt["efficiency"] = scn_params["efficiency"][carrier]
1371
    df_ocgt["marginal_cost"] = (
1372
        scn_params["marginal_cost"][carrier]
1373
        / scn_params["efficiency"][carrier]
1374
    )
1375
1376
    # Adjust p_nom
1377
    df_ocgt["p_nom"] = df_ocgt["p_nom"] / scn_params["efficiency"][carrier]
1378
1379
    # Select next id value
1380
    new_id = db.next_etrago_id("link")
1381
    df_ocgt["link_id"] = range(new_id, new_id + len(df_ocgt))
1382
1383
    # Insert data to db
1384
    df_ocgt.to_sql(
1385
        "egon_etrago_link",
1386
        engine,
1387
        schema="grid",
1388
        index=False,
1389
        if_exists="append",
1390
    )
1391