Passed
Pull Request — dev (#1170)
by
unknown
05:05
created

data.datasets.chp_etrago.insert_scenario()   B

Complexity

Conditions 1

Size

Total Lines 265
Code Lines 144

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 144
dl 0
loc 265
rs 7
c 0
b 0
f 0
cc 1
nop 1

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
The central module containing all code dealing with chp for eTraGo.
3
"""
4
5
import geopandas as gpd
6
import pandas as pd
7
8
from egon.data import config, db
9
from egon.data.datasets import Dataset
10
from egon.data.datasets.etrago_setup import link_geom_from_buses
11
from egon.data.datasets.scenario_parameters import get_sector_parameters
12
13
14
class ChpEtrago(Dataset):
15
    """
16
    Collect data related to combined heat and power plants for the eTraGo tool
17
18
    This dataset collects data for combined heat and power plants and puts it into a format that
19
    is needed for the transmission grid optimisation within the tool eTraGo.
20
    This data is then writting into the corresponding tables that are read by eTraGo.
21
22
23
    *Dependencies*
24
      * :py:class:`HeatEtrago <egon.data.datasets.heat_etrago.HeatEtrago>`
25
      * :py:class:`Chp <egon.data.datasets.chp.Chp>`
26
27
    *Resulting tables*
28
      * :py:class:`grid.egon_etrago_link <egon.data.datasets.etrago_setup.EgonPfHvLink>` is extended
29
      * :py:class:`grid.egon_etrago_generator <egon.data.datasets.etrago_setup.EgonPfHvGenerator>` is extended
30
31
    """
32
33
    #:
34
    name: str = "ChpEtrago"
35
    #:
36
    version: str = "0.0.6"
37
38
    def __init__(self, dependencies):
39
        super().__init__(
40
            name=self.name,
41
            version=self.version,
42
            dependencies=dependencies,
43
            tasks=(insert),
44
        )
45
46
47
def insert_egon100re():
48
    sources = config.datasets()["chp_etrago"]["sources"]
49
50
    targets = config.datasets()["chp_etrago"]["targets"]
51
52
    db.execute_sql(
53
        f"""
54
        DELETE FROM {targets['link']['schema']}.{targets['link']['table']}
55
        WHERE carrier LIKE '%%CHP%%'
56
        AND scn_name = 'eGon100RE'
57
        AND bus0 IN
58
        (SELECT bus_id
59
         FROM {sources['etrago_buses']['schema']}.{sources['etrago_buses']['table']}
60
         WHERE scn_name = 'eGon100RE'
61
         AND country = 'DE')
62
        AND bus1 IN
63
        (SELECT bus_id
64
         FROM {sources['etrago_buses']['schema']}.{sources['etrago_buses']['table']}
65
         WHERE scn_name = 'eGon100RE'
66
         AND country = 'DE')
67
        """
68
    )
69
70
    # Select all CHP plants used in district heating
71
    chp_dh = db.select_dataframe(
72
        f"""
73
        SELECT electrical_bus_id, ch4_bus_id, a.carrier,
74
        SUM(el_capacity) AS el_capacity, SUM(th_capacity) AS th_capacity,
75
        c.bus_id as heat_bus_id
76
        FROM {sources['chp_table']['schema']}.
77
        {sources['chp_table']['table']} a
78
        JOIN {sources['district_heating_areas']['schema']}.
79
        {sources['district_heating_areas']['table']}  b
80
        ON a.district_heating_area_id = b.area_id
81
        JOIN grid.egon_etrago_bus c
82
        ON ST_Transform(ST_Centroid(b.geom_polygon), 4326) = c.geom
83
84
        WHERE a.scenario='eGon100RE'
85
        AND b.scenario = 'eGon100RE'
86
        AND c.scn_name = 'eGon100RE'
87
        AND c.carrier = 'central_heat'
88
        AND NOT district_heating_area_id IS NULL
89
        GROUP BY (
90
            electrical_bus_id, ch4_bus_id, a.carrier, c.bus_id)
91
        """
92
    )
93
94
    # Create geodataframes for gas CHP plants
95
    chp_el = link_geom_from_buses(
96
        gpd.GeoDataFrame(
97
            index=chp_dh.index,
98
            data={
99
                "scn_name": "eGon2035",
100
                "bus0": chp_dh.loc[:, "ch4_bus_id"].astype(int),
101
                "bus1": chp_dh.loc[:, "electrical_bus_id"].astype(int),
102
                "p_nom": chp_dh.loc[:, "el_capacity"],
103
                "carrier": "central_gas_CHP",
104
            },
105
        ),
106
        "eGon100RE",
107
    )
108
    # Set index
109
    chp_el["link_id"] = range(
110
        db.next_etrago_id("link"), len(chp_el) + db.next_etrago_id("link")
111
    )
112
113
    # Add marginal cost which is only VOM in case of gas chp
114
    chp_el["marginal_cost"] = get_sector_parameters("gas", "eGon100RE")[
115
        "marginal_cost"
116
    ]["chp_gas"]
117
118
    # Insert into database
119
    chp_el.to_postgis(
120
        targets["link"]["table"],
121
        schema=targets["link"]["schema"],
122
        con=db.engine(),
123
        if_exists="append",
124
    )
125
126
    #
127
    chp_heat = link_geom_from_buses(
128
        gpd.GeoDataFrame(
129
            index=chp_dh.index,
130
            data={
131
                "scn_name": "eGon100RE",
132
                "bus0": chp_dh.loc[:, "ch4_bus_id"].astype(int),
133
                "bus1": chp_dh.loc[:, "heat_bus_id"].astype(int),
134
                "p_nom": chp_dh.loc[:, "th_capacity"],
135
                "carrier": "central_gas_CHP_heat",
136
            },
137
        ),
138
        "eGon100RE",
139
    )
140
141
    chp_heat["link_id"] = range(
142
        db.next_etrago_id("link"), len(chp_heat) + db.next_etrago_id("link")
143
    )
144
145
    chp_heat.to_postgis(
146
        targets["link"]["table"],
147
        schema=targets["link"]["schema"],
148
        con=db.engine(),
149
        if_exists="append",
150
    )
151
152
153
def insert_scenario(scenario):
154
    sources = config.datasets()["chp_etrago"]["sources"]
155
156
    targets = config.datasets()["chp_etrago"]["targets"]
157
158
    db.execute_sql(
159
        f"""
160
        DELETE FROM {targets['link']['schema']}.{targets['link']['table']}
161
        WHERE carrier LIKE '%%CHP%%'
162
        AND scn_name = '{scenario}'
163
        AND bus0 IN
164
        (SELECT bus_id
165
         FROM {sources['etrago_buses']['schema']}.{sources['etrago_buses']['table']}
166
         WHERE scn_name = '{scenario}'
167
         AND country = 'DE')
168
        AND bus1 IN
169
        (SELECT bus_id
170
         FROM {sources['etrago_buses']['schema']}.{sources['etrago_buses']['table']}
171
         WHERE scn_name = '{scenario}'
172
         AND country = 'DE')
173
        """
174
    )
175
    db.execute_sql(
176
        f"""
177
        DELETE FROM {targets['generator']['schema']}.{targets['generator']['table']}
178
        WHERE carrier LIKE '%%CHP%%'
179
        AND scn_name = '{scenario}'
180
        """
181
    )
182
    # Select all CHP plants used in district heating
183
    chp_dh = db.select_dataframe(
184
        f"""
185
        SELECT electrical_bus_id, ch4_bus_id, a.carrier,
186
        SUM(el_capacity) AS el_capacity, SUM(th_capacity) AS th_capacity,
187
        c.bus_id as heat_bus_id
188
        FROM {sources['chp_table']['schema']}.
189
        {sources['chp_table']['table']} a
190
        JOIN {sources['district_heating_areas']['schema']}.
191
        {sources['district_heating_areas']['table']}  b
192
        ON a.district_heating_area_id = b.area_id
193
        JOIN grid.egon_etrago_bus c
194
        ON ST_Transform(ST_Centroid(b.geom_polygon), 4326) = c.geom
195
196
        WHERE a.scenario='{scenario}'
197
        AND b.scenario = '{scenario}'
198
        AND c.scn_name = '{scenario}'
199
        AND c.carrier = 'central_heat'
200
        AND NOT district_heating_area_id IS NULL
201
        GROUP BY (
202
            electrical_bus_id, ch4_bus_id, a.carrier, c.bus_id)
203
        """
204
    )
205
    # Divide into biomass and gas CHP which are modelled differently
206
    chp_link_dh = chp_dh[chp_dh.carrier == "gas"].index
207
    chp_generator_dh = chp_dh[chp_dh.carrier != "gas"].index
208
209
    # Create geodataframes for gas CHP plants
210
    chp_el = link_geom_from_buses(
211
        gpd.GeoDataFrame(
212
            index=chp_link_dh,
213
            data={
214
                "scn_name": scenario,
215
                "bus0": chp_dh.loc[chp_link_dh, "ch4_bus_id"].astype(int),
216
                "bus1": chp_dh.loc[chp_link_dh, "electrical_bus_id"].astype(
217
                    int
218
                ),
219
                "p_nom": chp_dh.loc[chp_link_dh, "el_capacity"],
220
                "carrier": "central_gas_CHP",
221
            },
222
        ),
223
        scenario,
224
    )
225
    # Set index
226
    chp_el["link_id"] = range(
227
        db.next_etrago_id("link"), len(chp_el) + db.next_etrago_id("link")
228
    )
229
230
    # Add marginal cost which is only VOM in case of gas chp
231
    chp_el["marginal_cost"] = get_sector_parameters("gas", scenario)[
232
        "marginal_cost"
233
    ]["chp_gas"]
234
235
    # Insert into database
236
    chp_el.to_postgis(
237
        targets["link"]["table"],
238
        schema=targets["link"]["schema"],
239
        con=db.engine(),
240
        if_exists="append",
241
    )
242
243
    #
244
    chp_heat = link_geom_from_buses(
245
        gpd.GeoDataFrame(
246
            index=chp_link_dh,
247
            data={
248
                "scn_name": scenario,
249
                "bus0": chp_dh.loc[chp_link_dh, "ch4_bus_id"].astype(int),
250
                "bus1": chp_dh.loc[chp_link_dh, "heat_bus_id"].astype(int),
251
                "p_nom": chp_dh.loc[chp_link_dh, "th_capacity"],
252
                "carrier": "central_gas_CHP_heat",
253
            },
254
        ),
255
        scenario,
256
    )
257
258
    chp_heat["link_id"] = range(
259
        db.next_etrago_id("link"), len(chp_heat) + db.next_etrago_id("link")
260
    )
261
262
    chp_heat.to_postgis(
263
        targets["link"]["table"],
264
        schema=targets["link"]["schema"],
265
        con=db.engine(),
266
        if_exists="append",
267
    )
268
269
    # Insert biomass, coal, oil and other CHP as generators
270
    # Create geodataframes for CHP plants
271
    chp_el_gen = pd.DataFrame(
272
        index=chp_generator_dh,
273
        data={
274
            "scn_name": scenario,
275
            "bus": chp_dh.loc[chp_generator_dh, "electrical_bus_id"].astype(
276
                int
277
            ),
278
            "p_nom": chp_dh.loc[chp_generator_dh, "el_capacity"],
279
            "carrier": chp_dh.loc[chp_generator_dh, "carrier"],
280
        },
281
    )
282
283
    chp_el_gen["generator_id"] = range(
284
        db.next_etrago_id("generator"),
285
        len(chp_el_gen) + db.next_etrago_id("generator"),
286
    )
287
288
    # Add marginal cost
289
    chp_el_gen["marginal_cost"] = (
290
        pd.Series(
291
            get_sector_parameters("electricity", scenario)["marginal_cost"]
292
        )
293
        .rename({"other_non_renewable": "others"})
294
        .loc[chp_el_gen["carrier"]]
295
    ).values
296
297
    chp_el_gen["carrier"] = (
298
        "central_" + chp_dh.loc[chp_generator_dh, "carrier"] + "_CHP"
299
    )
300
301
    chp_el_gen.to_sql(
302
        targets["generator"]["table"],
303
        schema=targets["generator"]["schema"],
304
        con=db.engine(),
305
        if_exists="append",
306
        index=False,
307
    )
308
309
    chp_heat_gen = pd.DataFrame(
310
        index=chp_generator_dh,
311
        data={
312
            "scn_name": scenario,
313
            "bus": chp_dh.loc[chp_generator_dh, "heat_bus_id"].astype(int),
314
            "p_nom": chp_dh.loc[chp_generator_dh, "th_capacity"],
315
            "carrier": "central_"
316
            + chp_dh.loc[chp_generator_dh, "carrier"]
317
            + "_CHP_heat",
318
        },
319
    )
320
321
    chp_heat_gen["generator_id"] = range(
322
        db.next_etrago_id("generator"),
323
        len(chp_heat_gen) + db.next_etrago_id("generator"),
324
    )
325
326
    chp_heat_gen.to_sql(
327
        targets["generator"]["table"],
328
        schema=targets["generator"]["schema"],
329
        con=db.engine(),
330
        if_exists="append",
331
        index=False,
332
    )
333
334
    chp_industry = db.select_dataframe(
335
        f"""
336
        SELECT electrical_bus_id, ch4_bus_id, carrier,
337
        SUM(el_capacity) AS el_capacity, SUM(th_capacity) AS th_capacity
338
        FROM {sources['chp_table']['schema']}.{sources['chp_table']['table']}
339
        WHERE scenario='{scenario}'
340
        AND district_heating_area_id IS NULL
341
        GROUP BY (electrical_bus_id, ch4_bus_id, carrier)
342
        """
343
    )
344
    chp_link_ind = chp_industry[chp_industry.carrier == "gas"].index
345
346
    chp_generator_ind = chp_industry[chp_industry.carrier != "gas"].index
347
348
    chp_el_ind = link_geom_from_buses(
349
        gpd.GeoDataFrame(
350
            index=chp_link_ind,
351
            data={
352
                "scn_name": scenario,
353
                "bus0": chp_industry.loc[chp_link_ind, "ch4_bus_id"].astype(
354
                    int
355
                ),
356
                "bus1": chp_industry.loc[
357
                    chp_link_ind, "electrical_bus_id"
358
                ].astype(int),
359
                "p_nom": chp_industry.loc[chp_link_ind, "el_capacity"],
360
                "carrier": "industrial_gas_CHP",
361
            },
362
        ),
363
        scenario,
364
    )
365
366
    chp_el_ind["link_id"] = range(
367
        db.next_etrago_id("link"), len(chp_el_ind) + db.next_etrago_id("link")
368
    )
369
370
    # Add marginal cost which is only VOM in case of gas chp
371
    chp_el_ind["marginal_cost"] = get_sector_parameters("gas", scenario)[
372
        "marginal_cost"
373
    ]["chp_gas"]
374
375
    chp_el_ind.to_postgis(
376
        targets["link"]["table"],
377
        schema=targets["link"]["schema"],
378
        con=db.engine(),
379
        if_exists="append",
380
    )
381
382
    # Insert biomass CHP as generators
383
    chp_el_ind_gen = pd.DataFrame(
384
        index=chp_generator_ind,
385
        data={
386
            "scn_name": scenario,
387
            "bus": chp_industry.loc[
388
                chp_generator_ind, "electrical_bus_id"
389
            ].astype(int),
390
            "p_nom": chp_industry.loc[chp_generator_ind, "el_capacity"],
391
            "carrier": chp_industry.loc[chp_generator_ind, "carrier"],
392
        },
393
    )
394
395
    chp_el_ind_gen["generator_id"] = range(
396
        db.next_etrago_id("generator"),
397
        len(chp_el_ind_gen) + db.next_etrago_id("generator"),
398
    )
399
400
    # Add marginal cost
401
    chp_el_ind_gen["marginal_cost"] = (
402
        pd.Series(
403
            get_sector_parameters("electricity", scenario)["marginal_cost"]
404
        )
405
        .rename({"other_non_renewable": "others"})
406
        .loc[chp_el_ind_gen["carrier"]]
407
    ).values
408
409
    # Update carrier
410
    chp_el_ind_gen["carrier"] = "industrial_" + chp_el_ind_gen.carrier + "_CHP"
411
412
    chp_el_ind_gen.to_sql(
413
        targets["generator"]["table"],
414
        schema=targets["generator"]["schema"],
415
        con=db.engine(),
416
        if_exists="append",
417
        index=False,
418
    )
419
420
421
def insert():
422
    """Insert combined heat and power plants into eTraGo tables.
423
424
    Gas CHP plants are modeled as links to the gas grid,
425
    biomass CHP plants (only in eGon2035) are modeled as generators
426
427
    Returns
428
    -------
429
    None.
430
431
    """
432
433
    for scenario in config.settings()["egon-data"]["--scenarios"]:
434
        if scenario != "eGon100RE":
435
            insert_scenario(scenario)
436
437
        else:
438
            insert_egon100re()
439