Passed
Pull Request — dev (#848)
by
unknown
01:30
created

pv_rooftop_per_mv_grid()   A

Complexity

Conditions 1

Size

Total Lines 14
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 14
rs 10
c 0
b 0
f 0
cc 1
nop 0
1
"""The module containing all code dealing with pv rooftop distribution.
2
"""
3
import geopandas as gpd
4
import pandas as pd
5
6
from egon.data import config, db
7
from egon.data.datasets.scenario_parameters import get_sector_parameters
8
9
10
def pv_rooftop_per_mv_grid():
11
    """Execute pv rooftop distribution method per scenario
12
13
    Returns
14
    -------
15
    None.
16
17
    """
18
19
    pv_rooftop_per_mv_grid_and_scenario(
20
        scenario="eGon2035", level="federal_state"
21
    )
22
23
    pv_rooftop_per_mv_grid_and_scenario(scenario="eGon100RE", level="national")
24
25
26
def pv_rooftop_per_mv_grid_and_scenario(scenario, level):
27
    """Intergate solar rooftop per mv grid district
28
29
    The target capacity is distributed to the mv grid districts linear to
30
    the residential and service electricity demands.
31
32
    Parameters
33
    ----------
34
    scenario : str, optional
35
        Name of the scenario
36
    level : str, optional
37
        Choose level of target values.
38
39
    Returns
40
    -------
41
    None.
42
43
    """
44
    # Select sources and targets from dataset configuration
45
    sources = config.datasets()["solar_rooftop"]["sources"]
46
    targets = config.datasets()["solar_rooftop"]["targets"]
47
48
    # Delete existing rows
49
    db.execute_sql(
50
        f"""
51
        DELETE FROM {targets['generators']['schema']}.
52
        {targets['generators']['table']}
53
        WHERE carrier IN ('solar_rooftop')
54
        AND scn_name = '{scenario}'
55
        AND bus IN (SELECT bus_id FROM
56
                    {sources['egon_mv_grid_district']['schema']}.
57
                    {sources['egon_mv_grid_district']['table']}            )
58
        """
59
    )
60
61
    db.execute_sql(
62
        f"""
63
        DELETE FROM {targets['generator_timeseries']['schema']}.
64
        {targets['generator_timeseries']['table']}
65
        WHERE scn_name = '{scenario}'
66
        AND generator_id NOT IN (
67
            SELECT generator_id FROM
68
            grid.egon_etrago_generator
69
            WHERE scn_name = '{scenario}')
70
        """
71
    )
72
73
    # Select demand per mv grid district
74
    demand = db.select_dataframe(
75
        f"""
76
         SELECT SUM(demand) as demand,
77
         b.bus_id, vg250_lan
78
         FROM {sources['electricity_demand']['schema']}.
79
         {sources['electricity_demand']['table']} a
80
         JOIN {sources['map_zensus_grid_districts']['schema']}.
81
         {sources['map_zensus_grid_districts']['table']} b
82
         ON a.zensus_population_id = b.zensus_population_id
83
         JOIN {sources['map_grid_boundaries']['schema']}.
84
         {sources['map_grid_boundaries']['table']} c
85
         ON c.bus_id = b.bus_id
86
         WHERE scenario = '{scenario}'
87
         GROUP BY (b.bus_id, vg250_lan)
88
         """
89
    )
90
91
    # Distribute to mv grids per federal state or Germany
92
    if level == "federal_state":
93
        targets_per_federal_state = db.select_dataframe(
94
            f"""
95
            SELECT DISTINCT ON (gen) capacity, gen
96
            FROM {sources['scenario_capacities']['schema']}.
97
            {sources['scenario_capacities']['table']} a
98
            JOIN {sources['federal_states']['schema']}.
99
            {sources['federal_states']['table']} b
100
            ON a.nuts = b.nuts
101
            WHERE carrier = 'solar_rooftop'
102
            AND scenario_name = '{scenario}'
103
            """,
104
            index_col="gen",
105
        )
106
107
        demand["share_federal_state"] = demand.groupby(
108
            "vg250_lan"
109
        ).demand.apply(lambda grp: grp / grp.sum())
110
111
        demand["target_federal_state"] = targets_per_federal_state.capacity[
112
            demand.vg250_lan
113
        ].values
114
115
        demand.set_index("bus_id", inplace=True)
116
117
        capacities = demand["share_federal_state"].mul(
118
            demand["target_federal_state"]
119
        )
120
    else:
121
122
        target = db.select_dataframe(
123
            f"""
124
            SELECT capacity
125
            FROM {sources['scenario_capacities']['schema']}.
126
            {sources['scenario_capacities']['table']} a
127
            WHERE carrier = 'solar_rooftop'
128
            AND scenario_name = '{scenario}'
129
            """
130
        ).capacity[0]
131
132
        demand["share_country"] = demand.demand / demand.demand.sum()
133
134
        demand.set_index("bus_id", inplace=True)
135
136
        capacities = demand["share_country"].mul(target)
137
138
    # Select next id value
139
    new_id = db.next_etrago_id("generator")
140
141
    # Store data in dataframe
142
    pv_rooftop = pd.DataFrame(
143
        data={
144
            "scn_name": scenario,
145
            "carrier": "solar_rooftop",
146
            "bus": demand.index,
147
            "p_nom": capacities,
148
            "generator_id": range(new_id, new_id + len(demand)),
149
        }
150
    )
151
152
    # Select feedin timeseries
153
    weather_cells = db.select_geodataframe(
154
        f"""
155
            SELECT w_id, geom
156
            FROM {sources['weather_cells']['schema']}.
157
                {sources['weather_cells']['table']}
158
            """,
159
        index_col="w_id",
160
    )
161
162
    mv_grid_districts = db.select_geodataframe(
163
        f"""
164
        SELECT bus_id as bus_id, ST_Centroid(geom) as geom
165
        FROM {sources['egon_mv_grid_district']['schema']}.
166
        {sources['egon_mv_grid_district']['table']}
167
        """,
168
        index_col="bus_id",
169
    )
170
171
    # Map centroid of mv grids to weather cells
172
    join = gpd.sjoin(weather_cells, mv_grid_districts)[["index_right"]]
173
174
    feedin = db.select_dataframe(
175
        f"""
176
            SELECT w_id, feedin
177
            FROM {sources['solar_feedin']['schema']}.
178
                {sources['solar_feedin']['table']}
179
            WHERE carrier = 'pv'
180
            AND weather_year = 2011
181
            """,
182
        index_col="w_id",
183
    )
184
185
    # Create timeseries only for mv grid districts with pv rooftop
186
    join = join[join.index_right.isin(pv_rooftop.bus)]
187
188
    timeseries = pd.DataFrame(
189
        data={
190
            "scn_name": scenario,
191
            "temp_id": 1,
192
            "p_max_pu": feedin.feedin[join.index].values,
193
            "generator_id": pv_rooftop.generator_id[join.index_right].values,
194
        }
195
    ).set_index("generator_id")
196
197
    pv_rooftop = pv_rooftop.set_index("generator_id")
198
    pv_rooftop["marginal_cost"] = get_sector_parameters(
199
        "electricity", scenario
200
    )["marginal_cost"]["solar"]
201
202
    # Insert data to database
203
    pv_rooftop.to_sql(
204
        targets["generators"]["table"],
205
        schema=targets["generators"]["schema"],
206
        if_exists="append",
207
        con=db.engine(),
208
    )
209
210
    timeseries.to_sql(
211
        targets["generator_timeseries"]["table"],
212
        schema=targets["generator_timeseries"]["schema"],
213
        if_exists="append",
214
        con=db.engine(),
215
    )
216