Passed
Pull Request — dev (#1170)
by
unknown
05:05
created

insert_generators_tyndp()   B

Complexity

Conditions 4

Size

Total Lines 156
Code Lines 68

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 68
dl 0
loc 156
rs 8.0472
c 0
b 0
f 0
cc 4
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
"""The central module containing all code dealing with electrical neighbours
2
"""
3
4
from os import path
5
from pathlib import Path
6
import datetime
7
import logging
8
import os.path
9
import zipfile
10
11
from shapely.geometry import LineString
12
from sqlalchemy.orm import sessionmaker
13
import entsoe
14
import geopandas as gpd
15
import pandas as pd
16
import requests
17
18
from egon.data import config, db, logger
19
from egon.data.db import session_scope
20
from egon.data.datasets import Dataset, wrapped_partial
21
from egon.data.datasets.fill_etrago_gen import add_marginal_costs
22
from egon.data.datasets.fix_ehv_subnetworks import select_bus_id
23
from egon.data.datasets.scenario_parameters import get_sector_parameters
24
import egon.data.datasets.etrago_setup as etrago
25
import egon.data.datasets.scenario_parameters.parameters as scenario_parameters
26
27
28
class ElectricalNeighbours(Dataset):
29
    """
30
    Add lines, loads, generation and storage for electrical neighbours
31
32
    This dataset creates data for modelling the considered foreign countries and writes
33
    that data into the database tables that can be read by the eTraGo tool.
34
    Neighbouring countries are modelled in a lower spatial resolution, in general one node per
35
    country is considered.
36
    Defined load timeseries as well as generatrion and storage capacities are connected to these nodes.
37
    The nodes are connected by AC and DC transmission lines with the German grid and other neighbouring countries
38
    considering the grid topology from ENTSO-E.
39
40
41
    *Dependencies*
42
      * :py:class:`Tyndp <egon.data.datasets.tyndp.Tyndp>`
43
      * :py:class:`PypsaEurSec <egon.data.datasets.pypsaeursec.PypsaEurSec>`
44
45
46
    *Resulting tables*
47
      * :py:class:`grid.egon_etrago_bus <egon.data.datasets.etrago_setup.EgonPfHvBus>` is extended
48
      * :py:class:`grid.egon_etrago_link <egon.data.datasets.etrago_setup.EgonPfHvLink>` is extended
49
      * :py:class:`grid.egon_etrago_line <egon.data.datasets.etrago_setup.EgonPfHvLine>` is extended
50
      * :py:class:`grid.egon_etrago_load <egon.data.datasets.etrago_setup.EgonPfHvLoad>` is extended
51
      * :py:class:`grid.egon_etrago_load_timeseries <egon.data.datasets.etrago_setup.EgonPfHvLoadTimeseries>` is extended
52
      * :py:class:`grid.egon_etrago_storage <egon.data.datasets.etrago_setup.EgonPfHvStorageUnit>` is extended
53
      * :py:class:`grid.egon_etrago_generator <egon.data.datasets.etrago_setup.EgonPfHvGenerator>` is extended
54
      * :py:class:`grid.egon_etrago_generator_timeseries <egon.data.datasets.etrago_setup.EgonPfHvGeneratorTimeseries>` is extended
55
      * :py:class:`grid.egon_etrago_transformer <egon.data.datasets.etrago_setup.EgonPfHvTransformer>` is extended
56
      
57
    """
58
59
    #:
60
    name: str = "ElectricalNeighbours"
61
    #:
62
    version: str = "0.0.7"
63
64
    def __init__(self, dependencies):
65
        super().__init__(
66
            name=self.name,
67
            version=self.version,
68
            dependencies=dependencies,
69
            tasks=(grid, {tyndp_generation, tyndp_demand}),
70
        )
71
72
73
def get_cross_border_buses(scenario, sources):
74
    """Returns buses from osmTGmod which are outside of Germany.
75
76
    Parameters
77
    ----------
78
    sources : dict
79
        List of sources
80
81
    Returns
82
    -------
83
    geopandas.GeoDataFrame
84
        Electricity buses outside of Germany
85
86
    """
87
    return db.select_geodataframe(
88
        f"""
89
        SELECT *
90
        FROM {sources['electricity_buses']['schema']}.
91
            {sources['electricity_buses']['table']}
92
        WHERE
93
        NOT ST_INTERSECTS (
94
            geom,
95
            (SELECT ST_Transform(ST_Buffer(geometry, 5), 4326) FROM
96
             {sources['german_borders']['schema']}.
97
            {sources['german_borders']['table']}))
98
        AND (bus_id IN (
99
            SELECT bus0 FROM
100
            {sources['lines']['schema']}.{sources['lines']['table']})
101
            OR bus_id IN (
102
            SELECT bus1 FROM
103
            {sources['lines']['schema']}.{sources['lines']['table']}))
104
        AND scn_name = '{scenario}';
105
        """,
106
        epsg=4326,
107
    )
108
109
110
def get_cross_border_lines(scenario, sources):
111
    """Returns lines from osmTGmod which end or start outside of Germany.
112
113
    Parameters
114
    ----------
115
    sources : dict
116
        List of sources
117
118
    Returns
119
    -------
120
    geopandas.GeoDataFrame
121
        AC-lines outside of Germany
122
123
    """
124
    return db.select_geodataframe(
125
        f"""
126
    SELECT *
127
    FROM {sources['lines']['schema']}.{sources['lines']['table']} a
128
    WHERE
129
    ST_INTERSECTS (
130
        a.topo,
131
        (SELECT ST_Transform(ST_boundary(geometry), 4326)
132
         FROM {sources['german_borders']['schema']}.
133
        {sources['german_borders']['table']}))
134
    AND scn_name = '{scenario}';
135
    """,
136
        epsg=4326,
137
    )
138
139
140
def central_buses_egon100(sources):
141
    """Returns buses in the middle of foreign countries based on eGon100RE
142
143
    Parameters
144
    ----------
145
    sources : dict
146
        List of sources
147
148
    Returns
149
    -------
150
    pandas.DataFrame
151
        Buses in the center of foreign countries
152
153
    """
154
    return db.select_dataframe(
155
        f"""
156
        SELECT *
157
        FROM {sources['electricity_buses']['schema']}.
158
            {sources['electricity_buses']['table']}
159
        WHERE country != 'DE'
160
        AND scn_name = 'eGon100RE'
161
        AND bus_id NOT IN (
162
            SELECT bus_i
163
            FROM {sources['osmtgmod_bus']['schema']}.
164
            {sources['osmtgmod_bus']['table']})
165
        AND carrier = 'AC'
166
        """
167
    )
168
169
170
def buses(scenario, sources, targets):
171
    """Insert central buses in foreign countries per scenario
172
173
    Parameters
174
    ----------
175
    sources : dict
176
        List of dataset sources
177
    targets : dict
178
        List of dataset targets
179
180
    Returns
181
    -------
182
    central_buses : geoapndas.GeoDataFrame
183
        Buses in the center of foreign countries
184
185
    """
186
    sql_delete = f"""
187
        DELETE FROM {sources['electricity_buses']['schema']}.
188
            {sources['electricity_buses']['table']}
189
        WHERE country != 'DE' AND scn_name = '{scenario}'
190
        AND carrier = 'AC'
191
        AND bus_id NOT IN (
192
            SELECT bus_i
193
            FROM  {sources['osmtgmod_bus']['schema']}.
194
            {sources['osmtgmod_bus']['table']})
195
        """
196
    # Drop only buses with v_nom != 380 for eGon100RE
197
    # to keep buses from pypsa-eur-sec
198
    if scenario == "eGon100RE":
199
        sql_delete += "AND v_nom < 380"
200
201
    # Delete existing buses
202
    db.execute_sql(sql_delete)
203
204
    central_buses = central_buses_egon100(sources)
205
206
    next_bus_id = db.next_etrago_id("bus") + 1
207
208
    # if in test mode, add bus in center of Germany
209
    if config.settings()["egon-data"]["--dataset-boundary"] != "Everything":
210
        central_buses = pd.concat(
211
            [
212
                central_buses,
213
                pd.DataFrame(
214
                    index=[central_buses.index.max() + 1],
215
                    data={
216
                        "scn_name": scenario,
217
                        "bus_id": next_bus_id,
218
                        "x": 10.4234469,
219
                        "y": 51.0834196,
220
                        "country": "DE",
221
                        "carrier": "AC",
222
                        "v_nom": 380.0,
223
                    },
224
                ),
225
            ],
226
            ignore_index=True,
227
        )
228
        next_bus_id += 1
229
230
    # Add buses for other voltage levels
231
    foreign_buses = get_cross_border_buses(scenario, sources)
232
    if config.settings()["egon-data"]["--dataset-boundary"] == "Everything":
233
        foreign_buses = foreign_buses[foreign_buses.country != "DE"]
234
    vnom_per_country = foreign_buses.groupby("country").v_nom.unique().copy()
235
    for cntr in vnom_per_country.index:
236
        print(cntr)
237 View Code Duplication
        if 110.0 in vnom_per_country[cntr]:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
238
            central_buses = pd.concat(
239
                [
240
                    central_buses,
241
                    pd.DataFrame(
242
                        index=[central_buses.index.max() + 1],
243
                        data={
244
                            "scn_name": scenario,
245
                            "bus_id": next_bus_id,
246
                            "x": central_buses[
247
                                central_buses.country == cntr
248
                            ].x.unique()[0],
249
                            "y": central_buses[
250
                                central_buses.country == cntr
251
                            ].y.unique()[0],
252
                            "country": cntr,
253
                            "carrier": "AC",
254
                            "v_nom": 110.0,
255
                        },
256
                    ),
257
                ],
258
                ignore_index=True,
259
            )
260
            next_bus_id += 1
261 View Code Duplication
        if 220.0 in vnom_per_country[cntr]:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
262
            central_buses = pd.concat(
263
                [
264
                    central_buses,
265
                    pd.DataFrame(
266
                        index=[central_buses.index.max() + 1],
267
                        data={
268
                            "scn_name": scenario,
269
                            "bus_id": next_bus_id,
270
                            "x": central_buses[
271
                                central_buses.country == cntr
272
                            ].x.unique()[0],
273
                            "y": central_buses[
274
                                central_buses.country == cntr
275
                            ].y.unique()[0],
276
                            "country": cntr,
277
                            "carrier": "AC",
278
                            "v_nom": 220.0,
279
                        },
280
                    ),
281
                ],
282
                ignore_index=True,
283
            )
284
            next_bus_id += 1
285
286
    # Add geometry column
287
    central_buses = gpd.GeoDataFrame(
288
        central_buses,
289
        geometry=gpd.points_from_xy(central_buses.x, central_buses.y),
290
        crs="EPSG:4326",
291
    )
292
    central_buses["geom"] = central_buses.geometry.copy()
293
    central_buses = central_buses.set_geometry("geom").drop(
294
        "geometry", axis="columns"
295
    )
296
    central_buses.scn_name = scenario
297
298
    # Insert all central buses for eGon2035
299
    if scenario in [
300
        "eGon2035",
301
        "status2019",
302
        "status2023",
303
    ]:  # TODO: status2023 this is hardcoded shit
304
        central_buses.to_postgis(
305
            targets["buses"]["table"],
306
            schema=targets["buses"]["schema"],
307
            if_exists="append",
308
            con=db.engine(),
309
            index=False,
310
        )
311
    # Insert only buses for eGon100RE that are not coming from pypsa-eur-sec
312
    # (buses with another voltage_level or inside Germany in test mode)
313
    else:
314
        central_buses[
315
            (central_buses.v_nom != 380) | (central_buses.country == "DE")
316
        ].to_postgis(
317
            targets["buses"]["table"],
318
            schema=targets["buses"]["schema"],
319
            if_exists="append",
320
            con=db.engine(),
321
            index=False,
322
        )
323
324
    return central_buses
325
326
327
def cross_border_lines(scenario, sources, targets, central_buses):
328
    """Adds lines which connect border-crossing lines from osmtgmod
329
    to the central buses in the corresponding neigbouring country
330
331
    Parameters
332
    ----------
333
    sources : dict
334
        List of dataset sources
335
    targets : dict
336
        List of dataset targets
337
    central_buses : geopandas.GeoDataFrame
338
        Buses in the center of foreign countries
339
340
    Returns
341
    -------
342
    new_lines : geopandas.GeoDataFrame
343
        Lines that connect cross-border lines to central bus per country
344
345
    """
346
    # Delete existing data
347
    db.execute_sql(
348
        f"""
349
        DELETE FROM {targets['lines']['schema']}.
350
        {targets['lines']['table']}
351
        WHERE scn_name = '{scenario}'
352
        AND line_id NOT IN (
353
            SELECT branch_id
354
            FROM  {sources['osmtgmod_branch']['schema']}.
355
            {sources['osmtgmod_branch']['table']}
356
              WHERE result_id = 1 and (link_type = 'line' or
357
                                       link_type = 'cable'))
358
        AND bus0 IN (
359
            SELECT bus_i
360
            FROM  {sources['osmtgmod_bus']['schema']}.
361
            {sources['osmtgmod_bus']['table']})
362
        AND bus1 NOT IN (
363
            SELECT bus_i
364
            FROM  {sources['osmtgmod_bus']['schema']}.
365
            {sources['osmtgmod_bus']['table']})
366
        """
367
    )
368
369
    # Calculate cross-border busses and lines from osmtgmod
370
    foreign_buses = get_cross_border_buses(scenario, sources)
371
    if config.settings()["egon-data"]["--dataset-boundary"] == "Everything":
372
        foreign_buses = foreign_buses[foreign_buses.country != "DE"]
373
    lines = get_cross_border_lines(scenario, sources)
374
375
    # Select bus outside of Germany from border-crossing lines
376
    lines.loc[
377
        lines[lines.bus0.isin(foreign_buses.bus_id)].index, "foreign_bus"
378
    ] = lines.loc[lines[lines.bus0.isin(foreign_buses.bus_id)].index, "bus0"]
379
    lines.loc[
380
        lines[lines.bus1.isin(foreign_buses.bus_id)].index, "foreign_bus"
381
    ] = lines.loc[lines[lines.bus1.isin(foreign_buses.bus_id)].index, "bus1"]
382
383
    # Drop lines with start and endpoint in Germany
384
    lines = lines[lines.foreign_bus.notnull()]
385
    lines.loc[:, "foreign_bus"] = lines.loc[:, "foreign_bus"].astype(int)
386
387
    # Copy all parameters from border-crossing lines
388
    new_lines = lines.copy().set_crs(4326)
389
390
    # Set bus0 as foreign_bus from osmtgmod
391
    new_lines.bus0 = new_lines.foreign_bus.copy()
392
    new_lines.bus0 = new_lines.bus0.astype(int)
393
394
    # Add country tag and set index
395
    new_lines["country"] = (
396
        foreign_buses.set_index("bus_id")
397
        .loc[lines.foreign_bus, "country"]
398
        .values
399
    )
400
401
    if config.settings()["egon-data"]["--dataset-boundary"] == "Everything":
402
        new_lines = new_lines[~new_lines.country.isnull()]
403
    new_lines.line_id = range(
404
        db.next_etrago_id("line"), db.next_etrago_id("line") + len(new_lines)
405
    )
406
407
    # Set bus in center of foreogn countries as bus1
408
    for i, row in new_lines.iterrows():
409
        print(row)
410
        new_lines.loc[i, "bus1"] = central_buses.bus_id[
411
            (central_buses.country == row.country)
412
            & (central_buses.v_nom == row.v_nom)
413
        ].values[0]
414
415
    # Create geometry for new lines
416
    new_lines["geom_bus0"] = (
417
        foreign_buses.set_index("bus_id").geom[new_lines.bus0].values
418
    )
419
    new_lines["geom_bus1"] = (
420
        central_buses.set_index("bus_id").geom[new_lines.bus1].values
421
    )
422
    new_lines["topo"] = new_lines.apply(
423
        lambda x: LineString([x["geom_bus0"], x["geom_bus1"]]), axis=1
424
    )
425
426
    # Set topo as geometry column
427
    new_lines = new_lines.set_geometry("topo").set_crs(4326)
428
    # Calcultae length of lines based on topology
429
    old_length = new_lines["length"].copy()
430
    new_lines["length"] = new_lines.to_crs(3035).length / 1000
431
432
    # Set electrical parameters based on lines from osmtgmod
433
    for parameter in ["x", "r"]:
434
        new_lines[parameter] = (
435
            new_lines[parameter] / old_length * new_lines["length"]
436
        )
437
    for parameter in ["b", "g"]:
438
        new_lines[parameter] = (
439
            new_lines[parameter] * old_length / new_lines["length"]
440
        )
441
442
    # Drop intermediate columns
443
    new_lines.drop(
444
        ["foreign_bus", "country", "geom_bus0", "geom_bus1", "geom"],
445
        axis="columns",
446
        inplace=True,
447
    )
448
449
    new_lines = new_lines[new_lines.bus0 != new_lines.bus1]
450
451
    # Set scn_name
452
453
    # Insert lines to the database
454
    new_lines.to_postgis(
455
        targets["lines"]["table"],
456
        schema=targets["lines"]["schema"],
457
        if_exists="append",
458
        con=db.engine(),
459
        index=False,
460
    )
461
462
    return new_lines
463
464
465
def choose_transformer(s_nom):
466
    """Select transformer and parameters from existing data in the grid model
467
468
    It is assumed that transformers in the foreign countries are not limiting
469
    the electricity flow, so the capacitiy s_nom is set to the minimum sum
470
    of attached AC-lines.
471
    The electrical parameters are set according to already inserted
472
    transformers in the grid model for Germany.
473
474
    Parameters
475
    ----------
476
    s_nom : float
477
        Minimal sum of nominal power of lines at one side
478
479
    Returns
480
    -------
481
    int
482
        Selected transformer nominal power
483
    float
484
        Selected transformer nominal impedance
485
486
    """
487
488
    if s_nom <= 600:
489
        return 600, 0.0002
490
    elif (s_nom > 600) & (s_nom <= 1200):
491
        return 1200, 0.0001
492
    elif (s_nom > 1200) & (s_nom <= 1600):
493
        return 1600, 0.000075
494
    elif (s_nom > 1600) & (s_nom <= 2100):
495
        return 2100, 0.00006667
496
    elif (s_nom > 2100) & (s_nom <= 2600):
497
        return 2600, 0.0000461538
498
    elif (s_nom > 2600) & (s_nom <= 4800):
499
        return 4800, 0.000025
500
    elif (s_nom > 4800) & (s_nom <= 6000):
501
        return 6000, 0.0000225
502
    elif (s_nom > 6000) & (s_nom <= 7200):
503
        return 7200, 0.0000194444
504
    elif (s_nom > 7200) & (s_nom <= 8000):
505
        return 8000, 0.000016875
506
    elif (s_nom > 8000) & (s_nom <= 9000):
507
        return 9000, 0.000015
508
    elif (s_nom > 9000) & (s_nom <= 13000):
509
        return 13000, 0.0000103846
510
    elif (s_nom > 13000) & (s_nom <= 20000):
511
        return 20000, 0.00000675
512
    elif (s_nom > 20000) & (s_nom <= 33000):
513
        return 33000, 0.00000409091
514
515
516
def central_transformer(scenario, sources, targets, central_buses, new_lines):
517
    """Connect central foreign buses with different voltage levels
518
519
    Parameters
520
    ----------
521
    sources : dict
522
        List of dataset sources
523
    targets : dict
524
        List of dataset targets
525
    central_buses : geopandas.GeoDataFrame
526
        Buses in the center of foreign countries
527
    new_lines : geopandas.GeoDataFrame
528
        Lines that connect cross-border lines to central bus per country
529
530
    Returns
531
    -------
532
    None.
533
534
    """
535
    # Delete existing transformers in foreign countries
536
    db.execute_sql(
537
        f"""
538
        DELETE FROM {targets['transformers']['schema']}.
539
        {targets['transformers']['table']}
540
        WHERE scn_name = '{scenario}'
541
        AND trafo_id NOT IN (
542
            SELECT branch_id
543
            FROM {sources['osmtgmod_branch']['schema']}.
544
            {sources['osmtgmod_branch']['table']}
545
              WHERE result_id = 1 and link_type = 'transformer')
546
        """
547
    )
548
549
    # Initalize the dataframe for transformers
550
    trafo = gpd.GeoDataFrame(
551
        columns=["trafo_id", "bus0", "bus1", "s_nom"], dtype=int
552
    )
553
    trafo_id = db.next_etrago_id("transformer")
554
555
    # Add one transformer per central foreign bus with v_nom != 380
556
    for i, row in central_buses[central_buses.v_nom != 380].iterrows():
557
        s_nom_0 = new_lines[new_lines.bus0 == row.bus_id].s_nom.sum()
558
        s_nom_1 = new_lines[new_lines.bus1 == row.bus_id].s_nom.sum()
559
        if s_nom_0 == 0.0:
560
            s_nom = s_nom_1
561
        elif s_nom_1 == 0.0:
562
            s_nom = s_nom_0
563
        else:
564
            s_nom = min([s_nom_0, s_nom_1])
565
566
        s_nom, x = choose_transformer(s_nom)
567
568
        trafo = pd.concat(
569
            [
570
                trafo,
571
                pd.DataFrame(
572
                    index=[trafo.index.max() + 1],
573
                    data={
574
                        "trafo_id": trafo_id,
575
                        "bus0": row.bus_id,
576
                        "bus1": central_buses[
577
                            (central_buses.v_nom == 380)
578
                            & (central_buses.country == row.country)
579
                        ].bus_id.values[0],
580
                        "s_nom": s_nom,
581
                        "x": x,
582
                    },
583
                ),
584
            ],
585
            ignore_index=True,
586
        )
587
        trafo_id += 1
588
589
    # Set data type
590
    trafo = trafo.astype({"trafo_id": "int", "bus0": "int", "bus1": "int"})
591
    trafo["scn_name"] = scenario
592
593
    # Insert transformers to the database
594
    trafo.to_sql(
595
        targets["transformers"]["table"],
596
        schema=targets["transformers"]["schema"],
597
        if_exists="append",
598
        con=db.engine(),
599
        index=False,
600
    )
601
602
603
def foreign_dc_lines(scenario, sources, targets, central_buses):
604
    """Insert DC lines to foreign countries manually
605
606
    Parameters
607
    ----------
608
    sources : dict
609
        List of dataset sources
610
    targets : dict
611
        List of dataset targets
612
    central_buses : geopandas.GeoDataFrame
613
        Buses in the center of foreign countries
614
615
    Returns
616
    -------
617
    None.
618
619
    """
620
    # Delete existing dc lines to foreign countries
621
    db.execute_sql(
622
        f"""
623
        DELETE FROM {targets['links']['schema']}.
624
        {targets['links']['table']}
625
        WHERE scn_name = '{scenario}'
626
        AND carrier = 'DC'
627
        AND bus0 IN (
628
            SELECT bus_id
629
            FROM {sources['electricity_buses']['schema']}.
630
            {sources['electricity_buses']['table']}
631
              WHERE scn_name = '{scenario}'
632
              AND carrier = 'AC'
633
              AND country = 'DE')
634
        AND bus1 IN (
635
            SELECT bus_id
636
            FROM {sources['electricity_buses']['schema']}.
637
            {sources['electricity_buses']['table']}
638
              WHERE scn_name = '{scenario}'
639
              AND carrier = 'AC'
640
              AND country != 'DE')
641
        """
642
    )
643
    capital_cost = get_sector_parameters("electricity", scenario)[
644
        "capital_cost"
645
    ]
646
647
    # Add DC line from Lübeck to Sweden
648
    converter_luebeck = select_bus_id(
649
        10.802358024202768,
650
        53.897547401787,
651
        380,
652
        scenario,
653
        "AC",
654
        find_closest=True,
655
    )
656
657
    foreign_links = pd.DataFrame(
658
        index=[0],
659
        data={
660
            "link_id": db.next_etrago_id("link"),
661
            "bus0": converter_luebeck,
662
            "bus1": central_buses[
663
                (central_buses.country == "SE") & (central_buses.v_nom == 380)
664
            ]
665
            .squeeze()
666
            .bus_id,
667
            "p_nom": 600,
668
            "length": 262,
669
        },
670
    )
671
672
    # When not in test-mode, add DC line from Bentwisch to Denmark
673
    if config.settings()["egon-data"]["--dataset-boundary"] == "Everything":
674
        converter_bentwisch = select_bus_id(
675
            12.213671694775988,
676
            54.09974494662279,
677
            380,
678
            scenario,
679
            "AC",
680
            find_closest=True,
681
        )
682
683
        foreign_links = pd.concat(
684
            [
685
                foreign_links,
686
                pd.DataFrame(
687
                    index=[1],
688
                    data={
689
                        "link_id": db.next_etrago_id("link") + 1,
690
                        "bus0": converter_bentwisch,
691
                        "bus1": central_buses[
692
                            (central_buses.country == "DK")
693
                            & (central_buses.v_nom == 380)
694
                            & (central_buses.x > 10)
695
                        ]
696
                        .squeeze()
697
                        .bus_id,
698
                        "p_nom": 600,
699
                        "length": 170,
700
                    },
701
                ),
702
            ]
703
        )
704
705
    # Set parameters for all DC lines
706
    foreign_links["capital_cost"] = (
707
        capital_cost["dc_cable"] * foreign_links.length
708
        + 2 * capital_cost["dc_inverter"]
709
    )
710
    foreign_links["p_min_pu"] = -1
711
    foreign_links["p_nom_extendable"] = True
712
    foreign_links["p_nom_min"] = foreign_links["p_nom"]
713
    foreign_links["scn_name"] = scenario
714
    foreign_links["carrier"] = "DC"
715
    foreign_links["efficiency"] = 1
716
717
    # Add topology
718
    foreign_links = etrago.link_geom_from_buses(foreign_links, scenario)
719
720
    # Insert DC lines to the database
721
    foreign_links.to_postgis(
722
        targets["links"]["table"],
723
        schema=targets["links"]["schema"],
724
        if_exists="append",
725
        con=db.engine(),
726
        index=False,
727
    )
728
729
730
def grid():
731
    """Insert electrical grid compoenents for neighbouring countries
732
733
    Returns
734
    -------
735
    None.
736
737
    """
738
    # Select sources and targets from dataset configuration
739
    sources = config.datasets()["electrical_neighbours"]["sources"]
740
    targets = config.datasets()["electrical_neighbours"]["targets"]
741
742
    for scenario in config.settings()["egon-data"]["--scenarios"]:
743
        central_buses = buses(scenario, sources, targets)
744
745
        foreign_lines = cross_border_lines(
746
            scenario, sources, targets, central_buses
747
        )
748
749
        central_transformer(
750
            scenario, sources, targets, central_buses, foreign_lines
751
        )
752
753
        foreign_dc_lines(scenario, sources, targets, central_buses)
754
755
756
def map_carriers_tyndp():
757
    """Map carriers from TYNDP-data to carriers used in eGon
758
    Returns
759
    -------
760
    dict
761
        Carrier from TYNDP and eGon
762
    """
763
    return {
764
        "Battery": "battery",
765
        "DSR": "demand_side_response",
766
        "Gas CCGT new": "gas",
767
        "Gas CCGT old 2": "gas",
768
        "Gas CCGT present 1": "gas",
769
        "Gas CCGT present 2": "gas",
770
        "Gas conventional old 1": "gas",
771
        "Gas conventional old 2": "gas",
772
        "Gas OCGT new": "gas",
773
        "Gas OCGT old": "gas",
774
        "Gas CCGT old 1": "gas",
775
        "Gas CCGT old 2 Bio": "biogas",
776
        "Gas conventional old 2 Bio": "biogas",
777
        "Hard coal new": "coal",
778
        "Hard coal old 1": "coal",
779
        "Hard coal old 2": "coal",
780
        "Hard coal old 2 Bio": "coal",
781
        "Heavy oil old 1": "oil",
782
        "Heavy oil old 1 Bio": "oil",
783
        "Heavy oil old 2": "oil",
784
        "Light oil": "oil",
785
        "Lignite new": "lignite",
786
        "Lignite old 1": "lignite",
787
        "Lignite old 2": "lignite",
788
        "Lignite old 1 Bio": "lignite",
789
        "Lignite old 2 Bio": "lignite",
790
        "Nuclear": "nuclear",
791
        "Offshore Wind": "wind_offshore",
792
        "Onshore Wind": "wind_onshore",
793
        "Other non-RES": "others",
794
        "Other RES": "others",
795
        "P2G": "power_to_gas",
796
        "PS Closed": "pumped_hydro",
797
        "PS Open": "reservoir",
798
        "Reservoir": "reservoir",
799
        "Run-of-River": "run_of_river",
800
        "Solar PV": "solar",
801
        "Solar Thermal": "others",
802
        "Waste": "Other RES",
803
    }
804
805
806 View Code Duplication
def get_foreign_bus_id(scenario):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
807
    """Calculte the etrago bus id from Nodes of TYNDP based on the geometry
808
809
    Returns
810
    -------
811
    pandas.Series
812
        List of mapped node_ids from TYNDP and etragos bus_id
813
814
    """
815
816
    sources = config.datasets()["electrical_neighbours"]["sources"]
817
818
    bus_id = db.select_geodataframe(
819
        f"""SELECT bus_id, ST_Buffer(geom, 1) as geom, country
820
        FROM grid.egon_etrago_bus
821
        WHERE scn_name = '{scenario}'
822
        AND carrier = 'AC'
823
        AND v_nom = 380.
824
        AND country != 'DE'
825
        AND bus_id NOT IN (
826
            SELECT bus_i
827
            FROM osmtgmod_results.bus_data)
828
        """,
829
        epsg=3035,
830
    )
831
832
    # insert installed capacities
833
    file = zipfile.ZipFile(f"tyndp/{sources['tyndp_capacities']}")
834
835
    # Select buses in neighbouring countries as geodataframe
836
    buses = pd.read_excel(
837
        file.open("TYNDP-2020-Scenario-Datafile.xlsx").read(),
838
        sheet_name="Nodes - Dict",
839
    ).query("longitude==longitude")
840
    buses = gpd.GeoDataFrame(
841
        buses,
842
        crs=4326,
843
        geometry=gpd.points_from_xy(buses.longitude, buses.latitude),
844
    ).to_crs(3035)
845
846
    buses["bus_id"] = 0
847
848
    # Select bus_id from etrago with shortest distance to TYNDP node
849
    for i, row in buses.iterrows():
850
        distance = bus_id.set_index("bus_id").geom.distance(row.geometry)
851
        buses.loc[i, "bus_id"] = distance[
852
            distance == distance.min()
853
        ].index.values[0]
854
855
    return buses.set_index("node_id").bus_id
856
857
858
def calc_capacities():
859
    """Calculates installed capacities from TYNDP data
860
861
    Returns
862
    -------
863
    pandas.DataFrame
864
        Installed capacities per foreign node and energy carrier
865
866
    """
867
868
    sources = config.datasets()["electrical_neighbours"]["sources"]
869
870
    countries = [
871
        "AT",
872
        "BE",
873
        "CH",
874
        "CZ",
875
        "DK",
876
        "FR",
877
        "NL",
878
        "NO",
879
        "SE",
880
        "PL",
881
        "UK",
882
    ]
883
884
    # insert installed capacities
885
    file = zipfile.ZipFile(f"tyndp/{sources['tyndp_capacities']}")
886
    df = pd.read_excel(
887
        file.open("TYNDP-2020-Scenario-Datafile.xlsx").read(),
888
        sheet_name="Capacity",
889
    )
890
891
    # differneces between different climate years are very small (<1MW)
892
    # choose 1984 because it is the mean value
893
    df_2030 = (
894
        df.rename({"Climate Year": "Climate_Year"}, axis="columns")
895
        .query(
896
            'Scenario == "Distributed Energy" & Year == 2030 & '
897
            "Climate_Year == 1984"
898
        )
899
        .set_index(["Node/Line", "Generator_ID"])
900
    )
901
902
    df_2040 = (
903
        df.rename({"Climate Year": "Climate_Year"}, axis="columns")
904
        .query(
905
            'Scenario == "Distributed Energy" & Year == 2040 & '
906
            "Climate_Year == 1984"
907
        )
908
        .set_index(["Node/Line", "Generator_ID"])
909
    )
910
911
    # interpolate linear between 2030 and 2040 for 2035 accordning to
912
    # scenario report of TSO's and the approval by BNetzA
913
    df_2035 = pd.DataFrame(index=df_2030.index)
914
    df_2035["cap_2030"] = df_2030.Value
915
    df_2035["cap_2040"] = df_2040.Value
916
    df_2035.fillna(0.0, inplace=True)
917
    df_2035["cap_2035"] = (
918
        df_2035["cap_2030"] + (df_2035["cap_2040"] - df_2035["cap_2030"]) / 2
919
    )
920
    df_2035 = df_2035.reset_index()
921
    df_2035["carrier"] = df_2035.Generator_ID.map(map_carriers_tyndp())
922
923
    # group capacities by new carriers
924
    grouped_capacities = (
925
        df_2035.groupby(["carrier", "Node/Line"]).cap_2035.sum().reset_index()
926
    )
927
928
    # choose capacities for considered countries
929
    return grouped_capacities[
930
        grouped_capacities["Node/Line"].str[:2].isin(countries)
931
    ]
932
933
934
def insert_generators_tyndp(capacities):
935
    """Insert generators for foreign countries based on TYNDP-data
936
937
    Parameters
938
    ----------
939
    capacities : pandas.DataFrame
940
        Installed capacities per foreign node and energy carrier
941
942
    Returns
943
    -------
944
    None.
945
946
    """
947
    targets = config.datasets()["electrical_neighbours"]["targets"]
948
    map_buses = get_map_buses()
949
950
    # Delete existing data
951
    db.execute_sql(
952
        f"""
953
        DELETE FROM
954
        {targets['generators']['schema']}.{targets['generators']['table']}
955
        WHERE bus IN (
956
            SELECT bus_id FROM
957
            {targets['buses']['schema']}.{targets['buses']['table']}
958
            WHERE country != 'DE'
959
            AND scn_name = 'eGon2035')
960
        AND scn_name = 'eGon2035'
961
        AND carrier != 'CH4'
962
        """
963
    )
964
965
    db.execute_sql(
966
        f"""
967
        DELETE FROM
968
        {targets['generators_timeseries']['schema']}.
969
        {targets['generators_timeseries']['table']}
970
        WHERE generator_id NOT IN (
971
            SELECT generator_id FROM
972
            {targets['generators']['schema']}.{targets['generators']['table']}
973
        )
974
        AND scn_name = 'eGon2035'
975
        """
976
    )
977
978
    # Select generators from TYNDP capacities
979
    gen = capacities[
980
        capacities.carrier.isin(
981
            [
982
                "others",
983
                "wind_offshore",
984
                "wind_onshore",
985
                "solar",
986
                "reservoir",
987
                "run_of_river",
988
                "lignite",
989
                "coal",
990
                "oil",
991
                "nuclear",
992
            ]
993
        )
994
    ]
995
996
    # Set bus_id
997
    gen.loc[
998
        gen[gen["Node/Line"].isin(map_buses.keys())].index, "Node/Line"
999
    ] = gen.loc[
1000
        gen[gen["Node/Line"].isin(map_buses.keys())].index, "Node/Line"
1001
    ].map(
1002
        map_buses
1003
    )
1004
1005
    gen.loc[:, "bus"] = (
1006
        get_foreign_bus_id(scenario="eGon2035")
1007
        .loc[gen.loc[:, "Node/Line"]]
1008
        .values
1009
    )
1010
1011
    # Add scenario column
1012
    gen["scenario"] = "eGon2035"
1013
1014
    # Add marginal costs
1015
    gen = add_marginal_costs(gen)
1016
1017
    # insert generators data
1018
    session = sessionmaker(bind=db.engine())()
1019
    for i, row in gen.iterrows():
1020
        entry = etrago.EgonPfHvGenerator(
1021
            scn_name=row.scenario,
1022
            generator_id=int(db.next_etrago_id("generator")),
1023
            bus=row.bus,
1024
            carrier=row.carrier,
1025
            p_nom=row.cap_2035,
1026
            marginal_cost=row.marginal_cost,
1027
        )
1028
1029
        session.add(entry)
1030
        session.commit()
1031
1032
    # assign generators time-series data
1033
    renew_carriers_2035 = ["wind_onshore", "wind_offshore", "solar"]
1034
1035
    sql = f"""SELECT * FROM
1036
    {targets['generators_timeseries']['schema']}.
1037
    {targets['generators_timeseries']['table']}
1038
    WHERE scn_name = 'eGon100RE'
1039
    """
1040
    series_egon100 = pd.read_sql_query(sql, db.engine())
1041
1042
    sql = f""" SELECT * FROM
1043
    {targets['generators']['schema']}.{targets['generators']['table']}
1044
    WHERE bus IN (
1045
        SELECT bus_id FROM
1046
                {targets['buses']['schema']}.{targets['buses']['table']}
1047
                WHERE country != 'DE'
1048
                AND scn_name = 'eGon2035')
1049
        AND scn_name = 'eGon2035'
1050
    """
1051
    gen_2035 = pd.read_sql_query(sql, db.engine())
1052
    gen_2035 = gen_2035[gen_2035.carrier.isin(renew_carriers_2035)]
1053
1054
    sql = f""" SELECT * FROM
1055
    {targets['generators']['schema']}.{targets['generators']['table']}
1056
    WHERE bus IN (
1057
        SELECT bus_id FROM
1058
                {targets['buses']['schema']}.{targets['buses']['table']}
1059
                WHERE country != 'DE'
1060
                AND scn_name = 'eGon100RE')
1061
        AND scn_name = 'eGon100RE'
1062
    """
1063
    gen_100 = pd.read_sql_query(sql, db.engine())
1064
    gen_100 = gen_100[gen_100["carrier"].isin(renew_carriers_2035)]
1065
1066
    # egon_2035_to_100 map the timeseries used in the scenario eGon100RE
1067
    # to the same bus and carrier for the scenario egon2035
1068
    egon_2035_to_100 = {}
1069
    for i, gen in gen_2035.iterrows():
1070
        gen_id_100 = gen_100[
1071
            (gen_100["bus"] == gen["bus"])
1072
            & (gen_100["carrier"] == gen["carrier"])
1073
        ]["generator_id"].values[0]
1074
1075
        egon_2035_to_100[gen["generator_id"]] = gen_id_100
1076
1077
    # insert generators_timeseries data
1078
    session = sessionmaker(bind=db.engine())()
1079
1080
    for gen_id in gen_2035.generator_id:
1081
        serie = series_egon100[
1082
            series_egon100.generator_id == egon_2035_to_100[gen_id]
1083
        ]["p_max_pu"].values[0]
1084
        entry = etrago.EgonPfHvGeneratorTimeseries(
1085
            scn_name="eGon2035", generator_id=gen_id, temp_id=1, p_max_pu=serie
1086
        )
1087
1088
        session.add(entry)
1089
        session.commit()
1090
1091
1092
def insert_storage_tyndp(capacities):
1093
    """Insert storage units for foreign countries based on TYNDP-data
1094
1095
    Parameters
1096
    ----------
1097
    capacities : pandas.DataFrame
1098
        Installed capacities per foreign node and energy carrier
1099
1100
1101
    Returns
1102
    -------
1103
    None.
1104
1105
    """
1106
    targets = config.datasets()["electrical_neighbours"]["targets"]
1107
    map_buses = get_map_buses()
1108
1109
    # Delete existing data
1110
    db.execute_sql(
1111
        f"""
1112
        DELETE FROM {targets['storage']['schema']}.{targets['storage']['table']}
1113
        WHERE bus IN (
1114
            SELECT bus_id FROM
1115
            {targets['buses']['schema']}.{targets['buses']['table']}
1116
            WHERE country != 'DE'
1117
            AND scn_name = 'eGon2035')
1118
        AND scn_name = 'eGon2035'
1119
        """
1120
    )
1121
1122
    # Add missing information suitable for eTraGo selected from scenario_parameter table
1123
    parameters_pumped_hydro = scenario_parameters.electricity("eGon2035")[
1124
        "efficiency"
1125
    ]["pumped_hydro"]
1126
1127
    parameters_battery = scenario_parameters.electricity("eGon2035")[
1128
        "efficiency"
1129
    ]["battery"]
1130
1131
    # Select storage capacities from TYNDP-data
1132
    store = capacities[capacities.carrier.isin(["battery", "pumped_hydro"])]
1133
1134
    # Set bus_id
1135
    store.loc[
1136
        store[store["Node/Line"].isin(map_buses.keys())].index, "Node/Line"
1137
    ] = store.loc[
1138
        store[store["Node/Line"].isin(map_buses.keys())].index, "Node/Line"
1139
    ].map(
1140
        map_buses
1141
    )
1142
1143
    store.loc[:, "bus"] = (
1144
        get_foreign_bus_id(scenario="eGon2035")
1145
        .loc[store.loc[:, "Node/Line"]]
1146
        .values
1147
    )
1148
1149
    # Add columns for additional parameters to df
1150
    (
1151
        store["dispatch"],
1152
        store["store"],
1153
        store["standing_loss"],
1154
        store["max_hours"],
1155
    ) = (None, None, None, None)
1156
1157
    # Insert carrier specific parameters
1158
1159
    parameters = ["dispatch", "store", "standing_loss", "max_hours"]
1160
1161
    for x in parameters:
1162
        store.loc[store["carrier"] == "battery", x] = parameters_battery[x]
1163
        store.loc[store["carrier"] == "pumped_hydro", x] = (
1164
            parameters_pumped_hydro[x]
1165
        )
1166
1167
    # insert data
1168
    session = sessionmaker(bind=db.engine())()
1169
    for i, row in store.iterrows():
1170
        entry = etrago.EgonPfHvStorage(
1171
            scn_name="eGon2035",
1172
            storage_id=int(db.next_etrago_id("storage")),
1173
            bus=row.bus,
1174
            max_hours=row.max_hours,
1175
            efficiency_store=row.store,
1176
            efficiency_dispatch=row.dispatch,
1177
            standing_loss=row.standing_loss,
1178
            carrier=row.carrier,
1179
            p_nom=row.cap_2035,
1180
        )
1181
1182
        session.add(entry)
1183
        session.commit()
1184
1185
1186
def get_map_buses():
1187
    """Returns a dictonary of foreign regions which are aggregated to another
1188
1189
    Returns
1190
    -------
1191
    Combination of aggregated regions
1192
1193
1194
    """
1195
    return {
1196
        "DK00": "DKW1",
1197
        "DKKF": "DKE1",
1198
        "FR15": "FR00",
1199
        "NON1": "NOM1",
1200
        "NOS0": "NOM1",
1201
        "NOS1": "NOM1",
1202
        "PLE0": "PL00",
1203
        "PLI0": "PL00",
1204
        "SE00": "SE02",
1205
        "SE01": "SE02",
1206
        "SE03": "SE02",
1207
        "SE04": "SE02",
1208
        "RU": "RU00",
1209
    }
1210
1211
1212
def tyndp_generation():
1213
    """Insert data from TYNDP 2020 accordning to NEP 2021
1214
    Scenario 'Distributed Energy', linear interpolate between 2030 and 2040
1215
1216
    Returns
1217
    -------
1218
    None.
1219
    """
1220
1221
    capacities = calc_capacities()
1222
1223
    insert_generators_tyndp(capacities)
1224
1225
    insert_storage_tyndp(capacities)
1226
1227
1228
def tyndp_demand():
1229
    """Copy load timeseries data from TYNDP 2020.
1230
    According to NEP 2021, the data for 2030 and 2040 is interpolated linearly.
1231
1232
    Returns
1233
    -------
1234
    None.
1235
1236
    """
1237
    map_buses = get_map_buses()
1238
1239
    sources = config.datasets()["electrical_neighbours"]["sources"]
1240
    targets = config.datasets()["electrical_neighbours"]["targets"]
1241
1242
    # Delete existing data
1243
    db.execute_sql(
1244
        f"""
1245
        DELETE FROM {targets['loads']['schema']}.
1246
        {targets['loads']['table']}
1247
        WHERE
1248
        scn_name = 'eGon2035'
1249
        AND carrier = 'AC'
1250
        AND bus NOT IN (
1251
            SELECT bus_i
1252
            FROM  {sources['osmtgmod_bus']['schema']}.
1253
            {sources['osmtgmod_bus']['table']})
1254
        """
1255
    )
1256
1257
    # Connect to database
1258
    engine = db.engine()
1259
    session = sessionmaker(bind=engine)()
1260
1261
    nodes = [
1262
        "AT00",
1263
        "BE00",
1264
        "CH00",
1265
        "CZ00",
1266
        "DKE1",
1267
        "DKW1",
1268
        "FR00",
1269
        "NL00",
1270
        "LUB1",
1271
        "LUF1",
1272
        "LUG1",
1273
        "NOM1",
1274
        "NON1",
1275
        "NOS0",
1276
        "SE01",
1277
        "SE02",
1278
        "SE03",
1279
        "SE04",
1280
        "PL00",
1281
        "UK00",
1282
        "UKNI",
1283
    ]
1284
    # Assign etrago bus_id to TYNDP nodes
1285
    buses = pd.DataFrame({"nodes": nodes})
1286
    buses.loc[buses[buses.nodes.isin(map_buses.keys())].index, "nodes"] = (
1287
        buses[buses.nodes.isin(map_buses.keys())].nodes.map(map_buses)
1288
    )
1289
    buses.loc[:, "bus"] = (
1290
        get_foreign_bus_id(scenario="eGon2035")
1291
        .loc[buses.loc[:, "nodes"]]
1292
        .values
1293
    )
1294
    buses.set_index("nodes", inplace=True)
1295
    buses = buses[~buses.index.duplicated(keep="first")]
1296
1297
    # Read in data from TYNDP for 2030 and 2040
1298
    dataset_2030 = pd.read_excel(
1299
        f"tyndp/{sources['tyndp_demand_2030']}", sheet_name=nodes, skiprows=10
1300
    )
1301
1302
    dataset_2040 = pd.read_excel(
1303
        f"tyndp/{sources['tyndp_demand_2040']}", sheet_name=None, skiprows=10
1304
    )
1305
1306
    # Transform map_buses to pandas.Series and select only used values
1307
    map_series = pd.Series(map_buses)
1308
    map_series = map_series[map_series.index.isin(nodes)]
1309
1310
    # Calculate and insert demand timeseries per etrago bus_id
1311
    for bus in buses.index:
1312
        nodes = [bus]
1313
1314
        if bus in map_series.values:
1315
            nodes.extend(list(map_series[map_series == bus].index.values))
1316
1317
        load_id = db.next_etrago_id("load")
1318
1319
        # Some etrago bus_ids represent multiple TYNDP nodes,
1320
        # in this cases the loads are summed
1321
        data_2030 = pd.Series(index=range(8760), data=0.0)
1322
        for node in nodes:
1323
            data_2030 = dataset_2030[node][2011] + data_2030
1324
1325
        try:
1326
            data_2040 = pd.Series(index=range(8760), data=0.0)
1327
1328
            for node in nodes:
1329
                data_2040 = dataset_2040[node][2011] + data_2040
1330
        except:
1331
            data_2040 = data_2030
1332
1333
        # According to the NEP, data for 2030 and 2040 is linear interpolated
1334
        data_2035 = ((data_2030 + data_2040) / 2)[:8760]
1335
1336
        entry = etrago.EgonPfHvLoad(
1337
            scn_name="eGon2035",
1338
            load_id=int(load_id),
1339
            carrier="AC",
1340
            bus=int(buses.bus[bus]),
1341
        )
1342
1343
        entry_ts = etrago.EgonPfHvLoadTimeseries(
1344
            scn_name="eGon2035",
1345
            load_id=int(load_id),
1346
            temp_id=1,
1347
            p_set=list(data_2035.values),
1348
        )
1349
1350
        session.add(entry)
1351
        session.add(entry_ts)
1352
        session.commit()
1353
1354
1355
def get_entsoe_token():
1356
    """Check for token in home dir. If not exists, check in working dir"""
1357
    token_path = path.join(path.expanduser("~"), ".entsoe-token")
1358
    if not os.path.isfile(token_path):
1359
        logger.info(
1360
            f"Token file not found at {token_path}. Will check in working directory."
1361
        )
1362
        token_path = Path(".entsoe-token")
1363
        if os.path.isfile(token_path):
1364
            logger.info(f"Token found at {token_path}")
1365
    entsoe_token = open(token_path, "r").read(36)
1366
    if entsoe_token is None:
1367
        raise FileNotFoundError("No entsoe-token found.")
1368
    return entsoe_token
1369
1370
1371
def entsoe_historic_generation_capacities(
1372
    year_start="20190101", year_end="20200101"
1373
):
1374
    entsoe_token = get_entsoe_token()
1375
    client = entsoe.EntsoePandasClient(api_key=entsoe_token)
1376
1377
    start = pd.Timestamp(year_start, tz="Europe/Brussels")
1378
    end = pd.Timestamp(year_end, tz="Europe/Brussels")
1379
    start_gb = pd.Timestamp(year_start, tz="Europe/London")
1380
    end_gb = pd.Timestamp(year_end, tz="Europe/London")
1381
    countries = [
1382
        "LU",
1383
        "AT",
1384
        "FR",
1385
        "NL",
1386
        "CZ",
1387
        "DK_1",
1388
        "DK_2",
1389
        "PL",
1390
        "CH",
1391
        "NO",
1392
        "BE",
1393
        "SE",
1394
        "GB",
1395
    ]
1396
    # No GB data after Brexit
1397
    if int(year_start[:4]) > 2021:
1398
        logger.warning(
1399
            "No GB data after Brexit. GB is dropped from entsoe query!"
1400
        )
1401
        countries = [c for c in countries if c != "GB"]
1402
    # todo: define wanted countries
1403
1404
    not_retrieved = []
1405
    dfs = []
1406
    for country in countries:
1407
        if country == "GB":
1408
            kwargs = dict(start=start_gb, end=end_gb)
1409
        else:
1410
            kwargs = dict(start=start, end=end)
1411
        try:
1412
            country_data = client.query_installed_generation_capacity(
1413
                country, **kwargs
1414
            )
1415
            dfs.append(country_data)
1416
        except (entsoe.exceptions.NoMatchingDataError, requests.HTTPError):
1417
            logger.warning(
1418
                f"Data for country: {country} could not be retrieved."
1419
            )
1420
            not_retrieved.append(country)
1421
            pass
1422
1423
    if dfs:
1424
        df = pd.concat(dfs)
1425
        df["country"] = [c for c in countries if c not in not_retrieved]
1426
        df.set_index("country", inplace=True)
1427
        if int(year_start[:4]) == 2023:
1428
            # https://www.bmreports.com/bmrs/?q=foregeneration/capacityaggregated
1429
            # could probably somehow be automised
1430
            # https://www.elexonportal.co.uk/category/view/178
1431
            # in MW
1432
            installed_capacity_gb = pd.Series(
1433
                {
1434
                    "Biomass": 4438,
1435
                    "Fossil Gas": 37047,
1436
                    "Fossil Hard coal": 1491,
1437
                    "Hydro Pumped Storage": 5603,
1438
                    "Hydro Run-of-river and poundage": 2063,
1439
                    "Nuclear": 4950,
1440
                    "Other": 3313,
1441
                    "Other renewable": 1462,
1442
                    "Solar": 14518,
1443
                    "Wind Offshore": 13038,
1444
                    "Wind Onshore": 13907,
1445
                },
1446
                name="GB",
1447
            )
1448
            df = pd.concat([df.T, installed_capacity_gb], axis=1).T
1449
            logger.info("Manually added generation capacities for GB 2023.")
1450
            not_retrieved = [c for c in not_retrieved if c != "GB"]
1451
        df.fillna(0, inplace=True)
1452
    else:
1453
        df = pd.DataFrame()
1454
    return df, not_retrieved
1455
1456
1457
def entsoe_historic_demand(year_start="20190101", year_end="20200101"):
1458
    entsoe_token = get_entsoe_token()
1459
    client = entsoe.EntsoePandasClient(api_key=entsoe_token)
1460
1461
    start = pd.Timestamp(year_start, tz="Europe/Brussels")
1462
    end = pd.Timestamp(year_end, tz="Europe/Brussels")
1463
    start_gb = start.tz_convert("Europe/London")
1464
    end_gb = end.tz_convert("Europe/London")
1465
1466
    countries = [
1467
        "LU",
1468
        "AT",
1469
        "FR",
1470
        "NL",
1471
        "CZ",
1472
        "DK_1",
1473
        "DK_2",
1474
        "PL",
1475
        "CH",
1476
        "NO",
1477
        "BE",
1478
        "SE",
1479
        "GB",
1480
    ]
1481
1482
    # todo: define wanted countries
1483
1484
    not_retrieved = []
1485
    dfs = []
1486
1487
    for country in countries:
1488
        if country == "GB":
1489
            kwargs = dict(start=start_gb, end=end_gb)
1490
        else:
1491
            kwargs = dict(start=start, end=end)
1492
        try:
1493
            country_data = (
1494
                client.query_load(country, **kwargs)
1495
                .resample("H")["Actual Load"]
1496
                .mean()
1497
            )
1498
            if country == "GB":
1499
                country_data.index = country_data.index.tz_convert(
1500
                    "Europe/Brussels"
1501
                )
1502
            dfs.append(country_data)
1503
        except (entsoe.exceptions.NoMatchingDataError, requests.HTTPError):
1504
            not_retrieved.append(country)
1505
            logger.warning(
1506
                f"Data for country: {country} could not be retrieved."
1507
            )
1508
            pass
1509
1510
    if dfs:
1511
        df = pd.concat(dfs, axis=1)
1512
        df.columns = [c for c in countries if c not in not_retrieved]
1513
        df.index = pd.date_range(year_start, periods=8760, freq="H")
1514
    else:
1515
        df = pd.DataFrame()
1516
    return df, not_retrieved
1517
1518
1519
def map_carriers_entsoe():
1520
    """Map carriers from entsoe-data to carriers used in eGon
1521
    Returns
1522
    -------
1523
    dict
1524
        Carrier from entsoe to eGon
1525
    """
1526
    return {
1527
        "Biomass": "biomass",
1528
        "Fossil Brown coal/Lignite": "lignite",
1529
        "Fossil Coal-derived gas": "coal",
1530
        "Fossil Gas": "OCGT",
1531
        "Fossil Hard coal": "coal",
1532
        "Fossil Oil": "oil",
1533
        "Fossil Oil shale": "oil",
1534
        "Fossil Peat": "others",
1535
        "Geothermal": "geo_thermal",
1536
        "Hydro Pumped Storage": "Hydro Pumped Storage",
1537
        "Hydro Run-of-river and poundage": "run_of_river",
1538
        "Hydro Water Reservoir": "reservoir",
1539
        "Marine": "others",
1540
        "Nuclear": "nuclear",
1541
        "Other": "others",
1542
        "Other renewable": "others",
1543
        "Solar": "solar",
1544
        "Waste": "others",
1545
        "Wind Offshore": "wind_offshore",
1546
        "Wind Onshore": "wind_onshore",
1547
    }
1548
1549
1550
def entsoe_to_bus_etrago(scn_name):
1551
    map_entsoe = pd.Series(
1552
        {
1553
            "LU": "LU00",
1554
            "AT": "AT00",
1555
            "FR": "FR00",
1556
            "NL": "NL00",
1557
            "DK_1": "DK00",
1558
            "DK_2": "DKE1",
1559
            "PL": "PL00",
1560
            "CH": "CH00",
1561
            "NO": "NO00",
1562
            "BE": "BE00",
1563
            "SE": "SE00",
1564
            "GB": "UK00",
1565
            "CZ": "CZ00",
1566
        }
1567
    )
1568
1569
    for_bus = get_foreign_bus_id(scenario=scn_name)
1570
1571
    return map_entsoe.map(for_bus)
1572
1573
1574
def save_entsoe_data(df: pd.DataFrame, file_path: Path):
1575
    os.makedirs(file_path.parent, exist_ok=True)
1576
    if not df.empty:
1577
        df.to_csv(file_path, index_label="Index")
1578
        logger.info(
1579
            f"Saved entsoe data for {file_path.stem} "
1580
            f"to {file_path.parent} for countries: {df.index}"
1581
        )
1582
1583
1584
def fill_by_backup_data_from_former_runs(df_sq, file_path, not_retrieved):
1585
    """
1586
    Fills missing data from former runs
1587
    Parameters
1588
    ----------
1589
    df_sq: pd.DataFrame
1590
    file_path: str, Path
1591
    not_retrieved: list
1592
1593
    Returns
1594
    -------
1595
    df_sq, not_retrieved
1596
1597
    """
1598
    sq_backup = pd.read_csv(file_path, index_col="Index")
1599
    # check for missing columns in backup (former runs)
1600
    c_backup = [c for c in sq_backup.columns if c in not_retrieved]
1601
    # remove columns, if found in backup
1602
    not_retrieved = [c for c in not_retrieved if c not in c_backup]
1603
    if c_backup:
1604
        df_sq = pd.concat([df_sq, sq_backup.loc[:, c_backup]], axis=1)
1605
        logger.info(f"Appended data from former runs for {c_backup}")
1606
    return df_sq, not_retrieved
1607
1608
1609
def insert_generators_sq(scn_name="status2019"):
1610
    """
1611
    Insert generators for foreign countries based on ENTSO-E data
1612
1613
    Parameters
1614
    ----------
1615
    gen_sq : pandas dataframe
1616
        df with all the foreign generators produced by the function
1617
        entsoe_historic_generation_capacities
1618
    scn_name : str
1619
        The default is "status2019".
1620
1621
    Returns
1622
    -------
1623
    None.
1624
1625
    """
1626
    if "status" in scn_name:
1627
        year = int(scn_name.split("status")[-1])
1628
        year_start_end = {
1629
            "year_start": f"{year}0101",
1630
            "year_end": f"{year+1}0101",
1631
        }
1632
    else:
1633
        raise ValueError("No valid scenario name!")
1634
1635
    df_gen_sq, not_retrieved = entsoe_historic_generation_capacities(
1636
        **year_start_end
1637
    )
1638
1639 View Code Duplication
    if not_retrieved:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1640
        logger.warning("Generation data from entsoe could not be retrieved.")
1641
        # check for generation backup from former runs
1642
        file_path = Path(
1643
            "./", "entsoe_data", f"gen_entsoe_{scn_name}.csv"
1644
        ).resolve()
1645
        if os.path.isfile(file_path):
1646
            df_gen_sq, not_retrieved = fill_by_backup_data_from_former_runs(
1647
                df_gen_sq, file_path, not_retrieved
1648
            )
1649
        save_entsoe_data(df_gen_sq, file_path=file_path)
1650
1651
    if not_retrieved:
1652
        logger.warning(
1653
            f"Backup data of 2019 is used instead for {not_retrieved}"
1654
        )
1655
        df_gen_sq_backup = pd.read_csv(
1656
            "data_bundle_egon_data/entsoe/gen_entsoe.csv", index_col="Index"
1657
        )
1658
        df_gen_sq = pd.concat(
1659
            [df_gen_sq, df_gen_sq_backup.loc[not_retrieved]], axis=1
1660
        )
1661
1662
    targets = config.datasets()["electrical_neighbours"]["targets"]
1663
    # Delete existing data
1664
    db.execute_sql(
1665
        f"""
1666
        DELETE FROM
1667
        {targets['generators']['schema']}.{targets['generators']['table']}
1668
        WHERE bus IN (
1669
            SELECT bus_id FROM
1670
            {targets['buses']['schema']}.{targets['buses']['table']}
1671
            WHERE country != 'DE'
1672
            AND scn_name = '{scn_name}')
1673
        AND scn_name = '{scn_name}'
1674
        AND carrier != 'CH4'
1675
        """
1676
    )
1677
1678
    db.execute_sql(
1679
        f"""
1680
        DELETE FROM
1681
        {targets['generators_timeseries']['schema']}.
1682
        {targets['generators_timeseries']['table']}
1683
        WHERE generator_id NOT IN (
1684
            SELECT generator_id FROM
1685
            {targets['generators']['schema']}.{targets['generators']['table']}
1686
        )
1687
        AND scn_name = '{scn_name}'
1688
        """
1689
    )
1690
    entsoe_to_bus = entsoe_to_bus_etrago(scn_name)
1691
    carrier_entsoe = map_carriers_entsoe()
1692
    df_gen_sq = df_gen_sq.groupby(axis=1, by=carrier_entsoe).sum()
1693
1694
    # Filter generators modeled as storage and geothermal
1695
    df_gen_sq = df_gen_sq.loc[
1696
        :, ~df_gen_sq.columns.isin(["Hydro Pumped Storage", "geo_thermal"])
1697
    ]
1698
1699
    list_gen_sq = pd.DataFrame(
1700
        dtype=int, columns=["carrier", "country", "capacity"]
1701
    )
1702
    for carrier in df_gen_sq.columns:
1703
        gen_carry = df_gen_sq[carrier]
1704
        for country, cap in gen_carry.items():
1705
            gen = pd.DataFrame(
1706
                {"carrier": carrier, "country": country, "capacity": cap},
1707
                index=[1],
1708
            )
1709
            # print(gen)
1710
            list_gen_sq = pd.concat([list_gen_sq, gen], ignore_index=True)
1711
1712
    list_gen_sq = list_gen_sq[list_gen_sq.capacity > 0]
1713
    list_gen_sq["scenario"] = scn_name
1714
1715
    # Add marginal costs
1716
    list_gen_sq = add_marginal_costs(list_gen_sq)
1717
1718
    # Find foreign bus to assign the generator
1719
    list_gen_sq["bus"] = list_gen_sq.country.map(entsoe_to_bus)
1720
1721
    # insert generators data
1722
    session = sessionmaker(bind=db.engine())()
1723
    for i, row in list_gen_sq.iterrows():
1724
        entry = etrago.EgonPfHvGenerator(
1725
            scn_name=row.scenario,
1726
            generator_id=int(db.next_etrago_id("generator")),
1727
            bus=row.bus,
1728
            carrier=row.carrier,
1729
            p_nom=row.capacity,
1730
            marginal_cost=row.marginal_cost,
1731
        )
1732
1733
        session.add(entry)
1734
        session.commit()
1735
1736
    # assign generators time-series data
1737
    renew_carriers_sq = ["wind_onshore", "wind_offshore", "solar"]
1738
1739
    sql = f"""SELECT * FROM
1740
    {targets['generators_timeseries']['schema']}.
1741
    {targets['generators_timeseries']['table']}
1742
    WHERE scn_name = 'eGon100RE'
1743
    """
1744
    series_egon100 = pd.read_sql_query(sql, db.engine())
1745
1746
    sql = f""" SELECT * FROM
1747
    {targets['generators']['schema']}.{targets['generators']['table']}
1748
    WHERE bus IN (
1749
        SELECT bus_id FROM
1750
                {targets['buses']['schema']}.{targets['buses']['table']}
1751
                WHERE country != 'DE'
1752
                AND scn_name = '{scn_name}')
1753
        AND scn_name = '{scn_name}'
1754
    """
1755
    df_gen_sq = pd.read_sql_query(sql, db.engine())
1756
    df_gen_sq = df_gen_sq[df_gen_sq.carrier.isin(renew_carriers_sq)]
1757
1758
    sql = f""" SELECT * FROM
1759
    {targets['generators']['schema']}.{targets['generators']['table']}
1760
    WHERE bus IN (
1761
        SELECT bus_id FROM
1762
                {targets['buses']['schema']}.{targets['buses']['table']}
1763
                WHERE country != 'DE'
1764
                AND scn_name = 'eGon100RE')
1765
        AND scn_name = 'eGon100RE'
1766
    """
1767
    gen_100 = pd.read_sql_query(sql, db.engine())
1768
    gen_100 = gen_100[gen_100["carrier"].isin(renew_carriers_sq)]
1769
1770
    # egon_sq_to_100 map the timeseries used in the scenario eGon100RE
1771
    # to the same bus and carrier for the status quo scenario
1772
    egon_sq_to_100 = {}
1773
    for i, gen in df_gen_sq.iterrows():
1774
        gen_id_100 = gen_100[
1775
            (gen_100["bus"] == gen["bus"])
1776
            & (gen_100["carrier"] == gen["carrier"])
1777
        ]["generator_id"].values[0]
1778
1779
        egon_sq_to_100[gen["generator_id"]] = gen_id_100
1780
1781
    # insert generators_timeseries data
1782
    with session_scope() as session:
1783
        for gen_id in df_gen_sq.generator_id:
1784
            serie = series_egon100[
1785
                series_egon100.generator_id == egon_sq_to_100[gen_id]
1786
            ]["p_max_pu"].values[0]
1787
            entry = etrago.EgonPfHvGeneratorTimeseries(
1788
                scn_name=scn_name, generator_id=gen_id, temp_id=1, p_max_pu=serie
1789
            )
1790
1791
            session.add(entry)
1792
            session.commit()
1793
1794
    return
1795
1796
1797
def insert_storage_units_sq(scn_name="status2019"):
1798
    """
1799
    Insert storage_units for foreign countries based on ENTSO-E data
1800
1801
    Parameters
1802
    ----------
1803
    scn_name : str
1804
        Scenario to which the foreign storage units will be assigned.
1805
        The default is "status2019".
1806
1807
    Returns
1808
    -------
1809
    None.
1810
1811
    """
1812
    if "status" in scn_name:
1813
        year = int(scn_name.split("status")[-1])
1814
        year_start_end = {
1815
            "year_start": f"{year}0101",
1816
            "year_end": f"{year+1}0101",
1817
        }
1818
    else:
1819
        raise ValueError("No valid scenario name!")
1820
1821
    df_gen_sq, not_retrieved = entsoe_historic_generation_capacities(
1822
        **year_start_end
1823
    )
1824
1825 View Code Duplication
    if not_retrieved:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1826
        logger.warning("Generation data from entsoe could not be retrieved.")
1827
        # check for generation backup from former runs
1828
        file_path = Path(
1829
            "./", "entsoe_data", f"gen_entsoe_{scn_name}.csv"
1830
        ).resolve()
1831
        if os.path.isfile(file_path):
1832
            df_gen_sq, not_retrieved = fill_by_backup_data_from_former_runs(
1833
                df_gen_sq, file_path, not_retrieved
1834
            )
1835
        save_entsoe_data(df_gen_sq, file_path=file_path)
1836
1837
    if not_retrieved:
1838
        logger.warning(
1839
            f"Backup data of 2019 is used instead for {not_retrieved}"
1840
        )
1841
        df_gen_sq_backup = pd.read_csv(
1842
            "data_bundle_egon_data/entsoe/gen_entsoe.csv", index_col="Index"
1843
        )
1844
        df_gen_sq = pd.concat(
1845
            [df_gen_sq, df_gen_sq_backup.loc[not_retrieved]], axis=1
1846
        )
1847
1848
    sto_sq = df_gen_sq.loc[:, df_gen_sq.columns == "Hydro Pumped Storage"]
1849
    sto_sq.rename(columns={"Hydro Pumped Storage": "p_nom"}, inplace=True)
1850
1851
    targets = config.datasets()["electrical_neighbours"]["targets"]
1852
1853
    # Delete existing data
1854
    db.execute_sql(
1855
        f"""
1856
        DELETE FROM {targets['storage']['schema']}.{targets['storage']['table']}
1857
        WHERE bus IN (
1858
            SELECT bus_id FROM
1859
            {targets['buses']['schema']}.{targets['buses']['table']}
1860
            WHERE country != 'DE'
1861
            AND scn_name = '{scn_name}')
1862
        AND scn_name = '{scn_name}'
1863
        """
1864
    )
1865
1866
    # Add missing information suitable for eTraGo selected from scenario_parameter table
1867
    parameters_pumped_hydro = get_sector_parameters(sector="electricity", scenario=scn_name)["efficiency"]["pumped_hydro"]
1868
1869
    # Set bus_id
1870
    entsoe_to_bus = entsoe_to_bus_etrago(scn_name=scn_name)
1871
    sto_sq["bus"] = sto_sq.index.map(entsoe_to_bus)
1872
1873
    # Insert carrier specific parameters
1874
    sto_sq["carrier"] = "pumped_hydro"
1875
    sto_sq["scn_name"] = scn_name
1876
    sto_sq["dispatch"] = parameters_pumped_hydro["dispatch"]
1877
    sto_sq["store"] = parameters_pumped_hydro["store"]
1878
    sto_sq["standing_loss"] = parameters_pumped_hydro["standing_loss"]
1879
    sto_sq["max_hours"] = parameters_pumped_hydro["max_hours"]
1880
1881
    # Delete entrances without any installed capacity
1882
    sto_sq = sto_sq[sto_sq["p_nom"] > 0]
1883
1884
    # insert data pumped_hydro storage
1885
1886
    with session_scope() as session:
1887
        for i, row in sto_sq.iterrows():
1888
            entry = etrago.EgonPfHvStorage(
1889
                scn_name=scn_name,
1890
                storage_id=int(db.next_etrago_id("storage")),
1891
                bus=row.bus,
1892
                max_hours=row.max_hours,
1893
                efficiency_store=row.store,
1894
                efficiency_dispatch=row.dispatch,
1895
                standing_loss=row.standing_loss,
1896
                carrier=row.carrier,
1897
                p_nom=row.p_nom,
1898
            )
1899
1900
            session.add(entry)
1901
            session.commit()
1902
1903
1904
def insert_loads_sq(scn_name="status2019"):
1905
    """
1906
    Copy load timeseries data from entso-e.
1907
1908
    Returns
1909
    -------
1910
    None.
1911
1912
    """
1913
    sources = config.datasets()["electrical_neighbours"]["sources"]
1914
    targets = config.datasets()["electrical_neighbours"]["targets"]
1915
1916
    if scn_name == "status2019":
1917
        year_start_end = {"year_start": "20190101", "year_end": "20200101"}
1918
    elif scn_name == "status2023":
1919
        year_start_end = {"year_start": "20230101", "year_end": "20240101"}
1920
    else:
1921
        raise ValueError("No valid scenario name!")
1922
1923
    df_load_sq, not_retrieved = entsoe_historic_demand(**year_start_end)
1924
1925
    if not_retrieved:
1926
        logger.warning("Demand data from entsoe could not be retrieved.")
1927
        # check for generation backup from former runs
1928
        file_path = Path(
1929
            "./", "entsoe_data", f"load_entsoe_{scn_name}.csv"
1930
        ).resolve()
1931
        if os.path.isfile(file_path):
1932
            df_load_sq, not_retrieved = fill_by_backup_data_from_former_runs(
1933
                df_load_sq, file_path, not_retrieved
1934
            )
1935
        save_entsoe_data(df_load_sq, file_path=file_path)
1936
1937
    if not_retrieved:
1938
        logger.warning(
1939
            f"Backup data of 2019 is used instead for {not_retrieved}"
1940
        )
1941
        df_load_sq_backup = pd.read_csv(
1942
            "data_bundle_egon_data/entsoe/load_entsoe.csv", index_col="Index"
1943
        )
1944
        df_load_sq_backup.index = df_load_sq.index
1945
        df_load_sq = pd.concat(
1946
            [df_load_sq, df_load_sq_backup.loc[:, not_retrieved]], axis=1
1947
        )
1948
1949
    # Delete existing data
1950
    db.execute_sql(
1951
        f"""
1952
        DELETE FROM {targets['load_timeseries']['schema']}.
1953
        {targets['load_timeseries']['table']}
1954
        WHERE
1955
        scn_name = '{scn_name}'
1956
        AND load_id IN (
1957
        SELECT load_id FROM {targets['loads']['schema']}.
1958
        {targets['loads']['table']}
1959
        WHERE
1960
        scn_name = '{scn_name}'
1961
        AND carrier = 'AC'
1962
        AND bus NOT IN (
1963
            SELECT bus_i
1964
            FROM  {sources['osmtgmod_bus']['schema']}.
1965
            {sources['osmtgmod_bus']['table']}))
1966
        """
1967
    )
1968
1969
    db.execute_sql(
1970
        f"""
1971
        DELETE FROM {targets['loads']['schema']}.
1972
        {targets['loads']['table']}
1973
        WHERE
1974
        scn_name = '{scn_name}'
1975
        AND carrier = 'AC'
1976
        AND bus NOT IN (
1977
            SELECT bus_i
1978
            FROM  {sources['osmtgmod_bus']['schema']}.
1979
            {sources['osmtgmod_bus']['table']})
1980
        """
1981
    )
1982
1983
    # get the corresponding bus per foreign country
1984
    entsoe_to_bus = entsoe_to_bus_etrago(scn_name)
1985
1986
    # Calculate and insert demand timeseries per etrago bus_id
1987
    with session_scope() as session:
1988
        for country in df_load_sq.columns:
1989
            load_id = db.next_etrago_id("load")
1990
1991
            entry = etrago.EgonPfHvLoad(
1992
                scn_name=scn_name,
1993
                load_id=int(load_id),
1994
                carrier="AC",
1995
                bus=int(entsoe_to_bus[country]),
1996
            )
1997
1998
            entry_ts = etrago.EgonPfHvLoadTimeseries(
1999
                scn_name=scn_name,
2000
                load_id=int(load_id),
2001
                temp_id=1,
2002
                p_set=list(df_load_sq[country]),
2003
            )
2004
2005
            session.add(entry)
2006
            session.add(entry_ts)
2007
            session.commit()
2008
2009
2010
tasks = (grid,)
2011
2012
insert_per_scenario = set()
2013
2014
for scn_name in config.settings()["egon-data"]["--scenarios"]:
2015
2016
    if scn_name == "eGon2035":
2017
        insert_per_scenario.update([tyndp_generation, tyndp_demand])
2018
2019
    if "status" in scn_name:
2020
        postfix = f"_{scn_name.split('status')[-1]}"
2021
        insert_per_scenario.update(
2022
            [
2023
                wrapped_partial(
2024
                    insert_generators_sq, scn_name=scn_name, postfix=postfix
2025
                ),
2026
                wrapped_partial(
2027
                    insert_loads_sq, scn_name=scn_name, postfix=postfix
2028
                ),
2029
                wrapped_partial(
2030
                    insert_storage_units_sq, scn_name=scn_name, postfix=postfix
2031
                ),
2032
            ]
2033
        )
2034
2035
tasks = tasks + (insert_per_scenario,)
2036
2037
2038
class ElectricalNeighbours(Dataset):
2039
    def __init__(self, dependencies):
2040
        super().__init__(
2041
            name="ElectricalNeighbours",
2042
            version="0.0.11",
2043
            dependencies=dependencies,
2044
            tasks=tasks,
2045
        )
2046