Passed
Pull Request — dev (#1080)
by
unknown
01:51
created

insert_ocgt_abroad()   A

Complexity

Conditions 1

Size

Total Lines 62
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 28
dl 0
loc 62
rs 9.208
c 0
b 0
f 0
cc 1
nop 0

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