insert()   F
last analyzed

Complexity

Conditions 49

Size

Total Lines 1324
Code Lines 748

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 748
dl 0
loc 1324
rs 0
c 0
b 0
f 0
cc 49
nop 0

How to fix   Long Method    Complexity   

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:

Complexity

Complex classes like data.datasets.power_plants.pv_ground_mounted.insert() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import geopandas as gpd
2
import numpy as np
3
import pandas as pd
4
5
from egon.data import db
6
from egon.data.datasets.mastr import WORKING_DIR_MASTR_NEW
7
import egon.data.config
8
9
10
def insert():
11
    def mastr_existing_pv(pow_per_area):
12
        """Import MaStR data from csv-files.
13
14
        Parameters
15
        ----------
16
        pow_per_area: int
17
            Assumption for areas of existing pv farms and power of new built
18
            pv farms depending on area in kW/m²
19
20
        """
21
        # get config
22
        cfg = egon.data.config.datasets()["power_plants"]
23
24
        # import MaStR data: locations, grid levels and installed capacities
25
26
        # get relevant pv plants: ground mounted
27
        df = pd.read_csv(
28
            WORKING_DIR_MASTR_NEW / cfg["sources"]["mastr_pv"],
29
            usecols=[
30
                "Lage",
31
                "Laengengrad",
32
                "Breitengrad",
33
                "Nettonennleistung",
34
                "EinheitMastrNummer",
35
                "LokationMastrNummer",
36
            ],
37
        )
38
        df = df[df["Lage"] == "Freifläche"]
39
40
        # examine data concerning geographical locations and drop NaNs
41
        x1 = df["Laengengrad"].isnull().sum()
42
        x2 = df["Breitengrad"].isnull().sum()
43
        print(" ")
44
        print("Examination of MaStR data set:")
45
        print("original number of rows in the data set: " + str(len(df)))
46
        print("NaNs for longitude and latitude: " + str(x1) + " & " + str(x2))
47
        df.dropna(inplace=True)
48
        print("Number of rows after neglecting NaNs: " + str(len(df)))
49
        print(" ")
50
51
        # derive dataframe for locations
52
        mastr = gpd.GeoDataFrame(
53
            index=df.index,
54
            geometry=gpd.points_from_xy(df["Laengengrad"], df["Breitengrad"]),
55
            crs={"init": "epsg:4326"},
56
        )
57
        mastr = mastr.to_crs(3035)
58
59
        # derive installed capacities
60
        mastr["installed capacity in kW"] = df["Nettonennleistung"]
61
62
        # create buffer around locations
63
64
        # calculate bufferarea and -radius considering installed capacity
65
        df_radius = (
66
            mastr["installed capacity in kW"].div(pow_per_area * np.pi) ** 0.5
67
        )  # in m
68
69
        # create buffer
70
        mastr["buffer"] = mastr["geometry"].buffer(df_radius)
71
        mastr["buffer"].crs = 3035
72
73
        # derive MaStR-Nummer
74
        mastr["LokationMastrNummer"] = df["LokationMastrNummer"]
75
76
        # derive voltage level
77
78
        mastr["voltage_level"] = pd.Series(dtype=int)
79
        lvl = pd.read_csv(
80
            WORKING_DIR_MASTR_NEW / cfg["sources"]["mastr_location"],
81
            usecols=["Spannungsebene", "MaStRNummer"],
82
        )
83
84
        # assign voltage_level to MaStR-unit:
85
86
        vlevel_mapping = {
87
            "Höchstspannung": 1,
88
            "UmspannungZurHochspannung": 2,
89
            "Hochspannung": 3,
90
            "UmspannungZurMittelspannung": 4,
91
            "Mittelspannung": 5,
92
            "UmspannungZurNiederspannung": 6,
93
            "Niederspannung": 7,
94
        }
95
96
        mastr = mastr.merge(
97
            lvl[["MaStRNummer", "Spannungsebene"]],
98
            left_on="LokationMastrNummer",
99
            right_on="MaStRNummer",
100
            how="left",
101
        )
102
103
        mastr["voltage_level"] = mastr.Spannungsebene.replace(vlevel_mapping)
104
105
        mastr.drop(["MaStRNummer", "Spannungsebene"], axis=1, inplace=True)
106
107
        # ### examine data concerning voltage level
108
        x1 = mastr["voltage_level"].isnull().sum()
109
        print(" ")
110
        print("Examination of voltage levels in MaStR data set:")
111
        print("Original number of rows in MaStR: " + str(len(mastr)))
112
        print(
113
            "NaNs in voltage level caused by a) a missing assignment to the "
114
            "number or b) insufficient data: " + str(x1)
115
        )
116
        # drop PVs with missing values due to a) no assignment of
117
        # MaStR-numbers or b) missing data in row
118
        mastr.dropna(inplace=True)
119
        print("Number of rows after neglecting NaNs: " + str(len(mastr)))
120
121
        # drop PVs in low voltage level
122
        index_names = mastr[mastr["voltage_level"] == "Niederspannung"].index
123
        x2 = len(index_names)
124
        mastr.drop(index_names, inplace=True)
125
        index_names = mastr[
126
            mastr["voltage_level"] == "UmspannungZurNiederspannung"
127
        ].index
128
        x3 = len(index_names)
129
        mastr.drop(index_names, inplace=True)
130
131
        # ### further examination
132
        print("Number of PVs in low voltage level: " + str(x2))
133
        print("Number of PVs in LVMV level: " + str(x3))
134
        print(
135
            "Number of rows after dropping entries assigned to these levels: "
136
            + str(len(mastr))
137
        )
138
        print(" ")
139
140
        return mastr
141
142
    def potential_areas(con, join_buffer):
143
        """Import potential areas and choose and prepare areas suitable for PV
144
        ground mounted.
145
146
        Parameters
147
        ----------
148
        con:
149
            Connection to database
150
        join_buffer: int
151
            Maximum distance for joining of potential areas (only small ones
152
            to big ones) in m
153
154
        """
155
156
        # import potential areas: railways and roads & agriculture
157
158
        # roads and railway
159
        sql = (
160
            "SELECT id, geom FROM "
161
            "supply.egon_re_potential_area_pv_road_railway"
162
        )
163
        potentials_rora = gpd.GeoDataFrame.from_postgis(sql, con)
164
        potentials_rora = potentials_rora.set_index("id")
165
166
        # agriculture
167
        sql = (
168
            "SELECT id, geom FROM "
169
            "supply.egon_re_potential_area_pv_agriculture"
170
        )
171
        potentials_agri = gpd.GeoDataFrame.from_postgis(sql, con)
172
        potentials_agri = potentials_agri.set_index("id")
173
174
        # add areas < 1 ha to bigger areas if they are very close, otherwise
175
        # exclude areas < 1 ha
176
177
        # calculate area
178
        potentials_rora["area"] = potentials_rora.area
179
        potentials_agri["area"] = potentials_agri.area
180
181
        # roads and railways
182
183
        # ### counting variable for examination
184
        before = len(potentials_rora)
185
186
        # get small areas and create buffer for joining around them
187
        small_areas = potentials_rora[potentials_rora["area"] < 10000]
188
        small_buffers = small_areas.copy()
189
        small_buffers["geom"] = small_areas["geom"].buffer(join_buffer)
190
191
        # drop small areas in potential areas
192
        index_names = potentials_rora[potentials_rora["area"] < 10000].index
193
        potentials_rora.drop(index_names, inplace=True)
194
195
        # check intersection of small areas with other potential areas
196
        overlay = gpd.sjoin(potentials_rora, small_buffers)
197
        o = overlay["index_right"]
198
        o.drop_duplicates(inplace=True)
199
200
        # add small areas to big ones if buffer intersects
201
        for i in range(0, len(o)):
202
            index_potentials = o.index[i]
203
            index_small = o.iloc[i]
204
            x = potentials_rora["geom"].loc[index_potentials]
205
            y = small_areas["geom"].loc[index_small]
206
            join = gpd.GeoSeries(data=[x, y])
207
            potentials_rora["geom"].loc[index_potentials] = join.unary_union
208
209
        # ### examination of joining of areas
210
        count_small = len(small_buffers)
211
        count_join = len(o)
212
        count_delete = count_small - count_join
213
        print(" ")
214
        print(
215
            "Examination of potential areas in category 'Roads and Railways'"
216
        )
217
        print("Length of original data frame: " + str(before))
218
        print("Number of small areas: " + str(count_small))
219
        print("Number of joins: " + str(count_join))
220
        print("Deleted areas (not joined): " + str(count_delete))
221
        print("Length of resulting data frame: " + str(len(potentials_rora)))
222
        print(" ")
223
224
        # agriculture
225
226
        # ### counting variable for examination
227
        before = len(potentials_agri)
228
229
        # get small areas and create buffer for joining around them
230
        small_areas = potentials_agri[potentials_agri["area"] < 10000]
231
        small_buffers = small_areas.copy()
232
        small_buffers["geom"] = small_areas["geom"].buffer(join_buffer)
233
234
        # drop small areas in potential areas
235
        index_names = potentials_agri[potentials_agri["area"] < 10000].index
236
        potentials_agri.drop(index_names, inplace=True)
237
238
        # check intersection of small areas with other potential areas
239
        overlay = gpd.sjoin(potentials_agri, small_buffers)
240
        o = overlay["index_right"]
241
        o.drop_duplicates(inplace=True)
242
243
        # add small areas to big ones if buffer intersects
244
        for i in range(0, len(o)):
245
            index_potentials = o.index[i]
246
            index_small = o.iloc[i]
247
            x = potentials_agri["geom"].loc[index_potentials]
248
            y = small_areas["geom"].loc[index_small]
249
            join = gpd.GeoSeries(data=[x, y])
250
            potentials_agri["geom"].loc[index_potentials] = join.unary_union
251
252
        # ### examination of joining of areas
253
        count_small = len(small_buffers)
254
        count_join = len(o)
255
        count_delete = count_small - count_join
256
        print(" ")
257
        print("Examination of potential areas in category 'Agriculture'")
258
        print("Length of original data frame: " + str(before))
259
        print("Number of small areas: " + str(count_small))
260
        print("Number of joins: " + str(count_join))
261
        print("Deleted areas (not joined): " + str(count_delete))
262
        print("Length of resulting data frame: " + str(len(potentials_agri)))
263
        print(" ")
264
265
        # calculate new areas
266
        potentials_rora["area"] = potentials_rora.area
267
        potentials_agri["area"] = potentials_agri.area
268
269
        # check intersection of potential areas
270
271
        # ### counting variable
272
        agri_vorher = len(potentials_agri)
273
274
        # if areas intersect, keep road & railway potential areas and drop
275
        # agricultural ones
276
        overlay = gpd.sjoin(potentials_rora, potentials_agri)
277
        o = overlay["index_right"]
278
        o.drop_duplicates(inplace=True)
279
        for i in range(0, len(o)):
280
            index = o.iloc[i]
281
            potentials_agri.drop([index], inplace=True)
282
283
        # ### examination of intersection of areas
284
        print(" ")
285
        print("Review function to avoid intersection of potential areas:")
286
        print("Initial length potentials_agri: " + str(agri_vorher))
287
        print("Number of occurred cases: " + str(len(o)))
288
        print("Resulting length potentials_agri: " + str(len(potentials_agri)))
289
        print(" ")
290
291
        return potentials_rora, potentials_agri
292
293
    def select_pot_areas(mastr, potentials_pot):
294
        """Select potential areas where there are existing pv parks
295
        (MaStR-data).
296
297
        Parameters
298
        ----------
299
        mastr: gpd.GeoDataFrame()
300
            MaStR-DataFrame with existing pv parks
301
        potentials_pot: gpd.GeoDataFrame()
302
            Suitable potential areas
303
304
        """
305
306
        # select potential areas with existing pv parks
307
        # (potential areas intersect buffer around existing plants)
308
309
        # prepare dataframes to check intersection
310
        pvs = gpd.GeoDataFrame()
311
        pvs["geom"] = mastr["buffer"].copy()
312
        pvs.set_geometry("geom", inplace=True)
313
        pvs.crs = 3035
314
        pvs = pvs.set_geometry("geom")
315
        potentials = gpd.GeoDataFrame()
316
        potentials["geom"] = potentials_pot["geom"].copy()
317
        potentials.set_geometry("geom", inplace=True)
318
        potentials.crs = 3035
319
        potentials = potentials.set_geometry("geom")
320
321
        # check intersection of potential areas with exisiting PVs (MaStR)
322
        overlay = gpd.sjoin(pvs, potentials)
323
        o = overlay["index_right"]
324
        o.drop_duplicates(inplace=True)
325
326
        # define selected potentials areas
327
        pot_sel = potentials_pot.copy()
328
        pot_sel["selected"] = pd.Series()
329
        pot_sel["voltage_level"] = pd.Series(dtype=int)
330
        for i in range(0, len(o)):
331
            index_pot = o.iloc[i]
332
            pot_sel["selected"].loc[index_pot] = True
333
            # get voltage level of existing PVs
334
            index_pv = o.index[i]
335
            pot_sel["voltage_level"] = mastr["voltage_level"].loc[index_pv]
336
        pot_sel = pot_sel[pot_sel["selected"] == True]
337
        pot_sel.drop("selected", axis=1, inplace=True)
338
339
        # drop selected existing pv parks from mastr
340
        mastr.drop(index=o.index, inplace=True)
341
342
        return (pot_sel, mastr)
343
344
    def build_pv(pv_pot, pow_per_area):
345
        """Build new pv parks in selected potential areas.
346
347
        Parameters
348
        ----------
349
        pv_pot: gpd.GeoDataFrame()
350
            Selected potential areas
351
        pow_per_area: int
352
            Assumption for areas of existing pv farms and power of new built
353
            pv farms depending on area in kW/m²
354
355
        """
356
357
        # build pv farms in selected areas
358
359
        # calculation of centroids
360
        pv_pot["centroid"] = pv_pot["geom"].representative_point()
361
362
        # calculation of power in kW
363
        pv_pot["installed capacity in kW"] = pd.Series()
364
        pv_pot["installed capacity in kW"] = pv_pot["area"] * pow_per_area
365
366
        # check for maximal capacity for PV ground mounted
367
        limit_cap = 120000  # in kW
368
        pv_pot["installed capacity in kW"] = pv_pot[
369
            "installed capacity in kW"
370
        ].apply(lambda x: x if x < limit_cap else limit_cap)
371
372
        return pv_pot
373
374
    def adapt_grid_level(pv_pot, max_dist_hv, con):
375
        """Check and if needed adapt grid level of newly built pv parks.
376
377
        Parameters
378
        ----------
379
        pv_pot: gpd.GeoDataFrame()
380
            Newly built pv parks on selected potential areas
381
        max_dist_hv: int
382
            Assumption for maximum distance of park with hv-power to next
383
            substation in m
384
        con:
385
            Connection to database
386
387
        """
388
389
        # divide dataframe in MV and HV
390
        pv_pot_mv = pv_pot[pv_pot["voltage_level"] == 5]
391
        pv_pot_hv = pv_pot[pv_pot["voltage_level"] == 4]
392
393
        # check installed capacity in MV
394
395
        max_cap_mv = 5500  # in kW
396
397
        # find PVs which need to be HV or to have reduced capacity
398
        pv_pot_mv_to_hv = pv_pot_mv[
399
            pv_pot_mv["installed capacity in kW"] > max_cap_mv
400
        ]
401
402
        if len(pv_pot_mv_to_hv) > 0:
403
            # import data for HV substations
404
405
            sql = "SELECT point, voltage FROM grid.egon_hvmv_substation"
406
            hvmv_substation = gpd.GeoDataFrame.from_postgis(
407
                sql, con, geom_col="point"
408
            )
409
            hvmv_substation = hvmv_substation.to_crs(3035)
410
            hvmv_substation["voltage"] = hvmv_substation["voltage"].apply(
411
                lambda x: int(x.split(";")[0])
412
            )
413
            hv_substations = hvmv_substation[
414
                hvmv_substation["voltage"] >= 110000
415
            ]
416
            hv_substations = (
417
                hv_substations.unary_union
418
            )  # join all the hv_substations
419
420
            # check distance to HV substations of PVs with too high installed
421
            # capacity for MV
422
423
            # calculate distance to substations
424
            pv_pot_mv_to_hv["dist_to_HV"] = (
425
                pv_pot_mv_to_hv["geom"].to_crs(3035).distance(hv_substations)
426
            )
427
428
            # adjust grid level and keep capacity if transmission lines are
429
            # close
430
            pv_pot_mv_to_hv = pv_pot_mv_to_hv[
431
                pv_pot_mv_to_hv["dist_to_HV"] <= max_dist_hv
432
            ]
433
            pv_pot_mv_to_hv = pv_pot_mv_to_hv.drop(columns=["dist_to_HV"])
434
            pv_pot_hv = pd.concat([pv_pot_hv, pv_pot_mv_to_hv])
435
436
            # delete PVs which are now HV from MV dataframe
437
            for index, pot in pv_pot_mv_to_hv.iterrows():
438
                pv_pot_mv = pv_pot_mv.drop([index])
439
            pv_pot_hv["voltage_level"] = 4
440
441
            # keep grid level adjust capacity if transmission lines are too
442
            # far
443
            pv_pot_mv["installed capacity in kW"] = pv_pot_mv[
444
                "installed capacity in kW"
445
            ].apply(lambda x: x if x < max_cap_mv else max_cap_mv)
446
            pv_pot_mv["voltage_level"] = 5
447
448
            pv_pot = pd.concat([pv_pot_mv, pv_pot_hv])
449
450
        return pv_pot
451
452
    def build_additional_pv(potentials, pv, pow_per_area, con):
453
        """Build additional pv parks if pv parks on selected potential areas
454
        do not hit the target value.
455
456
         Parameters
457
         ----------
458
         potenatials: gpd.GeoDataFrame()
459
             All suitable potential areas
460
         pv: gpd.GeoDataFrame()
461
             Newly built pv parks on selected potential areas
462
        pow_per_area: int
463
             Assumption for areas of existing pv farms and power of new built
464
             pv farms depending on area in kW/m²
465
         con:
466
             Connection to database
467
468
        """
469
470
        # get MV grid districts
471
        sql = "SELECT bus_id, geom FROM grid.egon_mv_grid_district"
472
        distr = gpd.GeoDataFrame.from_postgis(sql, con)
473
        distr = distr.set_index("bus_id")
474
475
        # identify potential areas where there are no PV parks yet
476
        for index, pv in pv.iterrows():
477
            potentials = potentials.drop([index])
478
479
        # aggregate potential area per MV grid district
480
        pv_per_distr = gpd.GeoDataFrame()
481
        pv_per_distr["geom"] = distr["geom"].copy()
482
        centroids = potentials.copy()
483
        centroids["geom"] = centroids["geom"].representative_point()
484
485
        overlay = gpd.sjoin(centroids, distr)
486
487
        # ### examine potential area per grid district
488
        anz = len(overlay)
489
        anz_distr = len(overlay["index_right"].unique())
490
        size = 137500  # m2 Fläche für > 5,5 MW: (5500 kW / (0,04 kW/m2))
491
        anz_big = len(overlay[overlay["area"] >= size])
492
        anz_small = len(overlay[overlay["area"] < size])
493
494
        print(" ")
495
        print(
496
            "Examination of remaining potential areas in MV grid districts: "
497
        )
498
        print("Number of potential areas: " + str(anz))
499
        print(" -> distributed to " + str(anz_distr) + " districts")
500
        print("Number of areas with a potential >= 5,5 MW: " + str(anz_big))
501
        print("Number of areas with a potential < 5,5 MW: " + str(anz_small))
502
        print(" ")
503
504
        for index, dist in distr.iterrows():
505
            pots = overlay[overlay["index_right"] == index]["geom"].index
506
            p = gpd.GeoSeries(index=pots)
507
            for i in pots:
508
                p.loc[i] = potentials["geom"].loc[i]
509
            pv_per_distr["geom"].loc[index] = p.unary_union
510
511
        # calculate area per MV grid district and linearly distribute needed
512
        # capacity considering pow_per_area
513
        pv_per_distr["area"] = pv_per_distr["geom"].area
514
        pv_per_distr["installed capacity in kW"] = (
515
            pv_per_distr["area"] * pow_per_area
516
        )
517
518
        # calculate centroid
519
        pv_per_distr["centroid"] = pv_per_distr["geom"].representative_point()
520
521
        return pv_per_distr
522
523
    def check_target(
524
        pv_rora_i,
525
        pv_agri_i,
526
        pv_exist_i,
527
        potentials_rora_i,
528
        potentials_agri_i,
529
        target_power,
530
        pow_per_area,
531
        con,
532
    ):
533
        """Check target value per scenario and per state.
534
535
         Parameters
536
         ----------
537
         pv_rora_i: gpd.GeoDataFrame()
538
             Newly built pv parks on selected potential areas of road and
539
             railways p
540
         pv_agri_i: gpd.GeoDataFrame()
541
             Newly built pv parks on selected potential areas of agriculture
542
         pv_exist_i: gpd.GeoDataFrame()
543
             existing pv parks that don't intercept any potential area
544
         potenatials_rora_i: gpd.GeoDataFrame()
545
             All suitable potential areas of road and railway
546
         potenatials_rora_i: gpd.GeoDataFrame()
547
             All suitable potential areas of agriculture
548
         target_power: int
549
             Target for installed capacity of pv ground mounted in referenced
550
             state
551
        pow_per_area: int
552
             Assumption for areas of existing pv farms and power of new built
553
             pv farms depending on area in kW/m²
554
         con:
555
             Connection to database
556
557
        """
558
559
        # sum overall installed capacity for MV and HV
560
561
        total_pv_power = (
562
            pv_rora_i["installed capacity in kW"].sum()
563
            + pv_agri_i["installed capacity in kW"].sum()
564
            + pv_exist_i["installed capacity in kW"].sum()
565
        )
566
567
        pv_per_distr_i = gpd.GeoDataFrame()
568
569
        # check target value
570
571
        ###
572
        print(" ")
573
        print(
574
            "Installed capacity on areas with existing plants: "
575
            + str(total_pv_power / 1000)
576
            + " MW"
577
        )
578
579
        # linear scale farms to meet target if sum of installed capacity is
580
        # too high
581
        if total_pv_power >= target_power:
582
            scale_factor = target_power / total_pv_power
583
            pv_rora_i["installed capacity in kW"] = (
584
                pv_rora_i["installed capacity in kW"] * scale_factor
585
            )
586
            pv_agri_i["installed capacity in kW"] = (
587
                pv_agri_i["installed capacity in kW"] * scale_factor
588
            )
589
            pv_exist_i["installed capacity in kW"] = (
590
                pv_exist_i["installed capacity in kW"] * scale_factor
591
            )
592
593
            pv_per_distr_i["grid_district"] = pd.Series()
594
            pv_per_distr_i["installed capacity in kW"] = pd.Series(0)
595
596
            ###
597
            print(
598
                "Expansion of existing PV parks on potential areas to "
599
                "achieve target capacity is sufficient."
600
            )
601
            print(
602
                "Installed power is greater than the target value, scaling "
603
                "is applied:"
604
            )
605
            print("Scaling factor: " + str(scale_factor))
606
607
        # build new pv parks if sum of installed capacity is below target
608
        # value
609
        elif total_pv_power < target_power:
610
            rest_cap = target_power - total_pv_power
611
612
            ###
613
            print(
614
                "Expansion of existing PV parks on potential areas to "
615
                "achieve target capacity is unsufficient:"
616
            )
617
            print("Residual capacity: " + str(rest_cap / 1000) + " MW")
618
            print(
619
                "Residual capacity will initially be distributed via "
620
                "remaining potential areas 'Road & Railway'."
621
            )
622
623
            # build pv parks in potential areas road & railway
624
            pv_per_distr_i = build_additional_pv(
625
                potentials_rora_i, pv_rora_i, pow_per_area, con
626
            )
627
            # change index to add different Dataframes in the end
628
            pv_per_distr_i["grid_district"] = pv_per_distr_i.index.copy()
629
            pv_per_distr_i.index = range(0, len(pv_per_distr_i))
630
            # delete empty grid districts
631
            index_names = pv_per_distr_i[
632
                pv_per_distr_i["installed capacity in kW"].isna()
633
            ].index
634
            pv_per_distr_i.drop(index_names, inplace=True)
635
636
            if pv_per_distr_i["installed capacity in kW"].sum() > rest_cap:
637
                scale_factor = (
638
                    rest_cap / pv_per_distr_i["installed capacity in kW"].sum()
639
                )
640
                pv_per_distr_i["installed capacity in kW"] = (
641
                    pv_per_distr_i["installed capacity in kW"] * scale_factor
642
                )
643
644
                ###
645
                print(
646
                    "Residual capacity got distributed via scaling factor "
647
                    + str(scale_factor)
648
                    + " to remaining potential areas 'Road & Railway'."
649
                )
650
651
            # build pv parks on potential areas agriculture if still necessary
652
            elif pv_per_distr_i["installed capacity in kW"].sum() < rest_cap:
653
                rest_cap = (
654
                    target_power
655
                    - total_pv_power
656
                    - pv_per_distr_i["installed capacity in kW"].sum()
657
                )
658
659
                ###
660
                print(
661
                    "Distribution via potential areas Road & Railway "
662
                    "unsufficient to achieve target capacity:"
663
                )
664
                print("Residual capacity: " + str(rest_cap / 1000) + " MW")
665
                print(
666
                    "Residual capacity is distributed to remaining potential "
667
                    "areas 'Agriculture'."
668
                )
669
670
                pv_per_distr_i_2 = build_additional_pv(
671
                    potentials_agri_i, pv_agri_i, pow_per_area, con
672
                )
673
                # change index to add different Dataframes in the end
674
                pv_per_distr_i_2["grid_district"] = pv_per_distr_i_2.index
675
                pv_per_distr_i_2.index = range(len(pv_per_distr_i_2))
676
677
                # delete empty grid districts
678
                index_names = pv_per_distr_i_2[
679
                    pv_per_distr_i_2["installed capacity in kW"].isna()
680
                ].index
681
                pv_per_distr_i_2.drop(index_names, inplace=True)
682
683
                if (
684
                    pv_per_distr_i_2["installed capacity in kW"].sum()
685
                    > rest_cap
686
                ):
687
                    scale_factor = (
688
                        rest_cap
689
                        / pv_per_distr_i_2["installed capacity in kW"].sum()
690
                    )
691
                    pv_per_distr_i_2["installed capacity in kW"] = (
692
                        pv_per_distr_i_2["installed capacity in kW"]
693
                        * scale_factor
694
                    )
695
696
                    ###
697
                    print(
698
                        "Residual capacity got distributed via scaling "
699
                        "factor "
700
                        + str(scale_factor)
701
                        + " to remaining potential areas 'Road & Railway' "
702
                        "and 'Agriculture'."
703
                    )
704
705
                pv_per_distr_i = pd.concat(
706
                    [pv_per_distr_i, pv_per_distr_i_2], ignore_index=True
707
                )
708
709
            # assign grid level to pv_per_distr
710
            v_lvl = pd.Series(dtype=int, index=pv_per_distr_i.index)
711
            for index, distr in pv_per_distr_i.iterrows():
712
                if distr["installed capacity in kW"] > 5500:  # > 5 MW
713
                    v_lvl[index] = 4
714
                else:
715
                    v_lvl[index] = 5
716
            pv_per_distr_i["voltage_level"] = v_lvl
717
718
            # new overall installed capacity
719
            total_pv_power = (
720
                pv_rora_i["installed capacity in kW"].sum()
721
                + pv_agri_i["installed capacity in kW"].sum()
722
                + pv_exist_i["installed capacity in kW"].sum()
723
                + pv_per_distr_i["installed capacity in kW"].sum()
724
            )
725
726
            ###
727
            print(
728
                "Total installed capacity of PV farms: "
729
                + str(total_pv_power / 1000)
730
                + " MW"
731
            )
732
            print(" ")
733
734
        pv_rora_i = pv_rora_i[pv_rora_i["installed capacity in kW"] > 0]
735
        pv_agri_i = pv_agri_i[pv_agri_i["installed capacity in kW"] > 0]
736
        pv_exist_i = pv_exist_i[pv_exist_i["installed capacity in kW"] > 0]
737
        pv_per_distr_i = pv_per_distr_i[
738
            pv_per_distr_i["installed capacity in kW"] > 0
739
        ]
740
741
        return pv_rora_i, pv_agri_i, pv_exist_i, pv_per_distr_i
742
743
    def keep_existing_pv(mastr, con):
744
        pv_exist = mastr[
745
            [
746
                "geometry",
747
                "installed capacity in kW",
748
                "voltage_level",
749
            ]
750
        ]
751
        pv_exist.rename(columns={"geometry": "centroid"}, inplace=True)
752
        pv_exist = gpd.GeoDataFrame(pv_exist, geometry="centroid", crs=3035)
753
754
        # German states
755
        sql = "SELECT geometry as geom, gf FROM boundaries.vg250_lan"
756
        land = gpd.GeoDataFrame.from_postgis(sql, con).to_crs(3035)
757
        land = land[(land["gf"] != 1) & (land["gf"] != 2)]
758
        land = land.unary_union
759
        pv_exist = gpd.clip(pv_exist, land)
760
761
        return pv_exist
762
763
    def run_methodology(
764
        con=db.engine(),
765
        pow_per_area=0.04,
766
        join_buffer=10,
767
        max_dist_hv=20000,
768
        show_map=False,
769
    ):
770
        """Execute methodology to distribute pv ground mounted.
771
772
         Parameters
773
         ----------
774
         con:
775
             Connection to database
776
         pow_per_area: int, default 0.4
777
             Assumption for areas of existing pv farms and power of new built
778
             pv farms depending on area in kW/m²
779
         join_buffer : int, default 10
780
             Maximum distance for joining of potential areas (only small ones
781
             to big ones) in m
782
         max_dist_hv : int, default 20000
783
             Assumption for maximum distance of park with hv-power to next
784
             substation in m
785
        show_map:  boolean
786
            Optional creation of map to show distribution of installed
787
            capacity
788
789
        """
790
        ###
791
        print(" ")
792
        print("MaStR-Data")
793
        print(" ")
794
795
        # MaStR-data: existing PV farms
796
        mastr = mastr_existing_pv(pow_per_area)
797
798
        ###
799
        print(" ")
800
        print("potential area")
801
        print(" ")
802
803
        # database-data: potential areas for new PV farms
804
        potentials_rora, potentials_agri = potential_areas(con, join_buffer)
805
806
        ###
807
        print(" ")
808
        print("select potentials area")
809
        print(" ")
810
811
        # select potential areas with existing PV farms to build new PV farms
812
        pv_rora, mastr = select_pot_areas(mastr, potentials_rora)
813
        pv_agri, mastr = select_pot_areas(mastr, potentials_agri)
814
815
        ###
816
        print(" ")
817
        print(
818
            "build PV parks where there is PV ground mounted already "
819
            "(-> MaStR) on potential area"
820
        )
821
        print(" ")
822
823
        # build new PV farms
824
        pv_rora = build_pv(pv_rora, pow_per_area)
825
        pv_agri = build_pv(pv_agri, pow_per_area)
826
827
        # keep the existing pv_farms that don't intercept potential areas
828
        exist = keep_existing_pv(mastr, con)
829
830
        ###
831
        print(" ")
832
        print("adapt grid level of PV parks")
833
        print(" ")
834
835
        # adapt grid level to new farms
836
        rora = adapt_grid_level(pv_rora, max_dist_hv, con)
837
        agri = adapt_grid_level(pv_agri, max_dist_hv, con)
838
839
        ###
840
        print(" ")
841
        print(
842
            "check target value and build more PV parks on potential area if "
843
            "necessary"
844
        )
845
        print(" ")
846
847
        # initialize final dataframe
848
        pv_rora = gpd.GeoDataFrame()
849
        pv_agri = gpd.GeoDataFrame()
850
        pv_exist = gpd.GeoDataFrame()
851
        pv_per_distr = gpd.GeoDataFrame()
852
853
        # 1) scenario: eGon2035
854
        if (
855
            "eGon2035"
856
            in egon.data.config.settings()["egon-data"]["--scenarios"]
857
        ):
858
            ###
859
            print(" ")
860
            print("scenario: eGon2035")
861
            print(" ")
862
863
            # German states
864
            sql = "SELECT geometry as geom, nuts FROM boundaries.vg250_lan"
865
            states = gpd.GeoDataFrame.from_postgis(sql, con)
866
867
            # assumption for target value of installed capacity
868
            sql = (
869
                "SELECT capacity,scenario_name,nuts FROM "
870
                "supply.egon_scenario_capacities WHERE carrier='solar'"
871
            )
872
            target = pd.read_sql(sql, con)
873
            target = target[target["scenario_name"] == "eGon2035"]
874
            nuts = np.unique(target["nuts"])
875
876
            # prepare selection per state
877
            rora = rora.set_geometry("centroid")
878
            agri = agri.set_geometry("centroid")
879
            potentials_rora = potentials_rora.set_geometry("geom")
880
            potentials_agri = potentials_agri.set_geometry("geom")
881
882
            # check target value per state
883
            for i in nuts:
884
                target_power = (
885
                    target[target["nuts"] == i]["capacity"].iloc[0] * 1000
886
                )
887
888
                ###
889
                land = target[target["nuts"] == i]["nuts"].iloc[0]
890
                print(" ")
891
                print("Bundesland (NUTS): " + land)
892
                print("target power: " + str(target_power / 1000) + " MW")
893
894
                # select state
895
                state = states[states["nuts"] == i]
896
                state = state.to_crs(3035)
897
898
                # select PVs in state
899
                rora_i = gpd.sjoin(rora, state)
900
                agri_i = gpd.sjoin(agri, state)
901
                exist_i = gpd.sjoin(exist, state)
902
                rora_i.drop("index_right", axis=1, inplace=True)
903
                agri_i.drop("index_right", axis=1, inplace=True)
904
                exist_i.drop("index_right", axis=1, inplace=True)
905
                rora_i.drop_duplicates(inplace=True)
906
                agri_i.drop_duplicates(inplace=True)
907
                exist_i.drop_duplicates(inplace=True)
908
909
                # select potential areas in state
910
                potentials_rora_i = gpd.sjoin(potentials_rora, state)
911
                potentials_agri_i = gpd.sjoin(potentials_agri, state)
912
                potentials_rora_i.drop("index_right", axis=1, inplace=True)
913
                potentials_agri_i.drop("index_right", axis=1, inplace=True)
914
                potentials_rora_i.drop_duplicates(inplace=True)
915
                potentials_agri_i.drop_duplicates(inplace=True)
916
917
                # check target value and adapt installed capacity if necessary
918
                rora_i, agri_i, exist_i, distr_i = check_target(
919
                    rora_i,
920
                    agri_i,
921
                    exist_i,
922
                    potentials_rora_i,
923
                    potentials_agri_i,
924
                    target_power,
925
                    pow_per_area,
926
                    con,
927
                )
928
929
                if len(distr_i) > 0:
930
                    distr_i["nuts"] = target[target["nuts"] == i]["nuts"].iloc[
931
                        0
932
                    ]
933
934
                # ### examination of built PV parks per state
935
                rora_i_mv = rora_i[rora_i["voltage_level"] == 5]
936
                rora_i_hv = rora_i[rora_i["voltage_level"] == 4]
937
                agri_i_mv = agri_i[agri_i["voltage_level"] == 5]
938
                agri_i_hv = agri_i[agri_i["voltage_level"] == 4]
939
                print(
940
                    "eGon2035: Examination of voltage level per federal state:"
941
                )
942
                print("a) PVs on potential areas Road & Railway: ")
943
                print(
944
                    "Total installed capacity: "
945
                    + str(rora_i["installed capacity in kW"].sum() / 1000)
946
                    + " MW"
947
                )
948
                print("Number of PV farms: " + str(len(rora_i)))
949
                print(" - thereof MV: " + str(len(rora_i_mv)))
950
                print(" - thereof HV: " + str(len(rora_i_hv)))
951
                print("b) PVs on potential areas Agriculture: ")
952
                print(
953
                    "Total installed capacity: "
954
                    + str(agri_i["installed capacity in kW"].sum() / 1000)
955
                    + " MW"
956
                )
957
                print("Number of PV farms: " + str(len(agri_i)))
958
                print(" - thereof MV: " + str(len(agri_i_mv)))
959
                print(" - dthereof HV: " + str(len(agri_i_hv)))
960
                print("c) Existing PVs not in potential areas: ")
961
                print("Number of PV farms: " + str(len(exist_i)))
962
                print("d) PVs on additional potential areas per MV-District: ")
963
                if len(distr_i) > 0:
964
                    distr_i_mv = distr_i[distr_i["voltage_level"] == 5]
965
                    distr_i_hv = distr_i[distr_i["voltage_level"] == 4]
966
                    print(
967
                        "Total installed capacity: "
968
                        + str(distr_i["installed capacity in kW"].sum() / 1000)
969
                        + " MW"
970
                    )
971
                    print("Number of PV farms: " + str(len(distr_i)))
972
                    print(" - thereof MV: " + str(len(distr_i_mv)))
973
                    print(" - thereof HV: " + str(len(distr_i_hv)))
974
                else:
975
                    print(" -> No additional expansion necessary")
976
                print(" ")
977
978
                pv_rora = pv_rora.append(rora_i)
979
                pv_agri = pv_agri.append(agri_i)
980
                pv_exist = pv_exist.append(exist_i)
981
                if len(distr_i) > 0:
982
                    pv_per_distr = pd.concat([pv_per_distr, distr_i])
983
984
        if (
985
            "eGon100RE"
986
            in egon.data.config.settings()["egon-data"]["--scenarios"]
987
        ):
988
            # 2) scenario: eGon100RE
989
990
            # assumption for target value of installed capacity in Germany per
991
            # scenario
992
            sql = (
993
                "SELECT capacity,scenario_name FROM "
994
                "supply.egon_scenario_capacities WHERE carrier='solar'"
995
            )
996
            target_power = pd.read_sql(sql, con)
997
            target_power = target_power[
998
                target_power["scenario_name"] == "eGon100RE"
999
            ]
1000
            target_power = target_power["capacity"].sum() * 1000
1001
1002
            ###
1003
            print(" ")
1004
            print("scenario: eGon100RE")
1005
            print("target power: " + str(target_power) + " kW")
1006
            print(" ")
1007
1008
            # check target value and adapt installed capacity if necessary
1009
            (
1010
                pv_rora_100RE,
1011
                pv_agri_100RE,
1012
                pv_exist_100RE,
1013
                pv_per_distr_100RE,
1014
            ) = check_target(
1015
                rora,
1016
                agri,
1017
                exist,
1018
                potentials_rora,
1019
                potentials_agri,
1020
                target_power,
1021
                pow_per_area,
1022
                con,
1023
            )
1024
1025
        # ### create map to show distribution of installed capacity
1026
        if show_map == True:
1027
            # 1) eGon2035
1028
1029
            # get MV grid districts
1030
            sql = "SELECT bus_id, geom FROM grid.egon_mv_grid_district"
1031
            distr = gpd.GeoDataFrame.from_postgis(sql, con)
1032
            distr = distr.set_index("bus_id")
1033
1034
            # assign pv_per_distr-power to districts
1035
            distr["capacity"] = pd.Series()
1036
            for index, row in distr.iterrows():
1037
                if index in np.unique(pv_per_distr["grid_district"]):
1038
                    pv = pv_per_distr[pv_per_distr["grid_district"] == index]
1039
                    x = pv["installed capacity in kW"].iloc[0]
1040
                    distr["capacity"].loc[index] = x
1041
                else:
1042
                    distr["capacity"].loc[index] = 0
1043
            distr["capacity"] = distr["capacity"] / 1000
1044
1045
            # add pv_rora- and pv_agri-power to district
1046
            pv_rora = pv_rora.set_geometry("centroid")
1047
            pv_agri = pv_agri.set_geometry("centroid")
1048
            overlay_rora = gpd.sjoin(pv_rora, distr)
1049
            overlay_agri = gpd.sjoin(pv_agri, distr)
1050
1051
            for index, row in distr.iterrows():
1052
                o_rora = overlay_rora[overlay_rora["index_right"] == index]
1053
                o_agri = overlay_agri[overlay_agri["index_right"] == index]
1054
                cap_rora = o_rora["installed capacity in kW"].sum() / 1000
1055
                cap_agri = o_agri["installed capacity in kW"].sum() / 1000
1056
            distr["capacity"].loc[index] = (
1057
                distr["capacity"].loc[index] + cap_rora + cap_agri
0 ignored issues
show
introduced by
The variable index does not seem to be defined in case the for loop on line 1036 is not entered. Are you sure this can never be the case?
Loading history...
introduced by
The variable cap_agri does not seem to be defined in case the for loop on line 1051 is not entered. Are you sure this can never be the case?
Loading history...
introduced by
The variable cap_rora does not seem to be defined in case the for loop on line 1051 is not entered. Are you sure this can never be the case?
Loading history...
1058
            )
1059
1060
            from matplotlib import pyplot as plt
1061
1062
            fig, ax = plt.subplots(1, 1)
1063
            distr.boundary.plot(linewidth=0.2, ax=ax, color="black")
1064
            distr.plot(
1065
                ax=ax,
1066
                column="capacity",
1067
                cmap="magma_r",
1068
                legend=True,
1069
                legend_kwds={
1070
                    "label": "Installed capacity in MW",
1071
                    "orientation": "vertical",
1072
                },
1073
            )
1074
            plt.savefig("pv_per_distr_map_eGon2035.png", dpi=300)
1075
1076
            # 2) eGon100RE
1077
1078
            # get MV grid districts
1079
            sql = "SELECT bus_id, geom FROM grid.egon_mv_grid_district"
1080
            distr = gpd.GeoDataFrame.from_postgis(sql, con)
1081
            distr = distr.set_index("bus_id")
1082
1083
            # assign pv_per_distr-power to districts
1084
            distr["capacity"] = pd.Series()
1085
            for index, row in distr.iterrows():
1086
                if index in np.unique(pv_per_distr_100RE["grid_district"]):
0 ignored issues
show
introduced by
The variable pv_per_distr_100RE does not seem to be defined in case "eGon100RE" in SubscriptNode on line 985 is False. Are you sure this can never be the case?
Loading history...
1087
                    pv = pv_per_distr_100RE[
1088
                        pv_per_distr_100RE["grid_district"] == index
1089
                    ]
1090
                    x = pv["installed capacity in kW"].iloc[0]
1091
                    distr["capacity"].loc[index] = x
1092
                else:
1093
                    distr["capacity"].loc[index] = 0
1094
            distr["capacity"] = distr["capacity"] / 1000
1095
1096
            # add pv_rora- and pv_agri-power to district
1097
            pv_rora_100RE = pv_rora_100RE.set_geometry("centroid")
0 ignored issues
show
introduced by
The variable pv_rora_100RE does not seem to be defined in case "eGon100RE" in SubscriptNode on line 985 is False. Are you sure this can never be the case?
Loading history...
1098
            pv_agri_100RE = pv_agri_100RE.set_geometry("centroid")
0 ignored issues
show
introduced by
The variable pv_agri_100RE does not seem to be defined in case "eGon100RE" in SubscriptNode on line 985 is False. Are you sure this can never be the case?
Loading history...
1099
            overlay_rora = gpd.sjoin(pv_rora_100RE, distr)
1100
            overlay_agri = gpd.sjoin(pv_agri_100RE, distr)
1101
1102
            for index, row in distr.iterrows():
1103
                o_rora = overlay_rora[overlay_rora["index_right"] == index]
1104
                o_agri = overlay_agri[overlay_agri["index_right"] == index]
1105
                cap_rora = o_rora["installed capacity in kW"].sum() / 1000
1106
                cap_agri = o_agri["installed capacity in kW"].sum() / 1000
1107
            distr["capacity"].loc[index] = (
1108
                distr["capacity"].loc[index] + cap_rora + cap_agri
1109
            )
1110
1111
            from matplotlib import pyplot as plt
1112
1113
            fig, ax = plt.subplots(1, 1)
1114
            distr.boundary.plot(linewidth=0.2, ax=ax, color="black")
1115
            distr.plot(
1116
                ax=ax,
1117
                column="capacity",
1118
                cmap="magma_r",
1119
                legend=True,
1120
                legend_kwds={
1121
                    "label": "Installed capacity in MW",
1122
                    "orientation": "vertical",
1123
                },
1124
            )
1125
            plt.savefig("pv_per_distr_map_eGon100RE.png", dpi=300)
1126
1127
        pv_rora_100RE = pv_rora_100RE[
1128
            pv_rora_100RE["installed capacity in kW"] > 0
1129
        ]
1130
        pv_agri_100RE = pv_agri_100RE[
1131
            pv_agri_100RE["installed capacity in kW"] > 0
1132
        ]
1133
        pv_per_distr_100RE = pv_per_distr_100RE[
1134
            pv_per_distr_100RE["installed capacity in kW"] > 0
1135
        ]
1136
1137
        return (
1138
            pv_rora,
1139
            pv_agri,
1140
            pv_exist,
1141
            pv_per_distr,
1142
            pv_rora_100RE,
1143
            pv_agri_100RE,
1144
            pv_exist_100RE,
0 ignored issues
show
introduced by
The variable pv_exist_100RE does not seem to be defined in case "eGon100RE" in SubscriptNode on line 985 is False. Are you sure this can never be the case?
Loading history...
1145
            pv_per_distr_100RE,
1146
        )
1147
1148
    def insert_pv_parks(
1149
        pv_rora, pv_agri, pv_exist, pv_per_distr, scenario_name
1150
    ):
1151
        """Write to database.
1152
1153
        Parameters
1154
        ----------
1155
        pv_rora : gpd.GeoDataFrame()
1156
            Pv parks on selected potential areas of raod and railway
1157
        pv_agri : gpd.GeoDataFrame()
1158
            Pv parks on selected potential areas of raod and railway
1159
        pv_exist : gpd.GeoDataFrame()
1160
            Existing Pv parks on selected areas
1161
        pv_per_distr: gpd.GeoDataFrame()
1162
            Additionally built pv parks on potential areas per mv grid
1163
            district
1164
        scenario_name:
1165
            Scenario name of calculation
1166
1167
        """
1168
1169
        # prepare dataframe for integration in supply.egon_power_plants
1170
1171
        pv_parks = pd.concat(
1172
            [pv_rora, pv_agri, pv_exist, pv_per_distr], ignore_index=True
1173
        )
1174
        pv_parks["el_capacity"] = pv_parks["installed capacity in kW"] / 1000
1175
        pv_parks.rename(columns={"centroid": "geometry"}, inplace=True)
1176
        pv_parks = gpd.GeoDataFrame(pv_parks, geometry="geometry", crs=3035)
1177
        pv_parks = pv_parks[["el_capacity", "voltage_level", "geometry"]]
1178
1179
        # integration in supply.egon_power_plants
1180
1181
        con = db.engine()
1182
1183
        # maximum ID in egon_power_plants
1184
        sql = "SELECT MAX(id) FROM supply.egon_power_plants"
1185
        max_id = pd.read_sql(sql, con)
1186
        max_id = max_id["max"].iat[0]
1187
        if max_id is None:
1188
            max_id = 1
1189
1190
        pv_park_id = max_id + 1
1191
1192
        # copy relevant columns from pv_parks
1193
        insert_pv_parks = pv_parks[
1194
            ["el_capacity", "voltage_level", "geometry"]
1195
        ]
1196
        insert_pv_parks = insert_pv_parks.set_geometry("geometry")
1197
        insert_pv_parks["voltage_level"] = insert_pv_parks[
1198
            "voltage_level"
1199
        ].apply(int)
1200
1201
        # set static column values
1202
        insert_pv_parks["carrier"] = "solar"
1203
        insert_pv_parks["scenario"] = scenario_name
1204
1205
        # change name and crs of geometry column
1206
        insert_pv_parks.set_crs(epsg=3035, allow_override=True, inplace=True)
1207
        insert_pv_parks = (
1208
            insert_pv_parks.rename({"geometry": "geom"}, axis=1)
1209
            .set_geometry("geom")
1210
            .to_crs(4326)
1211
        )
1212
1213
        # reset index
1214
        insert_pv_parks.index = pd.RangeIndex(
1215
            start=pv_park_id, stop=pv_park_id + len(insert_pv_parks), name="id"
1216
        )
1217
1218
        # insert into database
1219
        insert_pv_parks.reset_index().to_postgis(
1220
            "egon_power_plants",
1221
            schema="supply",
1222
            con=db.engine(),
1223
            if_exists="append",
1224
        )
1225
1226
        return pv_parks
1227
1228
    # ########################################################################
1229
1230
    # execute methodology
1231
1232
    (
1233
        pv_rora,
1234
        pv_agri,
1235
        pv_exist,
1236
        pv_per_distr,
1237
        pv_rora_100RE,
1238
        pv_agri_100RE,
1239
        pv_exist_100RE,
1240
        pv_per_distr_100RE,
1241
    ) = run_methodology(
1242
        con=db.engine(),
1243
        pow_per_area=0.04,
1244
        join_buffer=10,
1245
        max_dist_hv=20000,
1246
        show_map=False,
1247
    )
1248
1249
    # ### examination of results
1250
    if len(pv_per_distr) > 0:
1251
        pv_per_distr_mv = pv_per_distr[pv_per_distr["voltage_level"] == 5]
1252
        pv_per_distr_hv = pv_per_distr[pv_per_distr["voltage_level"] == 4]
1253
    if len(pv_rora) > 0:
1254
        pv_rora_mv = pv_rora[pv_rora["voltage_level"] == 5]
1255
        pv_rora_hv = pv_rora[pv_rora["voltage_level"] == 4]
1256
        pv_agri_mv = pv_agri[pv_agri["voltage_level"] == 5]
1257
        pv_agri_hv = pv_agri[pv_agri["voltage_level"] == 4]
1258
1259
        print(" ")
1260
        print("eGon2035: Examination of overall voltage levels:")
1261
        print("a) PVs on potential areas Road & Railway: ")
1262
        print(
1263
            "Total installed capacity: "
1264
            + str(pv_rora["installed capacity in kW"].sum() / 1000)
1265
            + " MW"
1266
        )
1267
        print("Number of PV farms: " + str(len(pv_rora)))
1268
        print(" - thereof MV: " + str(len(pv_rora_mv)))
1269
        print(" - thereof HV: " + str(len(pv_rora_hv)))
1270
        print("b) PVs on potential areas Agriculture: ")
1271
        print(
1272
            "Total installed capacity: "
1273
            + str(pv_agri["installed capacity in kW"].sum() / 1000)
1274
            + " MW"
1275
        )
1276
        print("Number of PV farms: " + str(len(pv_agri)))
1277
        print(" - thereof MV: " + str(len(pv_agri_mv)))
1278
        print(" - thereof HV: " + str(len(pv_agri_hv)))
1279
        print("c) Existing PVs not in potential areas: ")
1280
        print("Number of PV farms: " + str(len(pv_exist)))
1281
        print("d) PVs on additional potential areas per MV-District: ")
1282
        if len(pv_per_distr) > 0:
1283
            print(
1284
                "Total installed capacity: "
1285
                + str(pv_per_distr["installed capacity in kW"].sum() / 1000)
1286
                + " MW"
1287
            )
1288
            print("Number of PV farms: " + str(len(pv_per_distr)))
1289
            print(" - thereof MV: " + str(len(pv_per_distr_mv)))
0 ignored issues
show
introduced by
The variable pv_per_distr_mv does not seem to be defined in case len(pv_per_distr) > 0 on line 1250 is False. Are you sure this can never be the case?
Loading history...
1290
            print(" - thereof HV: " + str(len(pv_per_distr_hv)))
0 ignored issues
show
introduced by
The variable pv_per_distr_hv does not seem to be defined in case len(pv_per_distr) > 0 on line 1250 is False. Are you sure this can never be the case?
Loading history...
1291
        else:
1292
            print(" -> No additional expansion needed")
1293
        print(" ")
1294
        ###
1295
1296
    # save to DB
1297
    if "eGon2035" in egon.data.config.settings()["egon-data"]["--scenarios"]:
1298
        if (
1299
            pv_rora["installed capacity in kW"].sum() > 0
1300
            or pv_agri["installed capacity in kW"].sum() > 0
1301
            or pv_per_distr["installed capacity in kW"].sum() > 0
1302
            or pv_exist["installed capacity in kW"].sum() > 0
1303
        ):
1304
            pv_parks = insert_pv_parks(
1305
                pv_rora, pv_agri, pv_exist, pv_per_distr, "eGon2035"
1306
            )
1307
1308
        else:
1309
            pv_parks = gpd.GeoDataFrame()
1310
    else:
1311
        pv_parks = gpd.GeoDataFrame()
1312
1313
    if "eGon100RE" in egon.data.config.settings()["egon-data"]["--scenarios"]:
1314
        if (
1315
            pv_rora_100RE["installed capacity in kW"].sum() > 0
1316
            or pv_agri_100RE["installed capacity in kW"].sum() > 0
1317
            or pv_per_distr_100RE["installed capacity in kW"].sum() > 0
1318
            or pv_exist_100RE["installed capacity in kW"].sum() > 0
1319
        ):
1320
            pv_parks_100RE = insert_pv_parks(
1321
                pv_rora_100RE,
1322
                pv_agri_100RE,
1323
                pv_exist_100RE,
1324
                pv_per_distr_100RE,
1325
                "eGon100RE",
1326
            )
1327
1328
        else:
1329
            pv_parks_100RE = gpd.GeoDataFrame()
1330
    else:
1331
        pv_parks_100RE = gpd.GeoDataFrame()
1332
1333
    return pv_parks, pv_parks_100RE
1334