Passed
Pull Request — dev (#870)
by
unknown
04:33 queued 03:08
created

data.datasets.heat_demand_timeseries   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 955
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 33
eloc 341
dl 0
loc 955
rs 9.76
c 0
b 0
f 0

9 Functions

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