Passed
Pull Request — dev (#905)
by
unknown
01:29
created

data.datasets.heat_demand_timeseries   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 997
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 35
eloc 359
dl 0
loc 997
rs 9.6
c 0
b 0
f 0

10 Functions

Rating   Name   Duplication   Size   Complexity  
A store_national_profiles() 0 89 2
A create_individual_heat_per_mv_grid() 0 73 1
B district_heating() 0 67 4
A create_district_heating_profile() 0 96 1
C create_individual_heating_profile_python_like() 0 146 7
A create_timeseries_for_building() 0 19 1
A create_individual_heating_peak_loads() 0 108 3
B individual_heating_per_mv_grid() 0 74 5
C create_district_heating_profile_python_like() 0 165 9
A calulate_peak_load() 0 22 1

1 Method

Rating   Name   Duplication   Size   Complexity  
A HeatTimeSeries.__init__() 0 14 1
1
from datetime import datetime
2
import os
3
4
from pathlib import Path
5
from sqlalchemy import ARRAY, Column, Float, Integer, String, Text
6
from sqlalchemy.ext.declarative import declarative_base
7
import geopandas as gpd
8
import numpy as np
9
import pandas as pd
10
11
from egon.data import db
12
import egon.data.datasets.era5 as era
13
14
try:
15
    from disaggregator import temporal
16
except ImportError as e:
17
    pass
18
19
from math import ceil
20
21
from egon.data.datasets import Dataset
22
import egon
23
24
from egon.data.datasets.heat_demand_timeseries.idp_pool import create, select
25
from egon.data.datasets.heat_demand_timeseries.service_sector import (
26
    CTS_demand_scale,
27
)
28
from egon.data.datasets.heat_demand_timeseries.daily import (
29
    map_climate_zones_to_zensus,
30
    daily_demand_shares_per_climate_zone,
31
)
32
33
34
Base = declarative_base()
35
36
37
class EgonTimeseriesDistrictHeating(Base):
38
    __tablename__ = "egon_timeseries_district_heating"
39
    __table_args__ = {"schema": "demand"}
40
    area_id = Column(Integer, primary_key=True)
41
    scenario = Column(Text, primary_key=True)
42
    dist_aggregated_mw = Column(ARRAY(Float(53)))
43
44
45
class EgonEtragoTimeseriesIndividualHeating(Base):
46
    __tablename__ = "egon_etrago_timeseries_individual_heating"
47
    __table_args__ = {"schema": "demand"}
48
    bus_id = Column(Integer, primary_key=True)
49
    scenario = Column(Text, primary_key=True)
50
    dist_aggregated_mw = Column(ARRAY(Float(53)))
51
52
53
class EgonIndividualHeatingPeakLoads(Base):
54
    __tablename__ = "egon_individual_heating_peak_loads"
55
    __table_args__ = {"schema": "demand"}
56
    building_id = Column(Integer, primary_key=True)
57
    scenario = Column(Text, primary_key=True)
58
    w_th = Column(Float(53))
59
60
61
def create_timeseries_for_building(building_id, scenario):
62
    """Generates final heat demand timeseries for a specific building
63
64
    Parameters
65
    ----------
66
    building_id : int
67
        Index of the selected building
68
    scenario : str
69
        Name of the selected scenario.
70
71
    Returns
72
    -------
73
    pandas.DataFrame
74
        Hourly heat demand timeseries in MW for the selected building
75
76
    """
77
78
    return db.select_dataframe(
79
        f"""
80
        SELECT building_demand * UNNEST(idp) as demand 
81
        FROM 
82
        (
83
        SELECT demand.demand / building.count * daily_demand.daily_demand_share as building_demand, daily_demand.day_of_year
84
        FROM 
85
        
86
        (SELECT demand FROM 
87
        demand.egon_peta_heat
88
        WHERE scenario = '{scenario}'
89
        AND sector = 'residential'
90
        AND zensus_population_id IN(
91
        SELECT zensus_population_id FROM 
92
        demand.heat_timeseries_selected_profiles
93
        WHERE building_id  = {building_id})) as demand,
94
        
95
        (SELECT COUNT(building_id)
96
        FROM demand.heat_timeseries_selected_profiles
97
        WHERE zensus_population_id IN(
98
        SELECT zensus_population_id FROM 
99
        demand.heat_timeseries_selected_profiles
100
        WHERE building_id  = {building_id})) as building,
101
        
102
        (SELECT daily_demand_share, day_of_year FROM 
103
        demand.egon_daily_heat_demand_per_climate_zone 
104
        WHERE climate_zone = (
105
            SELECT climate_zone FROM boundaries.egon_map_zensus_climate_zones
106
            WHERE zensus_population_id = 
107
            (SELECT zensus_population_id FROM demand.heat_timeseries_selected_profiles
108
             WHERE building_id = {building_id}))) as daily_demand) as daily_demand
109
        
110
        JOIN (SELECT b.idp, ordinality as day
111
        FROM demand.heat_timeseries_selected_profiles a,
112
        UNNEST (a.selected_idp_profiles) WITH ORDINALITY as selected_idp        
113
        JOIN demand.heat_idp_pool b
114
        ON selected_idp = b.index        
115
        WHERE a.building_id = {building_id}) as demand_profile
116
        ON demand_profile.day = daily_demand.day_of_year
117
        """
118
    )
119
120
121
def create_district_heating_profile(scenario, area_id):
122
    """Create heat demand profile for district heating grid including demands of
123
    households and service sector.
124
125
    Parameters
126
    ----------
127
    scenario : str
128
        Name of the selected scenario.
129
    area_id : int
130
        Index of the selected district heating grid
131
132
    Returns
133
    -------
134
    df : pandas,DataFrame
135
        Hourly heat demand timeseries in MW for the selected district heating grid
136
137
    """
138
139
    start_time = datetime.now()
140
141
    df = db.select_dataframe(
142
        f"""
143
        
144
        SELECT SUM(building_demand_per_hour) as demand_profile, hour_of_year
145
        FROM 
146
        
147
        (
148
        SELECT demand.demand  * 
149
        c.daily_demand_share * hourly_demand as building_demand_per_hour,
150
        ordinality + 24* (c.day_of_year-1) as hour_of_year,
151
        demand_profile.building_id,
152
        c.day_of_year,
153
        ordinality
154
        
155
        FROM 
156
        
157
        (SELECT zensus_population_id, demand FROM 
158
        demand.egon_peta_heat
159
        WHERE scenario = '{scenario}'
160
        AND sector = 'residential'
161
        AND zensus_population_id IN(
162
        SELECT zensus_population_id FROM 
163
        demand.egon_map_zensus_district_heating_areas
164
        WHERE scenario = '{scenario}'
165
        AND area_id = {area_id}
166
        )) as demand
167
        
168
        JOIN boundaries.egon_map_zensus_climate_zones b 
169
        ON demand.zensus_population_id = b.zensus_population_id
170
        
171
        JOIN demand.egon_daily_heat_demand_per_climate_zone c
172
        ON c.climate_zone = b.climate_zone
173
        
174
        JOIN (SELECT e.idp, ordinality as day, zensus_population_id, building_id
175
        FROM demand.heat_timeseries_selected_profiles d,
176
        UNNEST (d.selected_idp_profiles) WITH ORDINALITY as selected_idp        
177
        JOIN demand.heat_idp_pool e
178
        ON selected_idp = e.index
179
        WHERE zensus_population_id IN (
180
        SELECT zensus_population_id FROM 
181
        demand.egon_map_zensus_district_heating_areas
182
        WHERE scenario = '{scenario}'
183
        AND area_id = {area_id}
184
        ))  demand_profile
185
        ON (demand_profile.day = c.day_of_year AND 
186
            demand_profile.zensus_population_id = b.zensus_population_id)
187
        
188
        JOIN (SELECT COUNT(building_id), zensus_population_id
189
        FROM demand.heat_timeseries_selected_profiles
190
        WHERE zensus_population_id IN(
191
        SELECT zensus_population_id FROM 
192
        demand.heat_timeseries_selected_profiles
193
       WHERE zensus_population_id IN (
194
       SELECT zensus_population_id FROM 
195
       demand.egon_map_zensus_district_heating_areas
196
       WHERE scenario = '{scenario}'
197
       AND area_id = {area_id}
198
       ))
199
		GROUP BY zensus_population_id) building
200
        ON building.zensus_population_id = b.zensus_population_id,
201
        
202
        UNNEST(demand_profile.idp) WITH ORDINALITY as hourly_demand
203
        )   result
204
        
205
        
206
        GROUP BY hour_of_year
207
208
        """
209
    )
210
211
    print(
212
        f"Time to create time series for district heating grid {scenario} {area_id}:"
213
    )
214
    print(datetime.now() - start_time)
215
216
    return df
217
218
219
def create_district_heating_profile_python_like(scenario="eGon2035"):
220
    """Creates profiles for all district heating grids in one scenario.
221
    Similar to create_district_heating_profile but faster and needs more RAM.
222
    The results are directly written into the database.
223
224
    Parameters
225
    ----------
226
    scenario : str
227
        Name of the selected scenario.
228
229
    Returns
230
    -------
231
    None.
232
233
    """
234
235
    start_time = datetime.now()
236
237
    idp_df = db.select_dataframe(
238
        """
239
        SELECT index, idp FROM demand.heat_idp_pool
240
        """,
241
        index_col="index",
242
    )
243
244
    district_heating_grids = db.select_dataframe(
245
        f"""
246
        SELECT area_id 
247
        FROM demand.egon_district_heating_areas
248
        WHERE scenario = '{scenario}'
249
        """
250
    )
251
252
    annual_demand = db.select_dataframe(
253
        f"""
254
        SELECT a.zensus_population_id, demand/c.count as per_building , area_id FROM 
255
        demand.egon_peta_heat a
256
        INNER JOIN (
257
            SELECT * FROM demand.egon_map_zensus_district_heating_areas
258
            WHERE scenario = '{scenario}'
259
        ) b ON a.zensus_population_id = b.zensus_population_id
260
        
261
        JOIN (SELECT COUNT(building_id), zensus_population_id
262
        FROM demand.heat_timeseries_selected_profiles
263
        WHERE zensus_population_id IN(
264
        SELECT zensus_population_id FROM 
265
        demand.heat_timeseries_selected_profiles
266
        WHERE zensus_population_id IN (
267
        SELECT zensus_population_id FROM 
268
        boundaries.egon_map_zensus_grid_districts
269
       )) 
270
        GROUP BY zensus_population_id)c
271
        ON a.zensus_population_id = c.zensus_population_id
272
        
273
        WHERE a.scenario = '{scenario}'
274
        AND a.sector = 'residential'
275
        
276
        """,
277
        index_col="zensus_population_id",
278
    )
279
280
    daily_demand_shares = db.select_dataframe(
281
        """
282
        SELECT climate_zone, day_of_year as day, daily_demand_share FROM 
283
        demand.egon_daily_heat_demand_per_climate_zone        
284
        """
285
    )
286
287
    selected_profiles = db.select_dataframe(
288
        f"""
289
        SELECT a.zensus_population_id, building_id, c.climate_zone, 
290
        selected_idp, ordinality as day, b.area_id
291
        FROM demand.heat_timeseries_selected_profiles a
292
        INNER JOIN boundaries.egon_map_zensus_climate_zones c
293
        ON a.zensus_population_id = c.zensus_population_id
294
        INNER JOIN (
295
            SELECT * FROM demand.egon_map_zensus_district_heating_areas
296
            WHERE scenario = '{scenario}'
297
        ) b ON a.zensus_population_id = b.zensus_population_id        ,
298
        
299
        UNNEST (selected_idp_profiles) WITH ORDINALITY as selected_idp 
300
301
        """
302
    )
303
304
    df = pd.merge(
305
        selected_profiles, daily_demand_shares, on=["day", "climate_zone"]
306
    )
307
308
    CTS_demand_dist, CTS_demand_grid, CTS_demand_zensus = CTS_demand_scale(
309
        aggregation_level="district"
310
    )
311
312
    # TODO: use session_scope!
313
    from sqlalchemy.orm import sessionmaker
314
315
    session = sessionmaker(bind=db.engine())()
316
    engine = db.engine()
317
    EgonTimeseriesDistrictHeating.__table__.drop(bind=engine, checkfirst=True)
318
    EgonTimeseriesDistrictHeating.__table__.create(
319
        bind=engine, checkfirst=True
320
    )
321
    print(
322
        f"Time to create overhead for time series for district heating scenario {scenario}"
323
    )
324
    print(datetime.now() - start_time)
325
326
    start_time = datetime.now()
327
    for area in district_heating_grids.area_id.unique():
328
329
        if area in df.area_id.values:
330
            slice_df = pd.merge(
331
                df[df.area_id == area],
332
                idp_df,
333
                left_on="selected_idp",
334
                right_on="index",
335
            )
336
337
            for hour in range(24):
338
                slice_df[hour] = (
339
                    slice_df.idp.str[hour]
340
                    .mul(slice_df.daily_demand_share)
341
                    .mul(
342
                        annual_demand.loc[
343
                            slice_df.zensus_population_id.values,
344
                            "per_building",
345
                        ].values
346
                    )
347
                )
348
349
            hh = np.concatenate(
350
                slice_df.groupby("day").sum()[range(24)].values
351
            ).ravel()
352
353
        cts = CTS_demand_dist[
354
            (CTS_demand_dist.scenario == scenario)
355
            & (CTS_demand_dist.index == area)
356
        ].drop("scenario", axis="columns")
357
358
        if (area in df.area_id.values) and not cts.empty:
359
            entry = EgonTimeseriesDistrictHeating(
360
                area_id=int(area),
361
                scenario=scenario,
362
                dist_aggregated_mw=(hh + cts.values[0]).tolist(),
0 ignored issues
show
introduced by
The variable hh does not seem to be defined for all execution paths.
Loading history...
363
            )
364
        elif (area in df.area_id.values) and cts.empty:
365
            entry = EgonTimeseriesDistrictHeating(
366
                area_id=int(area),
367
                scenario=scenario,
368
                dist_aggregated_mw=(hh).tolist(),
369
            )
370
        elif not cts.empty:
371
            entry = EgonTimeseriesDistrictHeating(
372
                area_id=int(area),
373
                scenario=scenario,
374
                dist_aggregated_mw=(cts.values[0]).tolist(),
375
            )
376
377
        session.add(entry)
0 ignored issues
show
introduced by
The variable entry does not seem to be defined for all execution paths.
Loading history...
378
    session.commit()
379
380
    print(
381
        f"Time to create time series for district heating scenario {scenario}"
382
    )
383
    print(datetime.now() - start_time)
384
385
386
def create_individual_heat_per_mv_grid(scenario="eGon2035", mv_grid_id=1564):
387
    start_time = datetime.now()
388
    df = db.select_dataframe(
389
        f"""
390
        
391
        SELECT SUM(building_demand_per_hour) as demand_profile, hour_of_year
392
        FROM 
393
        
394
        (
395
        SELECT demand.demand  * 
396
        c.daily_demand_share * hourly_demand as building_demand_per_hour,
397
        ordinality + 24* (c.day_of_year-1) as hour_of_year,
398
        demand_profile.building_id,
399
        c.day_of_year,
400
        ordinality
401
        
402
        FROM 
403
        
404
        (SELECT zensus_population_id, demand FROM 
405
        demand.egon_peta_heat
406
        WHERE scenario = '{scenario}'
407
        AND sector = 'residential'
408
        AND zensus_population_id IN (
409
        SELECT zensus_population_id FROM 
410
        boundaries.egon_map_zensus_grid_districts
411
        WHERE bus_id = {mv_grid_id}
412
        )) as demand
413
        
414
        JOIN boundaries.egon_map_zensus_climate_zones b 
415
        ON demand.zensus_population_id = b.zensus_population_id
416
        
417
        JOIN demand.egon_daily_heat_demand_per_climate_zone c
418
        ON c.climate_zone = b.climate_zone
419
        
420
        JOIN (SELECT e.idp, ordinality as day, zensus_population_id, building_id
421
        FROM demand.heat_timeseries_selected_profiles d,
422
        UNNEST (d.selected_idp_profiles) WITH ORDINALITY as selected_idp        
423
        JOIN demand.heat_idp_pool e
424
        ON selected_idp = e.index
425
        WHERE zensus_population_id IN (
426
        SELECT zensus_population_id FROM 
427
        boundaries.egon_map_zensus_grid_districts
428
        WHERE bus_id = {mv_grid_id}
429
        ))  demand_profile
430
        ON (demand_profile.day = c.day_of_year AND 
431
            demand_profile.zensus_population_id = b.zensus_population_id)
432
        
433
        JOIN (SELECT COUNT(building_id), zensus_population_id
434
        FROM demand.heat_timeseries_selected_profiles
435
        WHERE zensus_population_id IN(
436
        SELECT zensus_population_id FROM 
437
        demand.heat_timeseries_selected_profiles
438
        WHERE zensus_population_id IN (
439
        SELECT zensus_population_id FROM 
440
        boundaries.egon_map_zensus_grid_districts
441
        WHERE bus_id = {mv_grid_id}
442
       ))
443
		GROUP BY zensus_population_id) building
444
        ON building.zensus_population_id = b.zensus_population_id,
445
        
446
        UNNEST(demand_profile.idp) WITH ORDINALITY as hourly_demand
447
        )   result
448
        
449
        
450
        GROUP BY hour_of_year
451
452
        """
453
    )
454
455
    print(f"Time to create time series for mv grid {scenario} {mv_grid_id}:")
456
    print(datetime.now() - start_time)
457
458
    return df
459
460
461
def calulate_peak_load(df, scenario):
462
463
    # peat load in W_th
464
    data = (
465
        df.groupby("building_id")
466
        .max()[range(24)]
467
        .max(axis=1)
468
        .mul(1000000)
469
        .astype(int)
470
        .reset_index()
471
    )
472
473
    data["scenario"] = scenario
474
475
    data.rename({0: "w_th"}, axis="columns", inplace=True)
476
477
    data.to_sql(
478
        EgonIndividualHeatingPeakLoads.__table__.name,
479
        schema=EgonIndividualHeatingPeakLoads.__table__.schema,
480
        con=db.engine(),
481
        if_exists="append",
482
        index=False,
483
    )
484
485
486
def create_individual_heating_peak_loads(scenario="eGon2035"):
487
488
    engine = db.engine()
489
490
    EgonIndividualHeatingPeakLoads.__table__.drop(bind=engine, checkfirst=True)
491
492
    EgonIndividualHeatingPeakLoads.__table__.create(
493
        bind=engine, checkfirst=True
494
    )
495
496
    start_time = datetime.now()
497
498
    idp_df = db.select_dataframe(
499
        """
500
        SELECT index, idp FROM demand.heat_idp_pool
501
        """,
502
        index_col="index",
503
    )
504
505
    annual_demand = db.select_dataframe(
506
        f"""
507
        SELECT a.zensus_population_id, demand/c.count as per_building, bus_id
508
        FROM demand.egon_peta_heat a
509
510
        
511
        JOIN (SELECT COUNT(building_id), zensus_population_id
512
        FROM demand.heat_timeseries_selected_profiles
513
        WHERE zensus_population_id IN(
514
        SELECT zensus_population_id FROM 
515
        demand.heat_timeseries_selected_profiles
516
        WHERE zensus_population_id IN (
517
        SELECT zensus_population_id FROM 
518
        boundaries.egon_map_zensus_grid_districts
519
       )) 
520
        GROUP BY zensus_population_id)c
521
        ON a.zensus_population_id = c.zensus_population_id
522
        
523
        JOIN boundaries.egon_map_zensus_grid_districts d
524
        ON a.zensus_population_id = d.zensus_population_id
525
        
526
        WHERE a.scenario = '{scenario}'
527
        AND a.sector = 'residential'
528
        AND a.zensus_population_id NOT IN (
529
            SELECT zensus_population_id FROM demand.egon_map_zensus_district_heating_areas
530
            WHERE scenario = '{scenario}'
531
        )
532
        
533
        """,
534
        index_col="zensus_population_id",
535
    )
536
537
    daily_demand_shares = db.select_dataframe(
538
        """
539
        SELECT climate_zone, day_of_year as day, daily_demand_share FROM 
540
        demand.egon_daily_heat_demand_per_climate_zone        
541
        """
542
    )
543
544
    start_time = datetime.now()
545
    for grid in annual_demand.bus_id.unique():
546
547
        selected_profiles = db.select_dataframe(
548
            f"""
549
            SELECT a.zensus_population_id, building_id, c.climate_zone, 
550
            selected_idp, ordinality as day
551
            FROM demand.heat_timeseries_selected_profiles a
552
            INNER JOIN boundaries.egon_map_zensus_climate_zones c
553
            ON a.zensus_population_id = c.zensus_population_id
554
            ,
555
            
556
            UNNEST (selected_idp_profiles) WITH ORDINALITY as selected_idp 
557
            
558
            WHERE a.zensus_population_id NOT IN (
559
                SELECT zensus_population_id FROM demand.egon_map_zensus_district_heating_areas
560
                WHERE scenario = '{scenario}'
561
            )
562
            AND a.zensus_population_id IN (
563
                SELECT zensus_population_id
564
                FROM boundaries.egon_map_zensus_grid_districts
565
                WHERE bus_id = '{grid}'
566
            )
567
    
568
            """
569
        )
570
571
        df = pd.merge(
572
            selected_profiles, daily_demand_shares, on=["day", "climate_zone"]
573
        )
574
575
        slice_df = pd.merge(
576
            df, idp_df, left_on="selected_idp", right_on="index"
577
        )
578
579
        for hour in range(24):
580
            slice_df[hour] = (
581
                slice_df.idp.str[hour]
582
                .mul(slice_df.daily_demand_share)
583
                .mul(
584
                    annual_demand.loc[
585
                        slice_df.zensus_population_id.values, "per_building"
586
                    ].values
587
                )
588
            )
589
590
        calulate_peak_load(slice_df, scenario)
591
592
    print(f"Time to create peak loads per building for {scenario}")
593
    print(datetime.now() - start_time)
594
595
596
def create_individual_heating_profile_python_like(scenario="eGon2035"):
597
598
    start_time = datetime.now()
599
600
    idp_df = db.select_dataframe(
601
        f"""
602
        SELECT index, idp FROM demand.heat_idp_pool
603
        """,
604
        index_col="index",
605
    )
606
607
    annual_demand = db.select_dataframe(
608
        f"""
609
        SELECT a.zensus_population_id, demand/c.count as per_building, bus_id
610
        FROM demand.egon_peta_heat a
611
612
        
613
        JOIN (SELECT COUNT(building_id), zensus_population_id
614
        FROM demand.heat_timeseries_selected_profiles
615
        WHERE zensus_population_id IN(
616
        SELECT zensus_population_id FROM 
617
        demand.heat_timeseries_selected_profiles
618
        WHERE zensus_population_id IN (
619
        SELECT zensus_population_id FROM 
620
        boundaries.egon_map_zensus_grid_districts
621
       )) 
622
        GROUP BY zensus_population_id)c
623
        ON a.zensus_population_id = c.zensus_population_id
624
        
625
        JOIN boundaries.egon_map_zensus_grid_districts d
626
        ON a.zensus_population_id = d.zensus_population_id
627
        
628
        WHERE a.scenario = '{scenario}'
629
        AND a.sector = 'residential'
630
        AND a.zensus_population_id NOT IN (
631
            SELECT zensus_population_id FROM demand.egon_map_zensus_district_heating_areas
632
            WHERE scenario = '{scenario}'
633
        )
634
        
635
        """,
636
        index_col="zensus_population_id",
637
    )
638
639
    daily_demand_shares = db.select_dataframe(
640
        f"""
641
        SELECT climate_zone, day_of_year as day, daily_demand_share FROM 
642
        demand.egon_daily_heat_demand_per_climate_zone        
643
        """
644
    )
645
646
    CTS_demand_dist, CTS_demand_grid, CTS_demand_zensus = CTS_demand_scale(
647
        aggregation_level="district"
648
    )
649
650
    # TODO: use session_scope!
651
    from sqlalchemy.orm import sessionmaker
652
653
    session = sessionmaker(bind=db.engine())()
654
655
    print(
656
        f"Time to create overhead for time series for district heating scenario {scenario}"
657
    )
658
    print(datetime.now() - start_time)
659
660
    start_time = datetime.now()
661
    for grid in annual_demand.bus_id.unique():
662
663
        selected_profiles = db.select_dataframe(
664
            f"""
665
            SELECT a.zensus_population_id, building_id, c.climate_zone, 
666
            selected_idp, ordinality as day
667
            FROM demand.heat_timeseries_selected_profiles a
668
            INNER JOIN boundaries.egon_map_zensus_climate_zones c
669
            ON a.zensus_population_id = c.zensus_population_id
670
            ,
671
            
672
            UNNEST (selected_idp_profiles) WITH ORDINALITY as selected_idp 
673
            
674
            WHERE a.zensus_population_id NOT IN (
675
                SELECT zensus_population_id FROM demand.egon_map_zensus_district_heating_areas
676
                WHERE scenario = '{scenario}'
677
            )
678
            AND a.zensus_population_id IN (
679
                SELECT zensus_population_id
680
                FROM boundaries.egon_map_zensus_grid_districts
681
                WHERE bus_id = '{grid}'
682
            )
683
    
684
            """
685
        )
686
687
        df = pd.merge(
688
            selected_profiles, daily_demand_shares, on=["day", "climate_zone"]
689
        )
690
691
        slice_df = pd.merge(
692
            df, idp_df, left_on="selected_idp", right_on="index"
693
        )
694
695
        for hour in range(24):
696
            slice_df[hour] = (
697
                slice_df.idp.str[hour]
698
                .mul(slice_df.daily_demand_share)
699
                .mul(
700
                    annual_demand.loc[
701
                        slice_df.zensus_population_id.values, "per_building"
702
                    ].values
703
                )
704
            )
705
706
        cts = CTS_demand_grid[
707
            (CTS_demand_grid.scenario == scenario)
708
            & (CTS_demand_grid.index == grid)
709
        ].drop("scenario", axis="columns")
710
711
        hh = np.concatenate(
712
            slice_df.groupby("day").sum()[range(24)].values
713
        ).ravel()
714
715
        if not (slice_df[hour].empty or cts.empty):
0 ignored issues
show
introduced by
The variable hour does not seem to be defined for all execution paths.
Loading history...
716
            entry = EgonEtragoTimeseriesIndividualHeating(
717
                bus_id=int(grid),
718
                scenario=scenario,
719
                dist_aggregated_mw=(hh + cts.values[0]).tolist(),
720
            )
721
        elif not slice_df[hour].empty:
722
            entry = EgonEtragoTimeseriesIndividualHeating(
723
                bus_id=int(grid),
724
                scenario=scenario,
725
                dist_aggregated_mw=(hh).tolist(),
726
            )
727
        elif not cts.empty:
728
            entry = EgonEtragoTimeseriesIndividualHeating(
729
                bus_id=int(grid),
730
                scenario=scenario,
731
                dist_aggregated_mw=(cts).tolist(),
732
            )
733
734
        session.add(entry)
0 ignored issues
show
introduced by
The variable entry does not seem to be defined for all execution paths.
Loading history...
735
736
    session.commit()
737
738
    print(
739
        f"Time to create time series for district heating scenario {scenario}"
740
    )
741
    print(datetime.now() - start_time)
742
743
744
def district_heating(method="python"):
745
746
    engine = db.engine()
747
    EgonTimeseriesDistrictHeating.__table__.drop(bind=engine, checkfirst=True)
748
    EgonTimeseriesDistrictHeating.__table__.create(
749
        bind=engine, checkfirst=True
750
    )
751
752
    if method == "python":
753
        create_district_heating_profile_python_like("eGon2035")
754
        create_district_heating_profile_python_like("eGon100RE")
755
756
    else:
757
758
        CTS_demand_dist, CTS_demand_grid, CTS_demand_zensus = CTS_demand_scale(
759
            aggregation_level="district"
760
        )
761
762
        ids = db.select_dataframe(
763
            """
764
            SELECT area_id, scenario
765
            FROM demand.egon_district_heating_areas
766
            """
767
        )
768
769
        df = pd.DataFrame(
770
            columns=["area_id", "scenario", "dist_aggregated_mw"]
771
        )
772
773
        for index, row in ids.iterrows():
774
            series = create_district_heating_profile(
775
                scenario=row.scenario, area_id=row.area_id
776
            )
777
778
            cts = (
779
                CTS_demand_dist[
780
                    (CTS_demand_dist.scenario == row.scenario)
781
                    & (CTS_demand_dist.index == row.area_id)
782
                ]
783
                .drop("scenario", axis="columns")
784
                .transpose()
785
            )
786
787
            if not cts.empty:
788
                data = (
789
                    cts[row.area_id] + series.demand_profile
790
                ).values.tolist()
791
            else:
792
                data = series.demand_profile.values.tolist()
793
794
            df = df.append(
795
                pd.Series(
796
                    data={
797
                        "area_id": row.area_id,
798
                        "scenario": row.scenario,
799
                        "dist_aggregated_mw": data,
800
                    },
801
                ),
802
                ignore_index=True,
803
            )
804
805
        df.to_sql(
806
            "egon_timeseries_district_heating",
807
            schema="demand",
808
            con=db.engine(),
809
            if_exists="append",
810
            index=False,
811
        )
812
813
814
def individual_heating_per_mv_grid(method="python"):
815
816
    if method == "python":
817
        engine = db.engine()
818
        EgonEtragoTimeseriesIndividualHeating.__table__.drop(
819
            bind=engine, checkfirst=True
820
        )
821
        EgonEtragoTimeseriesIndividualHeating.__table__.create(
822
            bind=engine, checkfirst=True
823
        )
824
825
        create_individual_heating_profile_python_like("eGon2035")
826
        create_individual_heating_profile_python_like("eGon100RE")
827
828
    else:
829
830
        engine = db.engine()
831
        EgonEtragoTimeseriesIndividualHeating.__table__.drop(
832
            bind=engine, checkfirst=True
833
        )
834
        EgonEtragoTimeseriesIndividualHeating.__table__.create(
835
            bind=engine, checkfirst=True
836
        )
837
838
        CTS_demand_dist, CTS_demand_grid, CTS_demand_zensus = CTS_demand_scale(
839
            aggregation_level="district"
840
        )
841
        df = pd.DataFrame(columns=["bus_id", "scenario", "dist_aggregated_mw"])
842
843
        ids = db.select_dataframe(
844
            """
845
            SELECT bus_id
846
            FROM grid.egon_mv_grid_district
847
            """
848
        )
849
850
        for index, row in ids.iterrows():
851
852
            for scenario in ["eGon2035", "eGon100RE"]:
853
                series = create_individual_heat_per_mv_grid(
854
                    scenario, row.bus_id
855
                )
856
                cts = (
857
                    CTS_demand_grid[
858
                        (CTS_demand_grid.scenario == scenario)
859
                        & (CTS_demand_grid.index == row.bus_id)
860
                    ]
861
                    .drop("scenario", axis="columns")
862
                    .transpose()
863
                )
864
                if not cts.empty:
865
                    data = (
866
                        cts[row.bus_id] + series.demand_profile
867
                    ).values.tolist()
868
                else:
869
                    data = series.demand_profile.values.tolist()
870
871
                df = df.append(
872
                    pd.Series(
873
                        data={
874
                            "bus_id": row.bus_id,
875
                            "scenario": scenario,
876
                            "dist_aggregated_mw": data,
877
                        },
878
                    ),
879
                    ignore_index=True,
880
                )
881
882
        df.to_sql(
883
            "egon_etrago_timeseries_individual_heating",
884
            schema="demand",
885
            con=db.engine(),
886
            if_exists="append",
887
            index=False,
888
        )
889
890
891
def store_national_profiles():
892
893
    scenario = "eGon100RE"
894
895
    df = db.select_dataframe(
896
        f"""
897
        
898
        SELECT SUM(building_demand_per_hour) as "residential rural"
899
        FROM 
900
        
901
        (
902
        SELECT demand.demand  * 
903
        c.daily_demand_share * hourly_demand as building_demand_per_hour,
904
        ordinality + 24* (c.day_of_year-1) as hour_of_year,
905
        demand_profile.building_id,
906
        c.day_of_year,
907
        ordinality
908
        
909
        FROM 
910
        
911
        (SELECT zensus_population_id, demand FROM 
912
        demand.egon_peta_heat
913
        WHERE scenario = '{scenario}'
914
        AND sector = 'residential'
915
       ) as demand
916
        
917
        JOIN boundaries.egon_map_zensus_climate_zones b 
918
        ON demand.zensus_population_id = b.zensus_population_id
919
        
920
        JOIN demand.egon_daily_heat_demand_per_climate_zone c
921
        ON c.climate_zone = b.climate_zone
922
        
923
        JOIN (SELECT e.idp, ordinality as day, zensus_population_id, building_id
924
        FROM demand.heat_timeseries_selected_profiles d,
925
        UNNEST (d.selected_idp_profiles) WITH ORDINALITY as selected_idp        
926
        JOIN demand.heat_idp_pool e
927
        ON selected_idp = e.index
928
        )  demand_profile
929
        ON (demand_profile.day = c.day_of_year AND 
930
            demand_profile.zensus_population_id = b.zensus_population_id)
931
        
932
        JOIN (SELECT COUNT(building_id), zensus_population_id
933
        FROM demand.heat_timeseries_selected_profiles
934
        WHERE zensus_population_id IN(
935
        SELECT zensus_population_id FROM 
936
        demand.heat_timeseries_selected_profiles
937
        )
938
		GROUP BY zensus_population_id) building
939
        ON building.zensus_population_id = b.zensus_population_id,
940
        
941
        UNNEST(demand_profile.idp) WITH ORDINALITY as hourly_demand
942
        )   result
943
        
944
        
945
        GROUP BY hour_of_year
946
947
        """
948
    )
949
950
    CTS_demand_dist, CTS_demand_grid, CTS_demand_zensus = CTS_demand_scale(
951
        aggregation_level="district"
952
    )
953
954
    df["service rural"] = (
955
        CTS_demand_dist.loc[CTS_demand_dist.scenario == scenario]
956
        .drop("scenario", axis=1)
957
        .sum()
958
    )
959
960
    df["urban central"] = db.select_dataframe(
961
        f"""
962
        SELECT sum(demand) as "urban central"
963
964
        FROM demand.egon_timeseries_district_heating, 
965
        UNNEST (dist_aggregated_mw) WITH ORDINALITY as demand
966
        
967
        WHERE scenario = '{scenario}'
968
        
969
        GROUP BY ordinality
970
        
971
        """
972
    )
973
974
    folder = Path(".") / "input-pypsa-eur-sec"
975
    # Create the folder, if it does not exists already
976
    if not os.path.exists(folder):
977
        os.mkdir(folder)
978
979
    df.to_csv(folder / f"heat_demand_timeseries_DE_{scenario}.csv")
980
981
982
class HeatTimeSeries(Dataset):
983
    def __init__(self, dependencies):
984
        super().__init__(
985
            name="HeatTimeSeries",
986
            version="0.0.7.dev",
987
            dependencies=dependencies,
988
            tasks=(
989
                {
990
                    map_climate_zones_to_zensus,
991
                    daily_demand_shares_per_climate_zone,
992
                    create,
993
                },
994
                select,
995
                district_heating,
996
                store_national_profiles,
997
            ),
998
        )
999