Passed
Pull Request — dev (#934)
by
unknown
02:06
created

data.datasets.sanity_checks.etrago_eGon2035_heat()   B

Complexity

Conditions 1

Size

Total Lines 222
Code Lines 86

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 86
dl 0
loc 222
rs 7.4581
c 0
b 0
f 0
cc 1
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
"""
2
This module does sanity checks for both the eGon2035 and the eGon100RE scenario
3
separately where a percentage error is given to showcase difference in output
4
and input values. Please note that there are missing input technologies in the
5
supply tables.
6
Authors: @ALonso, @dana, @nailend, @nesnoj, @khelfen
7
"""
8
from math import isclose
9
from pathlib import Path
10
11
from sqlalchemy import Numeric
12
from sqlalchemy.sql import and_, cast, func, or_
13
import matplotlib.pyplot as plt
14
import numpy as np
15
import pandas as pd
16
import seaborn as sns
17
18
from egon.data import config, db, logger
19
from egon.data.datasets import Dataset
20
from egon.data.datasets.electricity_demand_timeseries.cts_buildings import (
21
    EgonCtsElectricityDemandBuildingShare,
22
    EgonCtsHeatDemandBuildingShare,
23
)
24
from egon.data.datasets.emobility.motorized_individual_travel.db_classes import (
25
    EgonEvCountMunicipality,
26
    EgonEvCountMvGridDistrict,
27
    EgonEvCountRegistrationDistrict,
28
    EgonEvMvGridDistrict,
29
    EgonEvPool,
30
    EgonEvTrip,
31
)
32
from egon.data.datasets.emobility.motorized_individual_travel.helpers import (
33
    DATASET_CFG,
34
    read_simbev_metadata_file,
35
)
36
from egon.data.datasets.etrago_setup import (
37
    EgonPfHvLink,
38
    EgonPfHvLinkTimeseries,
39
    EgonPfHvLoad,
40
    EgonPfHvLoadTimeseries,
41
    EgonPfHvStore,
42
    EgonPfHvStoreTimeseries,
43
)
44
from egon.data.datasets.power_plants.pv_rooftop_buildings import (
45
    PV_CAP_PER_SQ_M,
46
    ROOF_FACTOR,
47
    SCENARIOS,
48
    load_building_data,
49
    scenario_data,
50
)
51
from egon.data.datasets.scenario_parameters import get_sector_parameters
52
import egon.data
53
54
TESTMODE_OFF = (
55
    config.settings()["egon-data"]["--dataset-boundary"] == "Everything"
56
)
57
58
59
class SanityChecks(Dataset):
60
    def __init__(self, dependencies):
61
        super().__init__(
62
            name="SanityChecks",
63
            version="0.0.5",
64
            dependencies=dependencies,
65
            tasks={
66
                etrago_eGon2035_electricity,
67
                etrago_eGon2035_heat,
68
                residential_electricity_annual_sum,
69
                residential_electricity_hh_refinement,
70
                cts_electricity_demand_share,
71
                cts_heat_demand_share,
72
                sanitycheck_emobility_mit,
73
                sanitycheck_pv_rooftop_buildings,
74
            },
75
        )
76
77
78
def etrago_eGon2035_electricity():
79
    """Execute basic sanity checks.
80
81
    Returns print statements as sanity checks for the electricity sector in
82
    the eGon2035 scenario.
83
84
    Parameters
85
    ----------
86
    None
87
88
    Returns
89
    -------
90
    None
91
    """
92
93
    scn = "eGon2035"
94
95
    # Section to check generator capacities
96
    logger.info(f"Sanity checks for scenario {scn}")
97
    logger.info(
98
        "For German electricity generators the following deviations between "
99
        "the inputs and outputs can be observed:"
100
    )
101
102
    carriers_electricity = [
103
        "others",
104
        "reservoir",
105
        "run_of_river",
106
        "oil",
107
        "wind_onshore",
108
        "wind_offshore",
109
        "solar",
110
        "solar_rooftop",
111
        "biomass",
112
    ]
113
114
    for carrier in carriers_electricity:
115
116
        if carrier == "biomass":
117
            sum_output = db.select_dataframe(
118
                """SELECT scn_name, SUM(p_nom::numeric) as output_capacity_mw
119
                    FROM grid.egon_etrago_generator
120
                    WHERE bus IN (
121
                        SELECT bus_id FROM grid.egon_etrago_bus
122
                        WHERE scn_name = 'eGon2035'
123
                        AND country = 'DE')
124
                    AND carrier IN ('biomass', 'industrial_biomass_CHP',
125
                    'central_biomass_CHP')
126
                    GROUP BY (scn_name);
127
                """,
128
                warning=False,
129
            )
130
131
        else:
132
            sum_output = db.select_dataframe(
133
                f"""SELECT scn_name,
134
                 SUM(p_nom::numeric) as output_capacity_mw
135
                         FROM grid.egon_etrago_generator
136
                         WHERE scn_name = '{scn}'
137
                         AND carrier IN ('{carrier}')
138
                         AND bus IN
139
                             (SELECT bus_id
140
                               FROM grid.egon_etrago_bus
141
                               WHERE scn_name = 'eGon2035'
142
                               AND country = 'DE')
143
                         GROUP BY (scn_name);
144
                    """,
145
                warning=False,
146
            )
147
148
        sum_input = db.select_dataframe(
149
            f"""SELECT carrier, SUM(capacity::numeric) as input_capacity_mw
150
                     FROM supply.egon_scenario_capacities
151
                     WHERE carrier= '{carrier}'
152
                     AND scenario_name ='{scn}'
153
                     GROUP BY (carrier);
154
                """,
155
            warning=False,
156
        )
157
158 View Code Duplication
        if (
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
159
            sum_output.output_capacity_mw.sum() == 0
160
            and sum_input.input_capacity_mw.sum() == 0
161
        ):
162
            logger.info(
163
                f"No capacity for carrier '{carrier}' needed to be"
164
                f" distributed. Everything is fine"
165
            )
166
167
        elif (
168
            sum_input.input_capacity_mw.sum() > 0
169
            and sum_output.output_capacity_mw.sum() == 0
170
        ):
171
            logger.info(
172
                f"Error: Capacity for carrier '{carrier}' was not distributed "
173
                f"at all!"
174
            )
175
176
        elif (
177
            sum_output.output_capacity_mw.sum() > 0
178
            and sum_input.input_capacity_mw.sum() == 0
179
        ):
180
            logger.info(
181
                f"Error: Eventhough no input capacity was provided for carrier"
182
                f"'{carrier}' a capacity got distributed!"
183
            )
184
185
        else:
186
            sum_input["error"] = (
187
                (sum_output.output_capacity_mw - sum_input.input_capacity_mw)
188
                / sum_input.input_capacity_mw
189
            ) * 100
190
            g = sum_input["error"].values[0]
191
192
            logger.info(f"{carrier}: " + str(round(g, 2)) + " %")
193
194
    # Section to check storage units
195
196
    logger.info(f"Sanity checks for scenario {scn}")
197
    logger.info(
198
        "For German electrical storage units the following deviations between"
199
        "the inputs and outputs can be observed:"
200
    )
201
202
    carriers_electricity = ["pumped_hydro"]
203
204
    for carrier in carriers_electricity:
205
206
        sum_output = db.select_dataframe(
207
            f"""SELECT scn_name, SUM(p_nom::numeric) as output_capacity_mw
208
                         FROM grid.egon_etrago_storage
209
                         WHERE scn_name = '{scn}'
210
                         AND carrier IN ('{carrier}')
211
                         AND bus IN
212
                             (SELECT bus_id
213
                               FROM grid.egon_etrago_bus
214
                               WHERE scn_name = 'eGon2035'
215
                               AND country = 'DE')
216
                         GROUP BY (scn_name);
217
                    """,
218
            warning=False,
219
        )
220
221
        sum_input = db.select_dataframe(
222
            f"""SELECT carrier, SUM(capacity::numeric) as input_capacity_mw
223
                     FROM supply.egon_scenario_capacities
224
                     WHERE carrier= '{carrier}'
225
                     AND scenario_name ='{scn}'
226
                     GROUP BY (carrier);
227
                """,
228
            warning=False,
229
        )
230
231 View Code Duplication
        if (
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
232
            sum_output.output_capacity_mw.sum() == 0
233
            and sum_input.input_capacity_mw.sum() == 0
234
        ):
235
            print(
236
                f"No capacity for carrier '{carrier}' needed to be "
237
                f"distributed. Everything is fine"
238
            )
239
240
        elif (
241
            sum_input.input_capacity_mw.sum() > 0
242
            and sum_output.output_capacity_mw.sum() == 0
243
        ):
244
            print(
245
                f"Error: Capacity for carrier '{carrier}' was not distributed"
246
                f" at all!"
247
            )
248
249
        elif (
250
            sum_output.output_capacity_mw.sum() > 0
251
            and sum_input.input_capacity_mw.sum() == 0
252
        ):
253
            print(
254
                f"Error: Eventhough no input capacity was provided for carrier"
255
                f" '{carrier}' a capacity got distributed!"
256
            )
257
258
        else:
259
            sum_input["error"] = (
260
                (sum_output.output_capacity_mw - sum_input.input_capacity_mw)
261
                / sum_input.input_capacity_mw
262
            ) * 100
263
            g = sum_input["error"].values[0]
264
265
            print(f"{carrier}: " + str(round(g, 2)) + " %")
266
267
    # Section to check loads
268
269
    print(
270
        "For German electricity loads the following deviations between the"
271
        " input and output can be observed:"
272
    )
273
274
    output_demand = db.select_dataframe(
275
        """SELECT a.scn_name, a.carrier,  SUM((SELECT SUM(p)
276
        FROM UNNEST(b.p_set) p))/1000000::numeric as load_twh
277
            FROM grid.egon_etrago_load a
278
            JOIN grid.egon_etrago_load_timeseries b
279
            ON (a.load_id = b.load_id)
280
            JOIN grid.egon_etrago_bus c
281
            ON (a.bus=c.bus_id)
282
            AND b.scn_name = 'eGon2035'
283
            AND a.scn_name = 'eGon2035'
284
            AND a.carrier = 'AC'
285
            AND c.scn_name= 'eGon2035'
286
            AND c.country='DE'
287
            GROUP BY (a.scn_name, a.carrier);
288
289
    """,
290
        warning=False,
291
    )["load_twh"].values[0]
292
293
    input_cts_ind = db.select_dataframe(
294
        """SELECT scenario,
295
         SUM(demand::numeric/1000000) as demand_mw_regio_cts_ind
296
            FROM demand.egon_demandregio_cts_ind
297
            WHERE scenario= 'eGon2035'
298
            AND year IN ('2035')
299
            GROUP BY (scenario);
300
301
        """,
302
        warning=False,
303
    )["demand_mw_regio_cts_ind"].values[0]
304
305
    input_hh = db.select_dataframe(
306
        """SELECT scenario, SUM(demand::numeric/1000000) as demand_mw_regio_hh
307
            FROM demand.egon_demandregio_hh
308
            WHERE scenario= 'eGon2035'
309
            AND year IN ('2035')
310
            GROUP BY (scenario);
311
        """,
312
        warning=False,
313
    )["demand_mw_regio_hh"].values[0]
314
315
    input_demand = input_hh + input_cts_ind
316
317
    e = round((output_demand - input_demand) / input_demand, 2) * 100
318
319
    print(f"electricity demand: {e} %")
320
321
322
def etrago_eGon2035_heat():
323
    """Execute basic sanity checks.
324
325
    Returns print statements as sanity checks for the heat sector in
326
    the eGon2035 scenario.
327
328
    Parameters
329
    ----------
330
    None
331
332
    Returns
333
    -------
334
    None
335
    """
336
337
    # Check input and output values for the carriers "others",
338
    # "reservoir", "run_of_river" and "oil"
339
340
    scn = "eGon2035"
341
342
    # Section to check generator capacities
343
    print(f"Sanity checks for scenario {scn}")
344
    print(
345
        "For German heat demands the following deviations between the inputs"
346
        " and outputs can be observed:"
347
    )
348
349
    # Sanity checks for heat demand
350
351
    output_heat_demand = db.select_dataframe(
352
        """SELECT a.scn_name,
353
          (SUM(
354
          (SELECT SUM(p) FROM UNNEST(b.p_set) p))/1000000)::numeric as load_twh
355
            FROM grid.egon_etrago_load a
356
            JOIN grid.egon_etrago_load_timeseries b
357
            ON (a.load_id = b.load_id)
358
            JOIN grid.egon_etrago_bus c
359
            ON (a.bus=c.bus_id)
360
            AND b.scn_name = 'eGon2035'
361
            AND a.scn_name = 'eGon2035'
362
            AND c.scn_name= 'eGon2035'
363
            AND c.country='DE'
364
            AND a.carrier IN ('rural_heat', 'central_heat')
365
            GROUP BY (a.scn_name);
366
        """,
367
        warning=False,
368
    )["load_twh"].values[0]
369
370
    input_heat_demand = db.select_dataframe(
371
        """SELECT scenario, SUM(demand::numeric/1000000) as demand_mw_peta_heat
372
            FROM demand.egon_peta_heat
373
            WHERE scenario= 'eGon2035'
374
            GROUP BY (scenario);
375
        """,
376
        warning=False,
377
    )["demand_mw_peta_heat"].values[0]
378
379
    e_demand = (
380
        round((output_heat_demand - input_heat_demand) / input_heat_demand, 2)
381
        * 100
382
    )
383
384
    logger.info(f"heat demand: {e_demand} %")
385
386
    # Sanity checks for heat supply
387
388
    logger.info(
389
        "For German heat supplies the following deviations between the inputs "
390
        "and outputs can be observed:"
391
    )
392
393
    # Comparison for central heat pumps
394
    heat_pump_input = db.select_dataframe(
395
        """SELECT carrier, SUM(capacity::numeric) as Urban_central_heat_pump_mw
396
            FROM supply.egon_scenario_capacities
397
            WHERE carrier= 'urban_central_heat_pump'
398
            AND scenario_name IN ('eGon2035')
399
            GROUP BY (carrier);
400
        """,
401
        warning=False,
402
    )["urban_central_heat_pump_mw"].values[0]
403
404
    heat_pump_output = db.select_dataframe(
405
        """SELECT carrier, SUM(p_nom::numeric) as Central_heat_pump_mw
406
            FROM grid.egon_etrago_link
407
            WHERE carrier= 'central_heat_pump'
408
            AND scn_name IN ('eGon2035')
409
            GROUP BY (carrier);
410
    """,
411
        warning=False,
412
    )["central_heat_pump_mw"].values[0]
413
414
    e_heat_pump = (
415
        round((heat_pump_output - heat_pump_input) / heat_pump_output, 2) * 100
416
    )
417
418
    logger.info(f"'central_heat_pump': {e_heat_pump} % ")
419
420
    # Comparison for residential heat pumps
421
422
    input_residential_heat_pump = db.select_dataframe(
423
        """SELECT carrier, SUM(capacity::numeric) as residential_heat_pump_mw
424
            FROM supply.egon_scenario_capacities
425
            WHERE carrier= 'residential_rural_heat_pump'
426
            AND scenario_name IN ('eGon2035')
427
            GROUP BY (carrier);
428
        """,
429
        warning=False,
430
    )["residential_heat_pump_mw"].values[0]
431
432
    output_residential_heat_pump = db.select_dataframe(
433
        """SELECT carrier, SUM(p_nom::numeric) as rural_heat_pump_mw
434
            FROM grid.egon_etrago_link
435
            WHERE carrier= 'rural_heat_pump'
436
            AND scn_name IN ('eGon2035')
437
            GROUP BY (carrier);
438
    """,
439
        warning=False,
440
    )["rural_heat_pump_mw"].values[0]
441
442
    e_residential_heat_pump = (
443
        round(
444
            (output_residential_heat_pump - input_residential_heat_pump)
445
            / input_residential_heat_pump,
446
            2,
447
        )
448
        * 100
449
    )
450
    logger.info(f"'residential heat pumps': {e_residential_heat_pump} %")
451
452
    # Comparison for resistive heater
453
    resistive_heater_input = db.select_dataframe(
454
        """SELECT carrier,
455
         SUM(capacity::numeric) as Urban_central_resistive_heater_MW
456
            FROM supply.egon_scenario_capacities
457
            WHERE carrier= 'urban_central_resistive_heater'
458
            AND scenario_name IN ('eGon2035')
459
            GROUP BY (carrier);
460
        """,
461
        warning=False,
462
    )["urban_central_resistive_heater_mw"].values[0]
463
464
    resistive_heater_output = db.select_dataframe(
465
        """SELECT carrier, SUM(p_nom::numeric) as central_resistive_heater_MW
466
            FROM grid.egon_etrago_link
467
            WHERE carrier= 'central_resistive_heater'
468
            AND scn_name IN ('eGon2035')
469
            GROUP BY (carrier);
470
        """,
471
        warning=False,
472
    )["central_resistive_heater_mw"].values[0]
473
474
    e_resistive_heater = (
475
        round(
476
            (resistive_heater_output - resistive_heater_input)
477
            / resistive_heater_input,
478
            2,
479
        )
480
        * 100
481
    )
482
483
    logger.info(f"'resistive heater': {e_resistive_heater} %")
484
485
    # Comparison for solar thermal collectors
486
487
    input_solar_thermal = db.select_dataframe(
488
        """SELECT carrier, SUM(capacity::numeric) as solar_thermal_collector_mw
489
            FROM supply.egon_scenario_capacities
490
            WHERE carrier= 'urban_central_solar_thermal_collector'
491
            AND scenario_name IN ('eGon2035')
492
            GROUP BY (carrier);
493
        """,
494
        warning=False,
495
    )["solar_thermal_collector_mw"].values[0]
496
497
    output_solar_thermal = db.select_dataframe(
498
        """SELECT carrier, SUM(p_nom::numeric) as solar_thermal_collector_mw
499
            FROM grid.egon_etrago_generator
500
            WHERE carrier= 'solar_thermal_collector'
501
            AND scn_name IN ('eGon2035')
502
            GROUP BY (carrier);
503
        """,
504
        warning=False,
505
    )["solar_thermal_collector_mw"].values[0]
506
507
    e_solar_thermal = (
508
        round(
509
            (output_solar_thermal - input_solar_thermal) / input_solar_thermal,
510
            2,
511
        )
512
        * 100
513
    )
514
    logger.info(f"'solar thermal collector': {e_solar_thermal} %")
515
516
    # Comparison for geothermal
517
518
    input_geo_thermal = db.select_dataframe(
519
        """SELECT carrier,
520
         SUM(capacity::numeric) as Urban_central_geo_thermal_MW
521
            FROM supply.egon_scenario_capacities
522
            WHERE carrier= 'urban_central_geo_thermal'
523
            AND scenario_name IN ('eGon2035')
524
            GROUP BY (carrier);
525
        """,
526
        warning=False,
527
    )["urban_central_geo_thermal_mw"].values[0]
528
529
    output_geo_thermal = db.select_dataframe(
530
        """SELECT carrier, SUM(p_nom::numeric) as geo_thermal_MW
531
            FROM grid.egon_etrago_generator
532
            WHERE carrier= 'geo_thermal'
533
            AND scn_name IN ('eGon2035')
534
            GROUP BY (carrier);
535
    """,
536
        warning=False,
537
    )["geo_thermal_mw"].values[0]
538
539
    e_geo_thermal = (
540
        round((output_geo_thermal - input_geo_thermal) / input_geo_thermal, 2)
541
        * 100
542
    )
543
    logger.info(f"'geothermal': {e_geo_thermal} %")
544
545
546
def residential_electricity_annual_sum(rtol=1e-5):
547
    """Sanity check for dataset electricity_demand_timeseries :
548
    Demand_Building_Assignment
549
550
    Aggregate the annual demand of all census cells at NUTS3 to compare
551
    with initial scaling parameters from DemandRegio.
552
    """
553
554
    df_nuts3_annual_sum = db.select_dataframe(
555
        sql="""
556
        SELECT dr.nuts3, dr.scenario, dr.demand_regio_sum, profiles.profile_sum
557
        FROM (
558
            SELECT scenario, SUM(demand) AS profile_sum, vg250_nuts3
559
            FROM demand.egon_demandregio_zensus_electricity AS egon,
560
             boundaries.egon_map_zensus_vg250 AS boundaries
561
            Where egon.zensus_population_id = boundaries.zensus_population_id
562
            AND sector = 'residential'
563
            GROUP BY vg250_nuts3, scenario
564
            ) AS profiles
565
        JOIN (
566
            SELECT nuts3, scenario, sum(demand) AS demand_regio_sum
567
            FROM demand.egon_demandregio_hh
568
            GROUP BY year, scenario, nuts3
569
              ) AS dr
570
        ON profiles.vg250_nuts3 = dr.nuts3 and profiles.scenario  = dr.scenario
571
        """
572
    )
573
574
    np.testing.assert_allclose(
575
        actual=df_nuts3_annual_sum["profile_sum"],
576
        desired=df_nuts3_annual_sum["demand_regio_sum"],
577
        rtol=rtol,
578
        verbose=False,
579
    )
580
581
    logger.info(
582
        "Aggregated annual residential electricity demand"
583
        " matches with DemandRegio at NUTS-3."
584
    )
585
586
587
def residential_electricity_hh_refinement(rtol=1e-5):
588
    """Sanity check for dataset electricity_demand_timeseries :
589
    Household Demands
590
591
    Check sum of aggregated household types after refinement method
592
    was applied and compare it to the original census values."""
593
594
    df_refinement = db.select_dataframe(
595
        sql="""
596
        SELECT refined.nuts3, refined.characteristics_code,
597
                refined.sum_refined::int, census.sum_census::int
598
        FROM(
599
            SELECT nuts3, characteristics_code, SUM(hh_10types) as sum_refined
600
            FROM society.egon_destatis_zensus_household_per_ha_refined
601
            GROUP BY nuts3, characteristics_code)
602
            AS refined
603
        JOIN(
604
            SELECT t.nuts3, t.characteristics_code, sum(orig) as sum_census
605
            FROM(
606
                SELECT nuts3, cell_id, characteristics_code,
607
                        sum(DISTINCT(hh_5types))as orig
608
                FROM society.egon_destatis_zensus_household_per_ha_refined
609
                GROUP BY cell_id, characteristics_code, nuts3) AS t
610
            GROUP BY t.nuts3, t.characteristics_code    ) AS census
611
        ON refined.nuts3 = census.nuts3
612
        AND refined.characteristics_code = census.characteristics_code
613
    """
614
    )
615
616
    np.testing.assert_allclose(
617
        actual=df_refinement["sum_refined"],
618
        desired=df_refinement["sum_census"],
619
        rtol=rtol,
620
        verbose=False,
621
    )
622
623
    logger.info("All Aggregated household types match at NUTS-3.")
624
625
626
def cts_electricity_demand_share(rtol=1e-5):
627
    """Sanity check for dataset electricity_demand_timeseries :
628
    CtsBuildings
629
630
    Check sum of aggregated cts electricity demand share which equals to one
631
    for every substation as the substation profile is linearly disaggregated
632
    to all buildings."""
633
634
    with db.session_scope() as session:
635
        cells_query = session.query(EgonCtsElectricityDemandBuildingShare)
636
637
    df_demand_share = pd.read_sql(
638
        cells_query.statement, cells_query.session.bind, index_col=None
639
    )
640
641
    np.testing.assert_allclose(
642
        actual=df_demand_share.groupby(["bus_id", "scenario"])[
643
            "profile_share"
644
        ].sum(),
645
        desired=1,
646
        rtol=rtol,
647
        verbose=False,
648
    )
649
650
    logger.info("The aggregated demand shares equal to one!.")
651
652
653
def cts_heat_demand_share(rtol=1e-5):
654
    """Sanity check for dataset electricity_demand_timeseries
655
    : CtsBuildings
656
657
    Check sum of aggregated cts heat demand share which equals to one
658
    for every substation as the substation profile is linearly disaggregated
659
    to all buildings."""
660
661
    with db.session_scope() as session:
662
        cells_query = session.query(EgonCtsHeatDemandBuildingShare)
663
664
    df_demand_share = pd.read_sql(
665
        cells_query.statement, cells_query.session.bind, index_col=None
666
    )
667
668
    np.testing.assert_allclose(
669
        actual=df_demand_share.groupby(["bus_id", "scenario"])[
670
            "profile_share"
671
        ].sum(),
672
        desired=1,
673
        rtol=rtol,
674
        verbose=False,
675
    )
676
677
    logger.info("The aggregated demand shares equal to one!.")
678
679
680
def sanitycheck_pv_rooftop_buildings():
681
    def egon_power_plants_pv_roof_building():
682
        sql = """
683
        SELECT *
684
        FROM supply.egon_power_plants_pv_roof_building
685
        """
686
687
        return db.select_dataframe(sql, index_col="index")
688
689
    pv_roof_df = egon_power_plants_pv_roof_building()
690
691
    valid_buildings_gdf = load_building_data()
692
693
    valid_buildings_gdf = valid_buildings_gdf.assign(
694
        bus_id=valid_buildings_gdf.bus_id.astype(int),
695
        overlay_id=valid_buildings_gdf.overlay_id.astype(int),
696
        max_cap=valid_buildings_gdf.building_area.multiply(
697
            ROOF_FACTOR * PV_CAP_PER_SQ_M
698
        ),
699
    )
700
701
    merge_df = pv_roof_df.merge(
702
        valid_buildings_gdf[["building_area"]],
703
        how="left",
704
        left_on="building_id",
705
        right_index=True,
706
    )
707
708
    assert (
709
        len(merge_df.loc[merge_df.building_area.isna()]) == 0
710
    ), f"{len(merge_df.loc[merge_df.building_area.isna()])} != 0"
711
712
    scenarios = ["status_quo", "eGon2035"]
713
714
    base_path = Path(egon.data.__path__[0]).resolve()
715
716
    res_dir = base_path / "sanity_checks"
717
718
    res_dir.mkdir(parents=True, exist_ok=True)
719
720
    for scenario in scenarios:
721
        fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 8))
722
723
        scenario_df = merge_df.loc[merge_df.scenario == scenario]
724
725
        logger.info(
726
            scenario + " Capacity:\n" + str(scenario_df.capacity.describe())
727
        )
728
729
        small_gens_df = scenario_df.loc[scenario_df.capacity < 100]
730
731
        sns.histplot(data=small_gens_df, x="capacity", ax=ax1).set_title(
732
            scenario
733
        )
734
735
        sns.scatterplot(
736
            data=small_gens_df, x="capacity", y="building_area", ax=ax2
737
        ).set_title(scenario)
738
739
        plt.tight_layout()
740
741
        plt.savefig(
742
            res_dir / f"{scenario}_pv_rooftop_distribution.png",
743
            bbox_inches="tight",
744
        )
745
746
    for scenario in SCENARIOS:
747
        if scenario == "eGon2035":
748
            assert isclose(
749
                scenario_data(scenario=scenario).capacity.sum(),
750
                merge_df.loc[merge_df.scenario == scenario].capacity.sum(),
751
                rel_tol=1e-02,
752
            ), (
753
                f"{scenario_data(scenario=scenario).capacity.sum()} != "
754
                f"{merge_df.loc[merge_df.scenario == scenario].capacity.sum()}"
755
            )
756
        elif scenario == "eGon100RE":
757
            sources = config.datasets()["solar_rooftop"]["sources"]
758
759
            target = db.select_dataframe(
760
                f"""
761
                SELECT capacity
762
                FROM {sources['scenario_capacities']['schema']}.
763
                {sources['scenario_capacities']['table']} a
764
                WHERE carrier = 'solar_rooftop'
765
                AND scenario_name = '{scenario}'
766
                """
767
            ).capacity[0]
768
769
            dataset = config.settings()["egon-data"]["--dataset-boundary"]
770
771
            if dataset == "Schleswig-Holstein":
772
                # since the required data is missing for a SH run, it is implemented
773
                # manually here
774
                total_2035 = 84070
775
                sh_2035 = 2700
776
777
                share = sh_2035 / total_2035
778
779
                target *= share
780
781
            assert isclose(
782
                target,
783
                merge_df.loc[merge_df.scenario == scenario].capacity.sum(),
784
            ), (
785
                f"{target} != "
786
                f"{merge_df.loc[merge_df.scenario == scenario].capacity.sum()}"
787
            )
788
        else:
789
            raise ValueError(f"Scenario {scenario} is not valid.")
790
791
792
def sanitycheck_emobility_mit():
793
    """Execute sanity checks for eMobility: motorized individual travel
794
795
    Checks data integrity for eGon2035, eGon2035_lowflex and eGon100RE scenario
796
    using assertions:
797
      1. Allocated EV numbers and EVs allocated to grid districts
798
      2. Trip data (original inout data from simBEV)
799
      3. Model data in eTraGo PF tables (grid.egon_etrago_*)
800
801
    Parameters
802
    ----------
803
    None
804
805
    Returns
806
    -------
807
    None
808
    """
809
810
    def check_ev_allocation():
811
        # Get target number for scenario
812
        ev_count_target = scenario_variation_parameters["ev_count"]
813
        print(f"  Target count: {str(ev_count_target)}")
814
815
        # Get allocated numbers
816
        ev_counts_dict = {}
817
        with db.session_scope() as session:
818
            for table, level in zip(
819
                [
820
                    EgonEvCountMvGridDistrict,
821
                    EgonEvCountMunicipality,
822
                    EgonEvCountRegistrationDistrict,
823
                ],
824
                ["Grid District", "Municipality", "Registration District"],
825
            ):
826
                query = session.query(
827
                    func.sum(
828
                        table.bev_mini
829
                        + table.bev_medium
830
                        + table.bev_luxury
831
                        + table.phev_mini
832
                        + table.phev_medium
833
                        + table.phev_luxury
834
                    ).label("ev_count")
835
                ).filter(
836
                    table.scenario == scenario_name,
837
                    table.scenario_variation == scenario_var_name,
838
                )
839
840
                ev_counts = pd.read_sql(
841
                    query.statement, query.session.bind, index_col=None
842
                )
843
                ev_counts_dict[level] = ev_counts.iloc[0].ev_count
844
                print(
845
                    f"    Count table: Total count for level {level} "
846
                    f"(table: {table.__table__}): "
847
                    f"{str(ev_counts_dict[level])}"
848
                )
849
850
        # Compare with scenario target (only if not in testmode)
851
        if TESTMODE_OFF:
852
            for level, count in ev_counts_dict.items():
853
                np.testing.assert_allclose(
854
                    count,
855
                    ev_count_target,
856
                    rtol=0.0001,
857
                    err_msg=f"EV numbers in {level} seems to be flawed.",
858
                )
859
        else:
860
            print("    Testmode is on, skipping sanity check...")
861
862
        # Get allocated EVs in grid districts
863
        with db.session_scope() as session:
864
            query = session.query(
865
                func.count(EgonEvMvGridDistrict.egon_ev_pool_ev_id).label(
866
                    "ev_count"
867
                ),
868
            ).filter(
869
                EgonEvMvGridDistrict.scenario == scenario_name,
870
                EgonEvMvGridDistrict.scenario_variation == scenario_var_name,
871
            )
872
        ev_count_alloc = (
873
            pd.read_sql(query.statement, query.session.bind, index_col=None)
874
            .iloc[0]
875
            .ev_count
876
        )
877
        print(
878
            f"    EVs allocated to Grid Districts "
879
            f"(table: {EgonEvMvGridDistrict.__table__}) total count: "
880
            f"{str(ev_count_alloc)}"
881
        )
882
883
        # Compare with scenario target (only if not in testmode)
884
        if TESTMODE_OFF:
885
            np.testing.assert_allclose(
886
                ev_count_alloc,
887
                ev_count_target,
888
                rtol=0.0001,
889
                err_msg=(
890
                    "EV numbers allocated to Grid Districts seems to be "
891
                    "flawed."
892
                ),
893
            )
894
        else:
895
            print("    Testmode is on, skipping sanity check...")
896
897
        return ev_count_alloc
898
899
    def check_trip_data():
900
        # Check if trips start at timestep 0 and have a max. of 35040 steps
901
        # (8760h in 15min steps)
902
        print("  Checking timeranges...")
903
        with db.session_scope() as session:
904
            query = session.query(
905
                func.count(EgonEvTrip.event_id).label("cnt")
906
            ).filter(
907
                or_(
908
                    and_(
909
                        EgonEvTrip.park_start > 0,
910
                        EgonEvTrip.simbev_event_id == 0,
911
                    ),
912
                    EgonEvTrip.park_end
913
                    > (60 / int(meta_run_config.stepsize)) * 8760,
914
                ),
915
                EgonEvTrip.scenario == scenario_name,
916
            )
917
        invalid_trips = pd.read_sql(
918
            query.statement, query.session.bind, index_col=None
919
        )
920
        np.testing.assert_equal(
921
            invalid_trips.iloc[0].cnt,
922
            0,
923
            err_msg=(
924
                f"{str(invalid_trips.iloc[0].cnt)} trips in table "
925
                f"{EgonEvTrip.__table__} have invalid timesteps."
926
            ),
927
        )
928
929
        # Check if charging demand can be covered by available charging energy
930
        # while parking
931
        print("  Compare charging demand with available power...")
932
        with db.session_scope() as session:
933
            query = session.query(
934
                func.count(EgonEvTrip.event_id).label("cnt")
935
            ).filter(
936
                func.round(
937
                    cast(
938
                        (EgonEvTrip.park_end - EgonEvTrip.park_start + 1)
939
                        * EgonEvTrip.charging_capacity_nominal
940
                        * (int(meta_run_config.stepsize) / 60),
941
                        Numeric,
942
                    ),
943
                    3,
944
                )
945
                < cast(EgonEvTrip.charging_demand, Numeric),
946
                EgonEvTrip.scenario == scenario_name,
947
            )
948
        invalid_trips = pd.read_sql(
949
            query.statement, query.session.bind, index_col=None
950
        )
951
        np.testing.assert_equal(
952
            invalid_trips.iloc[0].cnt,
953
            0,
954
            err_msg=(
955
                f"In {str(invalid_trips.iloc[0].cnt)} trips (table: "
956
                f"{EgonEvTrip.__table__}) the charging demand cannot be "
957
                f"covered by available charging power."
958
            ),
959
        )
960
961
    def check_model_data():
962
        # Check if model components were fully created
963
        print("  Check if all model components were created...")
964
        # Get MVGDs which got EV allocated
965
        with db.session_scope() as session:
966
            query = (
967
                session.query(
968
                    EgonEvMvGridDistrict.bus_id,
969
                )
970
                .filter(
971
                    EgonEvMvGridDistrict.scenario == scenario_name,
972
                    EgonEvMvGridDistrict.scenario_variation
973
                    == scenario_var_name,
974
                )
975
                .group_by(EgonEvMvGridDistrict.bus_id)
976
            )
977
        mvgds_with_ev = (
978
            pd.read_sql(query.statement, query.session.bind, index_col=None)
979
            .bus_id.sort_values()
980
            .to_list()
981
        )
982
983
        # Load model components
984
        with db.session_scope() as session:
985
            query = (
986
                session.query(
987
                    EgonPfHvLink.bus0.label("mvgd_bus_id"),
988
                    EgonPfHvLoad.bus.label("emob_bus_id"),
989
                    EgonPfHvLoad.load_id.label("load_id"),
990
                    EgonPfHvStore.store_id.label("store_id"),
991
                )
992
                .select_from(EgonPfHvLoad, EgonPfHvStore)
993
                .join(
994
                    EgonPfHvLoadTimeseries,
995
                    EgonPfHvLoadTimeseries.load_id == EgonPfHvLoad.load_id,
996
                )
997
                .join(
998
                    EgonPfHvStoreTimeseries,
999
                    EgonPfHvStoreTimeseries.store_id == EgonPfHvStore.store_id,
1000
                )
1001
                .filter(
1002
                    EgonPfHvLoad.carrier == "land transport EV",
1003
                    EgonPfHvLoad.scn_name == scenario_name,
1004
                    EgonPfHvLoadTimeseries.scn_name == scenario_name,
1005
                    EgonPfHvStore.carrier == "battery storage",
1006
                    EgonPfHvStore.scn_name == scenario_name,
1007
                    EgonPfHvStoreTimeseries.scn_name == scenario_name,
1008
                    EgonPfHvLink.scn_name == scenario_name,
1009
                    EgonPfHvLink.bus1 == EgonPfHvLoad.bus,
1010
                    EgonPfHvLink.bus1 == EgonPfHvStore.bus,
1011
                )
1012
            )
1013
        model_components = pd.read_sql(
1014
            query.statement, query.session.bind, index_col=None
1015
        )
1016
1017
        # Check number of buses with model components connected
1018
        mvgd_buses_with_ev = model_components.loc[
1019
            model_components.mvgd_bus_id.isin(mvgds_with_ev)
1020
        ]
1021
        np.testing.assert_equal(
1022
            len(mvgds_with_ev),
1023
            len(mvgd_buses_with_ev),
1024
            err_msg=(
1025
                f"Number of Grid Districts with connected model components "
1026
                f"({str(len(mvgd_buses_with_ev))} in tables egon_etrago_*) "
1027
                f"differ from number of Grid Districts that got EVs "
1028
                f"allocated ({len(mvgds_with_ev)} in table "
1029
                f"{EgonEvMvGridDistrict.__table__})."
1030
            ),
1031
        )
1032
1033
        # Check if all required components exist (if no id is NaN)
1034
        np.testing.assert_equal(
1035
            model_components.drop_duplicates().isna().any().any(),
1036
            False,
1037
            err_msg=(
1038
                f"Some components are missing (see True values): "
1039
                f"{model_components.drop_duplicates().isna().any()}"
1040
            ),
1041
        )
1042
1043
        # Get all model timeseries
1044
        print("  Loading model timeseries...")
1045
        # Get all model timeseries
1046
        model_ts_dict = {
1047
            "Load": {
1048
                "carrier": "land transport EV",
1049
                "table": EgonPfHvLoad,
1050
                "table_ts": EgonPfHvLoadTimeseries,
1051
                "column_id": "load_id",
1052
                "columns_ts": ["p_set"],
1053
                "ts": None,
1054
            },
1055
            "Link": {
1056
                "carrier": "BEV charger",
1057
                "table": EgonPfHvLink,
1058
                "table_ts": EgonPfHvLinkTimeseries,
1059
                "column_id": "link_id",
1060
                "columns_ts": ["p_max_pu"],
1061
                "ts": None,
1062
            },
1063
            "Store": {
1064
                "carrier": "battery storage",
1065
                "table": EgonPfHvStore,
1066
                "table_ts": EgonPfHvStoreTimeseries,
1067
                "column_id": "store_id",
1068
                "columns_ts": ["e_min_pu", "e_max_pu"],
1069
                "ts": None,
1070
            },
1071
        }
1072
1073
        with db.session_scope() as session:
1074
            for node, attrs in model_ts_dict.items():
1075
                print(f"    Loading {node} timeseries...")
1076
                subquery = (
1077
                    session.query(getattr(attrs["table"], attrs["column_id"]))
1078
                    .filter(attrs["table"].carrier == attrs["carrier"])
1079
                    .filter(attrs["table"].scn_name == scenario_name)
1080
                    .subquery()
1081
                )
1082
1083
                cols = [
1084
                    getattr(attrs["table_ts"], c) for c in attrs["columns_ts"]
1085
                ]
1086
                query = session.query(
1087
                    getattr(attrs["table_ts"], attrs["column_id"]), *cols
1088
                ).filter(
1089
                    getattr(attrs["table_ts"], attrs["column_id"]).in_(
1090
                        subquery
1091
                    ),
1092
                    attrs["table_ts"].scn_name == scenario_name,
1093
                )
1094
                attrs["ts"] = pd.read_sql(
1095
                    query.statement,
1096
                    query.session.bind,
1097
                    index_col=attrs["column_id"],
1098
                )
1099
1100
        # Check if all timeseries have 8760 steps
1101
        print("    Checking timeranges...")
1102
        for node, attrs in model_ts_dict.items():
1103
            for col in attrs["columns_ts"]:
1104
                ts = attrs["ts"]
1105
                invalid_ts = ts.loc[ts[col].apply(lambda _: len(_)) != 8760][
1106
                    col
1107
                ].apply(len)
1108
                np.testing.assert_equal(
1109
                    len(invalid_ts),
1110
                    0,
1111
                    err_msg=(
1112
                        f"{str(len(invalid_ts))} rows in timeseries do not "
1113
                        f"have 8760 timesteps. Table: "
1114
                        f"{attrs['table_ts'].__table__}, Column: {col}, IDs: "
1115
                        f"{str(list(invalid_ts.index))}"
1116
                    ),
1117
                )
1118
1119
        # Compare total energy demand in model with some approximate values
1120
        # (per EV: 14,000 km/a, 0.17 kWh/km)
1121
        print("  Checking energy demand in model...")
1122
        total_energy_model = (
1123
            model_ts_dict["Load"]["ts"].p_set.apply(lambda _: sum(_)).sum()
1124
            / 1e6
1125
        )
1126
        print(f"    Total energy amount in model: {total_energy_model} TWh")
1127
        total_energy_scenario_approx = ev_count_alloc * 14000 * 0.17 / 1e9
1128
        print(
1129
            f"    Total approximated energy amount in scenario: "
1130
            f"{total_energy_scenario_approx} TWh"
1131
        )
1132
        np.testing.assert_allclose(
1133
            total_energy_model,
1134
            total_energy_scenario_approx,
1135
            rtol=0.1,
1136
            err_msg=(
1137
                "The total energy amount in the model deviates heavily "
1138
                "from the approximated value for current scenario."
1139
            ),
1140
        )
1141
1142
        # Compare total storage capacity
1143
        print("  Checking storage capacity...")
1144
        # Load storage capacities from model
1145
        with db.session_scope() as session:
1146
            query = session.query(
1147
                func.sum(EgonPfHvStore.e_nom).label("e_nom")
1148
            ).filter(
1149
                EgonPfHvStore.scn_name == scenario_name,
1150
                EgonPfHvStore.carrier == "battery storage",
1151
            )
1152
        storage_capacity_model = (
1153
            pd.read_sql(
1154
                query.statement, query.session.bind, index_col=None
1155
            ).e_nom.sum()
1156
            / 1e3
1157
        )
1158
        print(
1159
            f"    Total storage capacity ({EgonPfHvStore.__table__}): "
1160
            f"{round(storage_capacity_model, 1)} GWh"
1161
        )
1162
1163
        # Load occurences of each EV
1164
        with db.session_scope() as session:
1165
            query = (
1166
                session.query(
1167
                    EgonEvMvGridDistrict.bus_id,
1168
                    EgonEvPool.type,
1169
                    func.count(EgonEvMvGridDistrict.egon_ev_pool_ev_id).label(
1170
                        "count"
1171
                    ),
1172
                )
1173
                .join(
1174
                    EgonEvPool,
1175
                    EgonEvPool.ev_id
1176
                    == EgonEvMvGridDistrict.egon_ev_pool_ev_id,
1177
                )
1178
                .filter(
1179
                    EgonEvMvGridDistrict.scenario == scenario_name,
1180
                    EgonEvMvGridDistrict.scenario_variation
1181
                    == scenario_var_name,
1182
                    EgonEvPool.scenario == scenario_name,
1183
                )
1184
                .group_by(EgonEvMvGridDistrict.bus_id, EgonEvPool.type)
1185
            )
1186
        count_per_ev_all = pd.read_sql(
1187
            query.statement, query.session.bind, index_col="bus_id"
1188
        )
1189
        count_per_ev_all["bat_cap"] = count_per_ev_all.type.map(
1190
            meta_tech_data.battery_capacity
1191
        )
1192
        count_per_ev_all["bat_cap_total_MWh"] = (
1193
            count_per_ev_all["count"] * count_per_ev_all.bat_cap / 1e3
1194
        )
1195
        storage_capacity_simbev = count_per_ev_all.bat_cap_total_MWh.div(
1196
            1e3
1197
        ).sum()
1198
        print(
1199
            f"    Total storage capacity (simBEV): "
1200
            f"{round(storage_capacity_simbev, 1)} GWh"
1201
        )
1202
1203
        np.testing.assert_allclose(
1204
            storage_capacity_model,
1205
            storage_capacity_simbev,
1206
            rtol=0.01,
1207
            err_msg=(
1208
                "The total storage capacity in the model deviates heavily "
1209
                "from the input data provided by simBEV for current scenario."
1210
            ),
1211
        )
1212
1213
        # Check SoC storage constraint: e_min_pu < e_max_pu for all timesteps
1214
        print("  Validating SoC constraints...")
1215
        stores_with_invalid_soc = []
1216
        for idx, row in model_ts_dict["Store"]["ts"].iterrows():
1217
            ts = row[["e_min_pu", "e_max_pu"]]
1218
            x = np.array(ts.e_min_pu) > np.array(ts.e_max_pu)
1219
            if x.any():
1220
                stores_with_invalid_soc.append(idx)
1221
1222
        np.testing.assert_equal(
1223
            len(stores_with_invalid_soc),
1224
            0,
1225
            err_msg=(
1226
                f"The store constraint e_min_pu < e_max_pu does not apply "
1227
                f"for some storages in {EgonPfHvStoreTimeseries.__table__}. "
1228
                f"Invalid store_ids: {stores_with_invalid_soc}"
1229
            ),
1230
        )
1231
1232
    def check_model_data_lowflex_eGon2035():
1233
        # TODO: Add eGon100RE_lowflex
1234
        print("")
1235
        print("SCENARIO: eGon2035_lowflex")
1236
1237
        # Compare driving load and charging load
1238
        print("  Loading eGon2035 model timeseries: driving load...")
1239
        with db.session_scope() as session:
1240
            query = (
1241
                session.query(
1242
                    EgonPfHvLoad.load_id,
1243
                    EgonPfHvLoadTimeseries.p_set,
1244
                )
1245
                .join(
1246
                    EgonPfHvLoadTimeseries,
1247
                    EgonPfHvLoadTimeseries.load_id == EgonPfHvLoad.load_id,
1248
                )
1249
                .filter(
1250
                    EgonPfHvLoad.carrier == "land transport EV",
1251
                    EgonPfHvLoad.scn_name == "eGon2035",
1252
                    EgonPfHvLoadTimeseries.scn_name == "eGon2035",
1253
                )
1254
            )
1255
        model_driving_load = pd.read_sql(
1256
            query.statement, query.session.bind, index_col=None
1257
        )
1258
        driving_load = np.array(model_driving_load.p_set.to_list()).sum(axis=0)
1259
1260
        print(
1261
            "  Loading eGon2035_lowflex model timeseries: dumb charging "
1262
            "load..."
1263
        )
1264
        with db.session_scope() as session:
1265
            query = (
1266
                session.query(
1267
                    EgonPfHvLoad.load_id,
1268
                    EgonPfHvLoadTimeseries.p_set,
1269
                )
1270
                .join(
1271
                    EgonPfHvLoadTimeseries,
1272
                    EgonPfHvLoadTimeseries.load_id == EgonPfHvLoad.load_id,
1273
                )
1274
                .filter(
1275
                    EgonPfHvLoad.carrier == "land transport EV",
1276
                    EgonPfHvLoad.scn_name == "eGon2035_lowflex",
1277
                    EgonPfHvLoadTimeseries.scn_name == "eGon2035_lowflex",
1278
                )
1279
            )
1280
        model_charging_load_lowflex = pd.read_sql(
1281
            query.statement, query.session.bind, index_col=None
1282
        )
1283
        charging_load = np.array(
1284
            model_charging_load_lowflex.p_set.to_list()
1285
        ).sum(axis=0)
1286
1287
        # Ratio of driving and charging load should be 0.9 due to charging
1288
        # efficiency
1289
        print("  Compare cumulative loads...")
1290
        print(f"    Driving load (eGon2035): {driving_load.sum() / 1e6} TWh")
1291
        print(
1292
            f"    Dumb charging load (eGon2035_lowflex): "
1293
            f"{charging_load.sum() / 1e6} TWh"
1294
        )
1295
        driving_load_theoretical = (
1296
            float(meta_run_config.eta_cp) * charging_load.sum()
0 ignored issues
show
introduced by
The variable meta_run_config does not seem to be defined in case the for loop on line 1314 is not entered. Are you sure this can never be the case?
Loading history...
1297
        )
1298
        np.testing.assert_allclose(
1299
            driving_load.sum(),
1300
            driving_load_theoretical,
1301
            rtol=0.01,
1302
            err_msg=(
1303
                f"The driving load (eGon2035) deviates by more than 1% "
1304
                f"from the theoretical driving load calculated from charging "
1305
                f"load (eGon2035_lowflex) with an efficiency of "
1306
                f"{float(meta_run_config.eta_cp)}."
1307
            ),
1308
        )
1309
1310
    print("=====================================================")
1311
    print("=== SANITY CHECKS FOR MOTORIZED INDIVIDUAL TRAVEL ===")
1312
    print("=====================================================")
1313
1314
    for scenario_name in ["eGon2035", "eGon100RE"]:
1315
        scenario_var_name = DATASET_CFG["scenario"]["variation"][scenario_name]
1316
1317
        print("")
1318
        print(f"SCENARIO: {scenario_name}, VARIATION: {scenario_var_name}")
1319
1320
        # Load scenario params for scenario and scenario variation
1321
        scenario_variation_parameters = get_sector_parameters(
1322
            "mobility", scenario=scenario_name
1323
        )["motorized_individual_travel"][scenario_var_name]
1324
1325
        # Load simBEV run config and tech data
1326
        meta_run_config = read_simbev_metadata_file(
1327
            scenario_name, "config"
1328
        ).loc["basic"]
1329
        meta_tech_data = read_simbev_metadata_file(scenario_name, "tech_data")
1330
1331
        print("")
1332
        print("Checking EV counts...")
1333
        ev_count_alloc = check_ev_allocation()
1334
1335
        print("")
1336
        print("Checking trip data...")
1337
        check_trip_data()
1338
1339
        print("")
1340
        print("Checking model data...")
1341
        check_model_data()
1342
1343
    print("")
1344
    check_model_data_lowflex_eGon2035()
1345
1346
    print("=====================================================")
1347