Completed
Push — dev ( 446f66...1681a8 )
by
unknown
22s queued 13s
created

data.datasets.etrago_setup   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 1225
Duplicated Lines 12 %

Importance

Changes 0
Metric Value
wmc 17
eloc 880
dl 147
loc 1225
rs 9.72
c 0
b 0
f 0

8 Functions

Rating   Name   Duplication   Size   Complexity  
A get_pypsa_field_descriptors() 0 28 2
B get_meta() 0 60 2
B check_carriers() 0 38 5
A create_etrago_id_sequences() 0 33 2
B create_tables() 0 126 1
A temp_resolution() 0 11 1
B insert_carriers() 0 75 1
A link_geom_from_buses() 0 41 2

1 Method

Rating   Name   Duplication   Size   Complexity  
A EtragoSetup.__init__() 0 9 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
# coding: utf-8
2
import datetime
3
import json
4
5
from geoalchemy2.types import Geometry
6
from shapely.geometry import LineString
7
from sqlalchemy import (
8
    ARRAY,
9
    BigInteger,
10
    Boolean,
11
    Column,
12
    DateTime,
13
    Float,
14
    Integer,
15
    Numeric,
16
    String,
17
    Text,
18
    text,
19
)
20
from sqlalchemy.ext.declarative import declarative_base
21
import geopandas as gpd
22
import pandas as pd
23
import pypsa
24
25
from egon.data import db
26
from egon.data.datasets import Dataset
27
from egon.data.metadata import (
28
    context,
29
    contributors,
30
    license_egon_data_odbl,
31
    meta_metadata,
32
    sources,
33
)
34
35
Base = declarative_base()
36
metadata = Base.metadata
37
38
network = pypsa.Network()
39
# add Storage key (called StorageUnit in PyPSA)
40
network.component_attrs["Storage"] = network.component_attrs["StorageUnit"]
41
42
43
def get_pypsa_field_descriptors(component, timeseries=False):
44
45
    ident = component.lower() + "_id"
46
47
    data = network.component_attrs[component].rename({"name": ident})
48
    data = data[data.status != "Output"]
49
50
    if timeseries:
51
        data = data[data["type"].str.contains("series")]
52
        data.loc["temp_id"] = [
53
            "integer",
54
            "n/a",
55
            "n/a",
56
            "Unique identifyier of temporal index",
57
            "Input",
58
        ]
59
60
    data.loc[ident, "type"] = "int"
61
    data.loc["scn_name"] = [
62
        "string",
63
        "n/a",
64
        "n/a",
65
        "Name of the eGon scenario",
66
        "Input",
67
    ]
68
    data.unit.fillna("none", inplace=True)
69
    data.default.fillna("n/a", inplace=True)
70
    return data
71
72
73
def get_meta(
74
    schema,
75
    component,
76
    description="TODO",
77
    source_list=[],
78
    contributor_list=[],
79
    timeseries=False,
80
):
81
82
    table = "egon_etrago_" + component.lower()
83
84
    if timeseries:
85
        table = table + "_timeseries"
86
    fields = (
87
        get_pypsa_field_descriptors(component, timeseries)
88
        .reset_index()
89
        .to_dict(orient="records")
90
    )
91
    # geometry column still missing
92
93
    meta = {
94
        "name": schema + "." + table,
95
        "title": component,
96
        "id": "WILL_BE_SET_AT_PUBLICATION",
97
        # no automatic description? PyPSA descriptions do not quite fit our
98
        # scope
99
        "description": description,
100
        "language": ["en-EN"],
101
        "publicationDate": datetime.date.today().isoformat(),
102
        "context": context(),
103
        "spatial": {
104
            "location": None,
105
            "extent": "Germany",
106
            "resolution": None,
107
        },
108
        "sources": source_list,
109
        "licenses": [license_egon_data_odbl()],
110
        "contributors": contributor_list,
111
        "resources": [
112
            {
113
                "profile": "tabular-data-resource",
114
                "name": schema + "." + table,
115
                "path": None,
116
                "format": "PostgreSQL",
117
                "encoding": "UTF-8",
118
                "schema": {
119
                    "fields": fields,
120
                    "primaryKey": ["scn_name", component.lower() + "_id"],
121
                    "foreignKeys": [],
122
                },
123
                "dialect": {"delimiter": "", "decimalSeparator": ""},
124
            }
125
        ],
126
        "metaMetadata": meta_metadata(),
127
    }
128
129
    # Create json dump
130
    meta_json = "'" + json.dumps(meta, indent=4, ensure_ascii=False) + "'"
131
132
    return meta_json
133
134
135
class EtragoSetup(Dataset):
136
    def __init__(self, dependencies):
137
        super().__init__(
138
            name="EtragoSetup",
139
            version="0.0.12",
140
            dependencies=dependencies,
141
            tasks=(
142
                create_tables,
143
                create_etrago_id_sequences,
144
                {temp_resolution, insert_carriers},
145
            ),
146
        )
147
148
149
class EgonPfHvBus(Base):
150
151
    source_list = [
152
        sources()["egon-data"],
153
        sources()["openstreetmap"],
154
        sources()["peta"],
155
        sources()["SciGRID_gas"],
156
        sources()["bgr_inspeeds_data_bundle"],
157
    ]
158
159
    contributor_list = contributors(["ic", "cb", "ke", "an", "fw"])
160
    contributor_list[0]["comment"] = "Added electricity substations"
161
    contributor_list[1]["comment"] = "Added heat buses"
162
    contributor_list[2]["comment"] = "Added DSM buses"
163
    contributor_list[3]["comment"] = "Added CH4 sector buses"
164
    contributor_list[4]["comment"] = "Added H2 sector buses"
165
166
    __tablename__ = "egon_etrago_bus"
167
    __table_args__ = {
168
        "schema": "grid",
169
        "comment": get_meta(
170
            "grid",
171
            "Bus",
172
            source_list=source_list,
173
            contributor_list=contributor_list,
174
        ),
175
    }
176
177
    scn_name = Column(String, primary_key=True, nullable=False)
178
    bus_id = Column(BigInteger, primary_key=True, nullable=False)
179
    v_nom = Column(Float(53), server_default="1.")
180
    type = Column(Text)
181
    carrier = Column(Text)
182
    v_mag_pu_set = Column(Float(53))
183
    v_mag_pu_min = Column(Float(53), server_default="0.")
184
    v_mag_pu_max = Column(Float(53), server_default="inf")
185
    x = Column(Float(53), server_default="0.")
186
    y = Column(Float(53), server_default="0.")
187
    geom = Column(Geometry("POINT", 4326), index=True)
188
    country = Column(Text, server_default=text("'DE'::text"))
189
190
191 View Code Duplication
class EgonPfHvBusTimeseries(Base):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
192
193
    source_list = [
194
        sources()["egon-data"],
195
    ]
196
197
    contributor_list = contributors(["cb"])
198
    contributor_list[0]["comment"] = "Added metadata"
199
200
    __tablename__ = "egon_etrago_bus_timeseries"
201
    __table_args__ = {
202
        "schema": "grid",
203
        "comment": get_meta(
204
            "grid",
205
            "Bus",
206
            source_list=source_list,
207
            contributor_list=contributor_list,
208
            timeseries=True,
209
        ),
210
    }
211
212
    scn_name = Column(String, primary_key=True, nullable=False)
213
    bus_id = Column(BigInteger, primary_key=True, nullable=False)
214
    v_mag_pu_set = Column(ARRAY(Float(precision=53)))
215
216
217
class EgonPfHvGenerator(Base):
218
219
    source_list = [
220
        sources()["egon-data"],
221
        sources()["openstreetmap"],
222
        sources()["mastr"],
223
        sources()["nep2021"],
224
        sources()["tyndp"],
225
        sources()["SciGRID_gas"],
226
        sources()["Einspeiseatlas"],
227
        sources()["technology-data"],
228
        sources()["vg250"],
229
    ]
230
231
    contributor_list = contributors(["ic", "cb", "ce", "an", "ke"])
232
    contributor_list[0]["comment"] = "Added hydro and biomass plants"
233
    contributor_list[1]["comment"] = "Added solar and geothermal plants"
234
    contributor_list[2]["comment"] = "Added wind on- and offshore plants"
235
    contributor_list[3]["comment"] = "Added gas feedin generators"
236
    contributor_list[4]["comment"] = "Added pv ground mounted"
237
238
    __tablename__ = "egon_etrago_generator"
239
    __table_args__ = {
240
        "schema": "grid",
241
        "comment": get_meta(
242
            "grid",
243
            "Generator",
244
            source_list=source_list,
245
            contributor_list=contributor_list,
246
        ),
247
    }
248
249
    scn_name = Column(String, primary_key=True, nullable=False)
250
    generator_id = Column(BigInteger, primary_key=True, nullable=False)
251
    bus = Column(BigInteger)
252
    control = Column(Text)
253
    type = Column(Text)
254
    carrier = Column(Text)
255
    p_nom = Column(Float(53), server_default="0.")
256
    p_nom_extendable = Column(Boolean, server_default="False")
257
    p_nom_min = Column(Float(53), server_default="0.")
258
    p_nom_max = Column(Float(53), server_default="inf")
259
    p_min_pu = Column(Float(53), server_default="0.")
260
    p_max_pu = Column(Float(53), server_default="1.")
261
    p_set = Column(Float(53))
262
    q_set = Column(Float(53))
263
    sign = Column(Float(53), server_default="1.")
264
    marginal_cost = Column(Float(53), server_default="0.")
265
    build_year = Column(BigInteger, server_default="0")
266
    lifetime = Column(Float(53), server_default="inf")
267
    capital_cost = Column(Float(53), server_default="0.")
268
    efficiency = Column(Float(53), server_default="1.")
269
    committable = Column(Boolean, server_default="False")
270
    start_up_cost = Column(Float(53), server_default="0.")
271
    shut_down_cost = Column(Float(53), server_default="0.")
272
    min_up_time = Column(BigInteger, server_default="0")
273
    min_down_time = Column(BigInteger, server_default="0")
274
    up_time_before = Column(BigInteger, server_default="0")
275
    down_time_before = Column(BigInteger, server_default="0")
276
    ramp_limit_up = Column(Float(53), server_default="NaN")
277
    ramp_limit_down = Column(Float(53), server_default="NaN")
278
    ramp_limit_start_up = Column(Float(53), server_default="1.")
279
    ramp_limit_shut_down = Column(Float(53), server_default="1.")
280
    e_nom_max = Column(
281
        Float(53), server_default="inf"
282
    )  # [MWh(/y)] Value to be used in eTraGo to set constraint for the production over the year
283
284
285
class EgonPfHvGeneratorTimeseries(Base):
286
287
    source_list = [
288
        sources()["egon-data"],
289
        sources()["era5"],
290
    ]
291
292
    contributor_list = contributors(["cb"])
293
    contributor_list[0][
294
        "comment"
295
    ] = "Added p_max_pu timeseries for pv and wind"
296
297
    __tablename__ = "egon_etrago_generator_timeseries"
298
    __table_args__ = {
299
        "schema": "grid",
300
        "comment": get_meta(
301
            "grid",
302
            "Generator",
303
            source_list=source_list,
304
            contributor_list=contributor_list,
305
            timeseries=True,
306
        ),
307
    }
308
309
    scn_name = Column(String, primary_key=True, nullable=False)
310
    generator_id = Column(Integer, primary_key=True, nullable=False)
311
    temp_id = Column(Integer, primary_key=True, nullable=False)
312
    p_set = Column(ARRAY(Float(precision=53)))
313
    q_set = Column(ARRAY(Float(precision=53)))
314
    p_min_pu = Column(ARRAY(Float(precision=53)))
315
    p_max_pu = Column(ARRAY(Float(precision=53)))
316
    marginal_cost = Column(ARRAY(Float(precision=53)))
317
318
319 View Code Duplication
class EgonPfHvLine(Base):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
320
321
    source_list = [
322
        sources()["egon-data"],
323
        sources()["openstreetmap"],
324
    ]
325
326
    contributor_list = contributors(["ic", "cb"])
327
    contributor_list[0]["comment"] = "Added lines from osmTGmod tables"
328
    contributor_list[1]["comment"] = "Added meta data"
329
330
    __tablename__ = "egon_etrago_line"
331
    __table_args__ = {
332
        "schema": "grid",
333
        "comment": get_meta(
334
            "grid",
335
            "Line",
336
            source_list=source_list,
337
            contributor_list=contributor_list,
338
        ),
339
    }
340
341
    scn_name = Column(String, primary_key=True, nullable=False)
342
    line_id = Column(BigInteger, primary_key=True, nullable=False)
343
    bus0 = Column(BigInteger)
344
    bus1 = Column(BigInteger)
345
    type = Column(Text)
346
    carrier = Column(Text)
347
    x = Column(Numeric, server_default="0.")
348
    r = Column(Numeric, server_default="0.")
349
    g = Column(Numeric, server_default="0.")
350
    b = Column(Numeric, server_default="0.")
351
    s_nom = Column(Numeric, server_default="0.")
352
    s_nom_extendable = Column(Boolean, server_default="False")
353
    s_nom_min = Column(Float(53), server_default="0.")
354
    s_nom_max = Column(Float(53), server_default="inf")
355
    s_max_pu = Column(Float(53), server_default="1.")
356
    build_year = Column(BigInteger, server_default="0")
357
    lifetime = Column(Float(53), server_default="inf")
358
    capital_cost = Column(Float(53), server_default="0.")
359
    length = Column(Float(53), server_default="0.")
360
    cables = Column(Integer)
361
    terrain_factor = Column(Float(53), server_default="1.")
362
    num_parallel = Column(Float(53), server_default="1.")
363
    v_ang_min = Column(Float(53), server_default="-inf")
364
    v_ang_max = Column(Float(53), server_default="inf")
365
    v_nom = Column(Float(53))
366
    geom = Column(Geometry("MULTILINESTRING", 4326))
367
    topo = Column(Geometry("LINESTRING", 4326))
368
369
370
class EgonPfHvLineTimeseries(Base):
371
372
    source_list = [
373
        sources()["egon-data"],
374
        sources()["nep2021"],
375
        sources()["era5"],
376
    ]
377
378
    contributor_list = contributors(["ce", "cb"])
379
    contributor_list[0]["comment"] = "Added s_max_pu timeseries"
380
    contributor_list[1]["comment"] = "Added meta data"
381
382
    __tablename__ = "egon_etrago_line_timeseries"
383
    __table_args__ = {
384
        "schema": "grid",
385
        "comment": get_meta(
386
            "grid",
387
            "Line",
388
            source_list=source_list,
389
            contributor_list=contributor_list,
390
            timeseries=True,
391
        ),
392
    }
393
394
    scn_name = Column(String, primary_key=True, nullable=False)
395
    line_id = Column(BigInteger, primary_key=True, nullable=False)
396
    temp_id = Column(Integer, primary_key=True, nullable=False)
397
    s_max_pu = Column(ARRAY(Float(precision=53)))
398
399
400
class EgonPfHvLink(Base):
401
402
    source_list = [
403
        sources()["egon-data"],
404
        sources()["openstreetmap"],
405
        sources()["nep2021"],
406
        sources()["peta"],
407
        sources()["mastr"],
408
        sources()["SciGRID_gas"],
409
        sources()["pipeline_classification"],
410
        sources()["technology-data"],
411
        sources()["dsm-heitkoetter"],
412
        sources()["schmidt"],
413
        sources()["hotmaps_industrial_sites"],
414
        sources()["demandregio"],
415
    ]
416
417
    contributor_list = contributors(["ic", "cb", "ke", "ja", "fw", "an"])
418
    contributor_list[0]["comment"] = "Added DC lines from osmTGmod tables"
419
    contributor_list[1]["comment"] = "Added CHPs and heat links"
420
    contributor_list[2]["comment"] = "Added DSM links"
421
    contributor_list[3]["comment"] = "Added e-Mobility links"
422
    contributor_list[4]["comment"] = "Added H2 related links"
423
    contributor_list[5]["comment"] = "Added CH4 links"
424
425
    __tablename__ = "egon_etrago_link"
426
    __table_args__ = {
427
        "schema": "grid",
428
        "comment": get_meta(
429
            "grid",
430
            "Link",
431
            source_list=source_list,
432
            contributor_list=contributor_list,
433
        ),
434
    }
435
436
    __tablename__ = "egon_etrago_link"
437
    __table_args__ = {"schema": "grid", "comment": get_meta("grid", "Link")}
438
439
    scn_name = Column(String, primary_key=True, nullable=False)
440
    link_id = Column(BigInteger, primary_key=True, nullable=False)
441
    bus0 = Column(BigInteger)
442
    bus1 = Column(BigInteger)
443
    type = Column(Text)
444
    carrier = Column(Text)
445
    efficiency = Column(Float(53), server_default="1.")
446
    build_year = Column(BigInteger, server_default="0")
447
    lifetime = Column(Float(53), server_default="inf")
448
    p_nom = Column(Numeric, server_default="0.")
449
    p_nom_extendable = Column(Boolean, server_default="False")
450
    p_nom_min = Column(Float(53), server_default="0.")
451
    p_nom_max = Column(Float(53), server_default="inf")
452
    p_min_pu = Column(Float(53), server_default="0.")
453
    p_max_pu = Column(Float(53), server_default="1.")
454
    p_set = Column(Float(53))
455
    capital_cost = Column(Float(53), server_default="0.")
456
    marginal_cost = Column(Float(53), server_default="0.")
457
    length = Column(Float(53), server_default="0.")
458
    terrain_factor = Column(Float(53), server_default="1.")
459
    geom = Column(Geometry("MULTILINESTRING", 4326))
460
    topo = Column(Geometry("LINESTRING", 4326))
461
462
463
class EgonPfHvLinkTimeseries(Base):
464
    source_list = [
465
        sources()["egon-data"],
466
        sources()["era5"],
467
        sources()["dsm-heitkoetter"],
468
        sources()["schmidt"],
469
        sources()["hotmaps_industrial_sites"],
470
        sources()["openstreetmap"],
471
        sources()["demandregio"],
472
    ]
473
474
    contributor_list = contributors(["cb", "ke", "ja"])
475
    contributor_list[0][
476
        "comment"
477
    ] = "Added efficiency timeseries for heat pumps"
478
    contributor_list[1]["comment"] = "Added dsm link timeseries"
479
    contributor_list[2]["comment"] = "Added e mobility link timeseries"
480
481
    __tablename__ = "egon_etrago_link_timeseries"
482
    __table_args__ = {
483
        "schema": "grid",
484
        "comment": get_meta(
485
            "grid",
486
            "Link",
487
            source_list=source_list,
488
            contributor_list=contributor_list,
489
            timeseries=True,
490
        ),
491
    }
492
493
    scn_name = Column(String, primary_key=True, nullable=False)
494
    link_id = Column(BigInteger, primary_key=True, nullable=False)
495
    temp_id = Column(Integer, primary_key=True, nullable=False)
496
    p_set = Column(ARRAY(Float(precision=53)))
497
    p_min_pu = Column(ARRAY(Float(precision=53)))
498
    p_max_pu = Column(ARRAY(Float(precision=53)))
499
    efficiency = Column(ARRAY(Float(precision=53)))
500
    marginal_cost = Column(ARRAY(Float(precision=53)))
501
502
503
class EgonPfHvLoad(Base):
504
505
    source_list = [
506
        sources()["egon-data"],
507
        sources()["demandregio"],
508
        sources()["nep2021"],
509
        sources()["peta"],
510
        sources()["schmidt"],
511
        sources()["hotmaps_industrial_sites"],
512
        sources()["openstreetmap"],
513
        sources()["openffe_gas"],
514
        sources()["tyndp"],
515
    ]
516
517
    contributor_list = contributors(["ic", "cb", "an", "ja"])
518
    contributor_list[0]["comment"] = "Added electrical demands"
519
    contributor_list[1]["comment"] = "Added heat deands"
520
    contributor_list[2]["comment"] = "Added gas demands"
521
    contributor_list[3]["comment"] = "Added mobility demands"
522
523
    __tablename__ = "egon_etrago_load"
524
    __table_args__ = {
525
        "schema": "grid",
526
        "comment": get_meta(
527
            "grid",
528
            "Load",
529
            source_list=source_list,
530
            contributor_list=contributor_list,
531
        ),
532
    }
533
534
    scn_name = Column(String, primary_key=True, nullable=False)
535
    load_id = Column(BigInteger, primary_key=True, nullable=False)
536
    bus = Column(BigInteger)
537
    type = Column(Text)
538
    carrier = Column(Text)
539
    p_set = Column(Float(53))
540
    q_set = Column(Float(53))
541
    sign = Column(Float(53), server_default="-1.")
542
543
544
class EgonPfHvLoadTimeseries(Base):
545
    source_list = [
546
        sources()["egon-data"],
547
        sources()["demandregio"],
548
        sources()["nep2021"],
549
        sources()["peta"],
550
        sources()["openffe_gas"],
551
        sources()["tyndp"],
552
        sources()["era5"],
553
        sources()["schmidt"],
554
        sources()["hotmaps_industrial_sites"],
555
        sources()["openstreetmap"],
556
    ]
557
558
    contributor_list = contributors(["cb", "ic", "ja", "an"])
559
    contributor_list[0]["comment"] = "Added heat load timeseries"
560
    contributor_list[1]["comment"] = "Added electricity load timeseries"
561
    contributor_list[2]["comment"] = "Added e mobility load timeseries"
562
    contributor_list[3]["comment"] = "Added gas load timeseries"
563
564
    __tablename__ = "egon_etrago_load_timeseries"
565
    __table_args__ = {
566
        "schema": "grid",
567
        "comment": get_meta(
568
            "grid",
569
            "Load",
570
            source_list=source_list,
571
            contributor_list=contributor_list,
572
            timeseries=True,
573
        ),
574
    }
575
576
    scn_name = Column(String, primary_key=True, nullable=False)
577
    load_id = Column(BigInteger, primary_key=True, nullable=False)
578
    temp_id = Column(Integer, primary_key=True, nullable=False)
579
    p_set = Column(ARRAY(Float(precision=53)))
580
    q_set = Column(ARRAY(Float(precision=53)))
581
582
583
class EgonPfHvCarrier(Base):
584
    source_list = [
585
        sources()["egon-data"],
586
    ]
587
588
    contributor_list = contributors(["fw"])
589
    contributor_list[0]["comment"] = "Added list of carriers"
590
591
    __tablename__ = "egon_etrago_carrier"
592
    __table_args__ = {
593
        "schema": "grid",
594
        "comment": get_meta(
595
            "grid",
596
            "Carrier",
597
            source_list=source_list,
598
            contributor_list=contributor_list,
599
        ),
600
    }
601
602
    name = Column(Text, primary_key=True, nullable=False)
603
    co2_emissions = Column(Float(53), server_default="0.")
604
    color = Column(Text)
605
    nice_name = Column(Text)
606
    commentary = Column(Text)
607
608
609
class EgonPfHvStorage(Base):
610
611
    source_list = [
612
        sources()["egon-data"],
613
        sources()["nep2021"],
614
        sources()["mastr"],
615
        sources()["technology-data"],
616
    ]
617
618
    contributor_list = contributors(["ic"])
619
    contributor_list[0][
620
        "comment"
621
    ] = "Added battery and pumped hydro storage units"
622
623
    __tablename__ = "egon_etrago_storage"
624
    __table_args__ = {
625
        "schema": "grid",
626
        "comment": get_meta(
627
            "grid",
628
            "Storage",
629
            source_list=source_list,
630
            contributor_list=contributor_list,
631
        ),
632
    }
633
634
    scn_name = Column(String, primary_key=True, nullable=False)
635
    storage_id = Column(BigInteger, primary_key=True, nullable=False)
636
    bus = Column(BigInteger)
637
    control = Column(Text)
638
    type = Column(Text)
639
    carrier = Column(Text)
640
    p_nom = Column(Float(53), server_default="0.")
641
    p_nom_extendable = Column((Boolean), server_default="False")
642
    p_nom_min = Column(Float(53), server_default="0.")
643
    p_nom_max = Column(Float(53), server_default="inf")
644
    p_min_pu = Column(Float(53), server_default="-1.")
645
    p_max_pu = Column(Float(53), server_default="1.")
646
    p_set = Column(Float(53))
647
    q_set = Column(Float(53))
648
    sign = Column(Float(53), server_default="1")
649
    marginal_cost = Column(Float(53), server_default="0.")
650
    capital_cost = Column(Float(53), server_default="0.")
651
    build_year = Column(BigInteger, server_default="0")
652
    lifetime = Column(Float(53), server_default="inf")
653
    state_of_charge_initial = Column(Float(53), server_default="0")
654
    cyclic_state_of_charge = Column(Boolean, server_default="False")
655
    state_of_charge_set = Column(Float(53))
656
    max_hours = Column(Float(53), server_default="1")
657
    efficiency_store = Column(Float(53), server_default="1.")
658
    efficiency_dispatch = Column(Float(53), server_default="1.")
659
    standing_loss = Column(Float(53), server_default="0.")
660
    inflow = Column(Float(53), server_default="0.")
661
662
663
class EgonPfHvStorageTimeseries(Base):
664
    source_list = [
665
        sources()["egon-data"],
666
    ]
667
668
    contributor_list = contributors(["cb"])
669
    contributor_list[0]["comment"] = "Added metadata"
670
671
    __tablename__ = "egon_etrago_storage_timeseries"
672
    __table_args__ = {
673
        "schema": "grid",
674
        "comment": get_meta(
675
            "grid",
676
            "Storage",
677
            source_list=source_list,
678
            contributor_list=contributor_list,
679
            timeseries=True,
680
        ),
681
    }
682
683
    scn_name = Column(String, primary_key=True, nullable=False)
684
    storage_id = Column(BigInteger, primary_key=True, nullable=False)
685
    temp_id = Column(Integer, primary_key=True, nullable=False)
686
    p_set = Column(ARRAY(Float(precision=53)))
687
    q_set = Column(ARRAY(Float(precision=53)))
688
    p_min_pu = Column(ARRAY(Float(precision=53)))
689
    p_max_pu = Column(ARRAY(Float(precision=53)))
690
    state_of_charge_set = Column(ARRAY(Float(precision=53)))
691
    inflow = Column(ARRAY(Float(precision=53)))
692
    marginal_cost = Column(ARRAY(Float(precision=53)))
693
694
695
class EgonPfHvStore(Base):
696
    source_dict = sources()
697
698
    source_list = [
699
        source_dict["bgr_inspee"],
700
        source_dict["bgr_inspeeds"],
701
        source_dict["bgr_inspeeds_data_bundle"],
702
        source_dict["bgr_inspeeds_report"],
703
        source_dict["SciGRID_gas"],
704
        sources()["technology-data"],
705
        sources()["dsm-heitkoetter"],
706
        sources()["schmidt"],
707
        sources()["hotmaps_industrial_sites"],
708
        sources()["openstreetmap"],
709
        sources()["demandregio"],
710
    ]
711
    contributor_list = contributors(["an", "fw", "ke", "cb", "ja"])
712
    contributor_list[0]["comment"] = "Add H2 storage"
713
    contributor_list[1]["comment"] = "Add CH4 storage"
714
    contributor_list[2]["comment"] = "Add DSM storage"
715
    contributor_list[3]["comment"] = "Add heat storage"
716
    contributor_list[4]["comment"] = "Add e-mobility storage"
717
718
    __tablename__ = "egon_etrago_store"
719
    __table_args__ = {
720
        "schema": "grid",
721
        "comment": get_meta(
722
            "grid",
723
            "Store",
724
            source_list=source_list,
725
            contributor_list=contributor_list,
726
        ),
727
    }
728
729
    scn_name = Column(String, primary_key=True, nullable=False)
730
    store_id = Column(BigInteger, primary_key=True, nullable=False)
731
    bus = Column(BigInteger)
732
    type = Column(Text)
733
    carrier = Column(Text)
734
    e_nom = Column(Float(53), server_default="0.")
735
    e_nom_extendable = Column((Boolean), server_default="False")
736
    e_nom_min = Column(Float(53), server_default="0.")
737
    e_nom_max = Column(Float(53), server_default="inf")
738
    e_min_pu = Column(Float(53), server_default="0.")
739
    e_max_pu = Column(Float(53), server_default="1.")
740
    p_set = Column(Float(53))
741
    q_set = Column(Float(53))
742
    e_initial = Column(Float(53), server_default="0.")
743
    e_cyclic = Column(Boolean, server_default="False")
744
    sign = Column(Float(53), server_default="1")
745
    marginal_cost = Column(Float(53), server_default="0.")
746
    capital_cost = Column(Float(53), server_default="0.")
747
    standing_loss = Column(Float(53), server_default="0.")
748
    build_year = Column(BigInteger, server_default="0")
749
    lifetime = Column(Float(53), server_default="inf")
750
751
752
class EgonPfHvStoreTimeseries(Base):
753
    source_dict = sources()
754
    # TODO: Add other sources for dsm
755
    source_list = [
756
        sources()["technology-data"],
757
        sources()["dsm-heitkoetter"],
758
        sources()["schmidt"],
759
        sources()["hotmaps_industrial_sites"],
760
        sources()["openstreetmap"],
761
        sources()["demandregio"],
762
    ]
763
    contributor_list = contributors(["ke", "ja"])
764
    contributor_list[0]["comment"] = "Add DSM storage"
765
    contributor_list[1]["comment"] = "Add e-mobility storage"
766
767
    __tablename__ = "egon_etrago_store_timeseries"
768
    __table_args__ = {
769
        "schema": "grid",
770
        "comment": get_meta(
771
            "grid",
772
            "Store",
773
            source_list=source_list,
774
            contributor_list=contributor_list,
775
            timeseries=True,
776
        ),
777
    }
778
    scn_name = Column(String, primary_key=True, nullable=False)
779
    store_id = Column(BigInteger, primary_key=True, nullable=False)
780
    temp_id = Column(Integer, primary_key=True, nullable=False)
781
    p_set = Column(ARRAY(Float(precision=53)))
782
    q_set = Column(ARRAY(Float(precision=53)))
783
    e_min_pu = Column(ARRAY(Float(precision=53)))
784
    e_max_pu = Column(ARRAY(Float(precision=53)))
785
    marginal_cost = Column(ARRAY(Float(precision=53)))
786
787
788
class EgonPfHvTempResolution(Base):
789
    __tablename__ = "egon_etrago_temp_resolution"
790
    __table_args__ = {"schema": "grid"}
791
792
    temp_id = Column(BigInteger, primary_key=True, nullable=False)
793
    timesteps = Column(BigInteger, nullable=False)
794
    resolution = Column(Text)
795
    start_time = Column(DateTime)
796
797
798 View Code Duplication
class EgonPfHvTransformer(Base):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
799
800
    source_list = [
801
        sources()["egon-data"],
802
        sources()["openstreetmap"],
803
    ]
804
805
    contributor_list = contributors(["ic", "cb"])
806
    contributor_list[0]["comment"] = "Added transformes from osmTGmod tables"
807
    contributor_list[1]["comment"] = "Added meta data"
808
809
    __tablename__ = "egon_etrago_transformer"
810
    __table_args__ = {
811
        "schema": "grid",
812
        "comment": get_meta(
813
            "grid",
814
            "Transformer",
815
            source_list=source_list,
816
            contributor_list=contributor_list,
817
        ),
818
    }
819
820
    scn_name = Column(String, primary_key=True, nullable=False)
821
    trafo_id = Column(BigInteger, primary_key=True, nullable=False)
822
    bus0 = Column(BigInteger)
823
    bus1 = Column(BigInteger)
824
    type = Column(Text)
825
    model = Column((Text), server_default="t")
826
    x = Column((Numeric), server_default="0.")
827
    r = Column((Numeric), server_default="0.")
828
    g = Column((Numeric), server_default="0.")
829
    b = Column((Numeric), server_default="0.")
830
    s_nom = Column(Float(53), server_default="0.")
831
    s_nom_extendable = Column((Boolean), server_default="False")
832
    s_nom_min = Column(Float(53), server_default="0.")
833
    s_nom_max = Column(Float(53), server_default="inf")
834
    s_max_pu = Column(Float(53), server_default="1.")
835
    tap_ratio = Column(Float(53), server_default="1.")
836
    tap_side = Column((BigInteger), server_default="0")
837
    tap_position = Column((BigInteger), server_default="0")
838
    phase_shift = Column(Float(53), server_default="0.")
839
    build_year = Column(BigInteger, server_default="0")
840
    lifetime = Column(Float(53), server_default="inf")
841
    v_ang_min = Column(Float(53), server_default="-inf")
842
    v_ang_max = Column(Float(53), server_default="inf")
843
    capital_cost = Column(Float(53), server_default="0.")
844
    num_parallel = Column(Float(53), server_default="1.")
845
    geom = Column(Geometry("MULTILINESTRING", 4326))
846
    topo = Column(Geometry("LINESTRING", 4326))
847
848
849 View Code Duplication
class EgonPfHvTransformerTimeseries(Base):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
850
    source_list = [
851
        sources()["egon-data"],
852
    ]
853
854
    contributor_list = contributors(["cb"])
855
    contributor_list[0]["comment"] = "Added meta data"
856
857
    __tablename__ = "egon_etrago_transformer_timeseries"
858
    __table_args__ = {
859
        "schema": "grid",
860
        "comment": get_meta(
861
            "grid",
862
            "Transformer",
863
            source_list=source_list,
864
            contributor_list=contributor_list,
865
            timeseries=True,
866
        ),
867
    }
868
869
    scn_name = Column(String, primary_key=True, nullable=False)
870
    trafo_id = Column(BigInteger, primary_key=True, nullable=False)
871
    temp_id = Column(Integer, primary_key=True, nullable=False)
872
    s_max_pu = Column(ARRAY(Float(precision=53)))
873
874
875
class EgonPfHvBusmap(Base):
876
    __tablename__ = "egon_etrago_hv_busmap"
877
    __table_args__ = {"schema": "grid"}
878
879
    scn_name = Column(Text, primary_key=True, nullable=False)
880
    bus0 = Column(Text, primary_key=True, nullable=False)
881
    bus1 = Column(Text, primary_key=True, nullable=False)
882
    path_length = Column(Numeric)
883
    version = Column(Text, primary_key=True, nullable=False)
884
885
886
def create_tables():
887
    """Create tables for eTraGo input data.
888
    Returns
889
    -------
890
    None.
891
    """
892
    db.execute_sql("CREATE SCHEMA IF NOT EXISTS grid;")
893
    engine = db.engine()
894
895
    ##################### drop tables with old names #########################
896
    db.execute_sql(
897
        """
898
        DROP TABLE IF EXISTS grid.egon_pf_hv_bus;"""
899
    )
900
    db.execute_sql(
901
        """
902
        DROP TABLE IF EXISTS grid.egon_pf_hv_bus_timeseries;"""
903
    )
904
    db.execute_sql(
905
        """
906
        DROP TABLE IF EXISTS grid.egon_pf_hv_carrier;"""
907
    )
908
    db.execute_sql(
909
        """
910
        DROP TABLE IF EXISTS grid.egon_pf_hv_generator;"""
911
    )
912
    db.execute_sql(
913
        """
914
        DROP TABLE IF EXISTS grid.egon_pf_hv_generator_timeseries;"""
915
    )
916
    db.execute_sql(
917
        """
918
        DROP TABLE IF EXISTS grid.egon_pf_hv_line;"""
919
    )
920
    db.execute_sql(
921
        """
922
        DROP TABLE IF EXISTS grid.egon_pf_hv_line_timeseries;"""
923
    )
924
    db.execute_sql(
925
        """
926
        DROP TABLE IF EXISTS grid.egon_pf_hv_link;"""
927
    )
928
    db.execute_sql(
929
        """
930
        DROP TABLE IF EXISTS grid.egon_pf_hv_link_timeseries;"""
931
    )
932
    db.execute_sql(
933
        """
934
        DROP TABLE IF EXISTS grid.egon_pf_hv_load;"""
935
    )
936
    db.execute_sql(
937
        """
938
        DROP TABLE IF EXISTS grid.egon_pf_hv_load_timeseries;"""
939
    )
940
    db.execute_sql(
941
        """
942
        DROP TABLE IF EXISTS grid.egon_pf_hv_storage;"""
943
    )
944
    db.execute_sql(
945
        """
946
        DROP TABLE IF EXISTS grid.egon_pf_hv_storage_timeseries;"""
947
    )
948
    db.execute_sql(
949
        """
950
        DROP TABLE IF EXISTS grid.egon_pf_hv_store;"""
951
    )
952
    db.execute_sql(
953
        """
954
        DROP TABLE IF EXISTS grid.egon_pf_hv_store_timeseries;"""
955
    )
956
    db.execute_sql(
957
        """
958
        DROP TABLE IF EXISTS grid.egon_pf_hv_temp_resolution;"""
959
    )
960
    db.execute_sql(
961
        """
962
        DROP TABLE IF EXISTS grid.egon_pf_hv_transformer;"""
963
    )
964
    db.execute_sql(
965
        """
966
        DROP TABLE IF EXISTS grid.egon_pf_hv_transformer_timeseries;"""
967
    )
968
    ##########################################################################
969
970
    # Drop existing tables
971
    EgonPfHvBus.__table__.drop(bind=engine, checkfirst=True)
972
    EgonPfHvBusTimeseries.__table__.drop(bind=engine, checkfirst=True)
973
    EgonPfHvGenerator.__table__.drop(bind=engine, checkfirst=True)
974
    EgonPfHvGeneratorTimeseries.__table__.drop(bind=engine, checkfirst=True)
975
    EgonPfHvLine.__table__.drop(bind=engine, checkfirst=True)
976
    EgonPfHvLineTimeseries.__table__.drop(bind=engine, checkfirst=True)
977
    EgonPfHvLink.__table__.drop(bind=engine, checkfirst=True)
978
    EgonPfHvLinkTimeseries.__table__.drop(bind=engine, checkfirst=True)
979
    EgonPfHvLoad.__table__.drop(bind=engine, checkfirst=True)
980
    EgonPfHvLoadTimeseries.__table__.drop(bind=engine, checkfirst=True)
981
    EgonPfHvCarrier.__table__.drop(bind=engine, checkfirst=True)
982
    EgonPfHvStorage.__table__.drop(bind=engine, checkfirst=True)
983
    EgonPfHvStorageTimeseries.__table__.drop(bind=engine, checkfirst=True)
984
    EgonPfHvStore.__table__.drop(bind=engine, checkfirst=True)
985
    EgonPfHvStoreTimeseries.__table__.drop(bind=engine, checkfirst=True)
986
    EgonPfHvTempResolution.__table__.drop(bind=engine, checkfirst=True)
987
    EgonPfHvTransformer.__table__.drop(bind=engine, checkfirst=True)
988
    EgonPfHvTransformerTimeseries.__table__.drop(bind=engine, checkfirst=True)
989
    EgonPfHvBusmap.__table__.drop(bind=engine, checkfirst=True)
990
    # Create new tables
991
    EgonPfHvBus.__table__.create(bind=engine, checkfirst=True)
992
    EgonPfHvBusTimeseries.__table__.create(bind=engine, checkfirst=True)
993
    EgonPfHvGenerator.__table__.create(bind=engine, checkfirst=True)
994
    EgonPfHvGeneratorTimeseries.__table__.create(bind=engine, checkfirst=True)
995
    EgonPfHvLine.__table__.create(bind=engine, checkfirst=True)
996
    EgonPfHvLineTimeseries.__table__.create(bind=engine, checkfirst=True)
997
    EgonPfHvLink.__table__.create(bind=engine, checkfirst=True)
998
    EgonPfHvLinkTimeseries.__table__.create(bind=engine, checkfirst=True)
999
    EgonPfHvLoad.__table__.create(bind=engine, checkfirst=True)
1000
    EgonPfHvLoadTimeseries.__table__.create(bind=engine, checkfirst=True)
1001
    EgonPfHvCarrier.__table__.create(bind=engine, checkfirst=True)
1002
    EgonPfHvStorage.__table__.create(bind=engine, checkfirst=True)
1003
    EgonPfHvStorageTimeseries.__table__.create(bind=engine, checkfirst=True)
1004
    EgonPfHvStore.__table__.create(bind=engine, checkfirst=True)
1005
    EgonPfHvStoreTimeseries.__table__.create(bind=engine, checkfirst=True)
1006
    EgonPfHvTempResolution.__table__.create(bind=engine, checkfirst=True)
1007
    EgonPfHvTransformer.__table__.create(bind=engine, checkfirst=True)
1008
    EgonPfHvTransformerTimeseries.__table__.create(
1009
        bind=engine, checkfirst=True
1010
    )
1011
    EgonPfHvBusmap.__table__.create(bind=engine, checkfirst=True)
1012
1013
1014
def create_etrago_id_sequences():
1015
    """
1016
    Forcefully recreate all required PostgreSQL sequences for etrago components.
1017
    Drops existing sequences and creates them fresh, starting from 1.
1018
1019
    This ensures that no stale or misaligned sequences remain from earlier states.
1020
1021
    Notes
1022
    -----
1023
    - All sequences are named grid.etrago_{component}_id_seq
1024
    - Existing sequences will be dropped with CASCADE
1025
    - New sequences will start from 1 (default PostgreSQL behavior)
1026
    """
1027
    components = [
1028
        "bus",
1029
        "line",
1030
        "transformer",
1031
        "load",
1032
        "storage",
1033
        "generator",
1034
        "link",
1035
        "store",
1036
    ]
1037
1038
    for component in components:
1039
        sequence_name = f"grid.etrago_{component}_id_seq"
1040
1041
        drop_query = f"DROP SEQUENCE IF EXISTS {sequence_name} CASCADE;"
1042
        create_query = f"CREATE SEQUENCE {sequence_name};"
1043
1044
        print(f"Recreating sequence: {sequence_name}")
1045
        db.execute_sql(drop_query)
1046
        db.execute_sql(create_query)
1047
1048
def temp_resolution():
1049
    """Insert temporal resolution for etrago
1050
1051
    Returns
1052
    -------
1053
    None.
1054
1055
    """
1056
1057
    db.execute_sql(
1058
        """
1059
        INSERT INTO grid.egon_etrago_temp_resolution
1060
        (temp_id, timesteps, resolution, start_time)
1061
        SELECT 1, 8760, 'h', TIMESTAMP '2011-01-01 00:00:00';
1062
        """
1063
    )
1064
1065
1066
def insert_carriers():
1067
    """Insert list of carriers into eTraGo table
1068
1069
    Returns
1070
    -------
1071
    None.
1072
1073
    """
1074
    # Delete existing entries
1075
    db.execute_sql(
1076
        """
1077
        DELETE FROM grid.egon_etrago_carrier
1078
        """
1079
    )
1080
1081
    # List carrier names from all components
1082
    df = pd.DataFrame(
1083
        data={
1084
            "name": [
1085
                "biogas",
1086
                "biogas_feedin",
1087
                "biogas_to_gas",
1088
                "biomass",
1089
                "pv",
1090
                "wind_offshore",
1091
                "wind_onshore",
1092
                "central_heat_pump",
1093
                "central_resistive_heater",
1094
                "CH4",
1095
                "CH4_for_industry",
1096
                "CH4_system_boundary",
1097
                "CH4_to_H2",
1098
                "dsm",
1099
                "H2",
1100
                "H2_feedin",
1101
                "H2_for_industry",
1102
                "H2_gridextension",
1103
                "H2_hgv_load",
1104
                "H2_overground",
1105
                "H2_retrofit",
1106
                "H2_saltcavern",
1107
                "H2_system_boundary",
1108
                "H2_to_CH4",
1109
                "H2_to_power",
1110
                "H2_underground",
1111
                "rural_heat_pump",
1112
                "industrial_biomass_CHP",
1113
                "industrial_gas_CHP",
1114
                "central_biomass_CHP_heat",
1115
                "central_biomass_CHP",
1116
                "central_gas_CHP",
1117
                "central_gas_CHP_heat",
1118
                "power_to_H2",
1119
                "rural_gas_boiler",
1120
                "central_gas_boiler",
1121
                "solar_thermal_collector",
1122
                "geo_thermal",
1123
                "AC",
1124
                "central_heat",
1125
                "rural_heat",
1126
                "natural_gas_feedin",
1127
                "pumped_hydro",
1128
                "battery",
1129
                "OCGT",
1130
            ]
1131
        }
1132
    )
1133
1134
    # Insert data into database
1135
    df.to_sql(
1136
        "egon_etrago_carrier",
1137
        schema="grid",
1138
        con=db.engine(),
1139
        if_exists="append",
1140
        index=False,
1141
    )
1142
1143
1144
def check_carriers():
1145
    """Check if any eTraGo table has carriers not included in the carrier table.
1146
1147
    Raises
1148
    ------
1149
    ValueError if carriers that are not defined in the carriers table are
1150
    used in any eTraGo table.
1151
    """
1152
    carriers = db.select_dataframe(
1153
        f"""
1154
        SELECT name FROM grid.egon_etrago_carrier
1155
        """
1156
    )
1157
    unknown_carriers = {}
1158
    tables = ["bus", "store", "storage", "link", "line", "generator", "load"]
1159
1160
    for table in tables:
1161
        # Delete existing entries
1162
        data = db.select_dataframe(
1163
            f"""
1164
            SELECT carrier FROM grid.egon_etrago_{table}
1165
            """
1166
        )
1167
        unknown_carriers[table] = data[~data["carrier"].isin(carriers)][
1168
            "carrier"
1169
        ].unique()
1170
1171
    if len(unknown_carriers) > 0:
1172
        msg = (
1173
            "The eTraGo tables contain carriers, that are not included in the "
1174
            "carrier table:\n"
1175
        )
1176
        for table, carriers in unknown_carriers.items():
1177
            carriers = [str(c) for c in carriers]
1178
            if len(carriers) > 0:
1179
                msg += table + ": '" + "', '".join(carriers) + "'\n"
1180
1181
        raise ValueError(msg)
1182
1183
1184
def link_geom_from_buses(df, scn_name):
1185
    """Add LineString geometry accoring to geometry of buses to links
1186
1187
    Parameters
1188
    ----------
1189
    df : pandas.DataFrame
1190
        List of eTraGo links with bus0 and bus1 but without topology
1191
    scn_name : str
1192
        Scenario name
1193
1194
    Returns
1195
    -------
1196
    gdf : geopandas.GeoDataFrame
1197
        List of eTraGo links with bus0 and bus1 but with topology
1198
1199
    """
1200
1201
    geom_buses = db.select_geodataframe(
1202
        f"""
1203
        SELECT bus_id, geom
1204
        FROM grid.egon_etrago_bus
1205
        WHERE scn_name = '{scn_name}'
1206
        """,
1207
        index_col="bus_id",
1208
        epsg=4326,
1209
    )
1210
1211
    # Create geometry columns for bus0 and bus1
1212
    df["geom_0"] = geom_buses.geom[df.bus0.values].values
1213
    df["geom_1"] = geom_buses.geom[df.bus1.values].values
1214
1215
    geometry = df.apply(
1216
        lambda x: LineString([x["geom_0"], x["geom_1"]]), axis=1
1217
    )
1218
    df = df.drop(["geom_0", "geom_1"], axis=1)
1219
1220
    gdf = gpd.GeoDataFrame(df, geometry=geometry, crs=4326).rename_geometry(
1221
        "topo"
1222
    )
1223
1224
    return gdf
1225