diff --git a/docs/data/DLR.rst b/docs/data/DLR.rst index 4c0b030c5..5414db22a 100644 --- a/docs/data/DLR.rst +++ b/docs/data/DLR.rst @@ -1 +1,47 @@ -Methods to include dynamic line rating in our model. +==================================================== +Methods to include dynamic line rating in our model +==================================================== + +To calculate the transmission capacity of each transmission line in the model, +the procedure suggested in the **Principles for the Expansion Planning of the +German Transmission Network** [NEP2021] where used: + +1. Import the temperature and wind temporal raster layers from ERA-5. Hourly +resolution data from the year 2011 was used. Raster resolution +latitude-longitude grids at 0.25° x 0.25°. + +2. Import shape file for the 9 regions proposed by the Principles for +the Expansion Planning. See Figure 1. + +.. image:: images/regions_DLR.png + :width: 400 + :alt: regions DLR + +Figure 1: Representative regions in Germany for DLR analysis [NEP2021] + +3. Find the lowest wind speed in each region. To perform this, for each +independent region, the wind speed of every cell in the raster layer should be +extracted and compared. This procedure is repeated for each hour in the +year 2011. The results are the 8760 lowest wind speed per region. + +4. Find the highest temperature in each region. To perform this, for each +independent region, the temperature of every cell in the raster layer should +be extracted and compared. This procedure is repeated for each hour in the +year 2011. The results are the 8760 maximum temperature per region. + +5. Calculate the maximum capacity for each region using the parameters shown in +Figure 2. + +.. image:: images/table_max_capacity_DLR.png + :width: 400 + :alt: table_max_capacity_DLR + +Figure 2: transmission capacity based on max temperature and min wind speed [NEP2021] + +6. Assign the maximum capacity of the corresponding region to each transmission +line inside each one of them. Crossborder lines and underground lines receive +no values. It means that their capacities are static and equal to their nominal +values. Lines that cross borders between regions receive the lowest +capacity per hour of the regions containing the line. + +.. [NEP2021] Principles for the Expansion Planning of the German Transmission Network https://www.netzentwicklungsplan.de/ \ No newline at end of file diff --git a/docs/images/regions_DLR.png b/docs/images/regions_DLR.png new file mode 100644 index 000000000..b4a7aedfd Binary files /dev/null and b/docs/images/regions_DLR.png differ diff --git a/docs/images/table_max_capacity_DLR.png b/docs/images/table_max_capacity_DLR.png new file mode 100644 index 000000000..016b7db3f Binary files /dev/null and b/docs/images/table_max_capacity_DLR.png differ diff --git a/src/egon/data/datasets/calculate_dlr.py b/src/egon/data/datasets/calculate_dlr.py index 95f1fac85..3680f9abb 100644 --- a/src/egon/data/datasets/calculate_dlr.py +++ b/src/egon/data/datasets/calculate_dlr.py @@ -21,10 +21,32 @@ class Calculate_dlr(Dataset): + """Calculate DLR and assign values to each line in the db + + Parameters + ---------- + *No parameters required + + *Dependencies* + * :py:class:`DataBundle ` + * :py:class:`Osmtgmod ` + * :py:class:`WeatherData ` + * :py:class:`FixEhvSubnetworks ` + + *Resulting tables* + * :py:class:`grid.egon_etrago_line_timeseries + ` is filled + """ + + #: + name: str = "dlr" + #: + version: str = "0.0.1" + def __init__(self, dependencies): super().__init__( - name="dlr", - version="0.0.1", + name=self.name, + version=self.version, dependencies=dependencies, tasks=(dlr,), ) diff --git a/src/egon/data/datasets/fill_etrago_gen.py b/src/egon/data/datasets/fill_etrago_gen.py index c9d8ea68b..cae8fff4f 100644 --- a/src/egon/data/datasets/fill_etrago_gen.py +++ b/src/egon/data/datasets/fill_etrago_gen.py @@ -9,10 +9,32 @@ class Egon_etrago_gen(Dataset): + """ + Group generators based on Scenario, carrier and bus. Marginal costs are + assigned to generators without this data. Grouped generators + are sent to the egon_etrago_generator table and a timeseries is assigned + to the weather dependent ones. + + *Dependencies* + * :py:class:`PowerPlants ` + * :py:class:`WeatherData ` + + *Resulting tables* + * :py:class:`grid.egon_etrago_generator + ` is extended + * :py:class:`grid.egon_etrago_generator_timeseries + ` is filled + + """ + #: + name: str = "etrago_generators" + #: + version: str = "0.0.8" + def __init__(self, dependencies): super().__init__( - name="etrago_generators", - version="0.0.8", + name=self.name, + version=self.version, dependencies=dependencies, tasks=(fill_etrago_generators,), ) @@ -65,7 +87,6 @@ def fill_etrago_generators(): def group_power_plants(power_plants, renew_feedin, etrago_gen_orig, cfg): - # group power plants by bus and carrier agg_func = { @@ -89,7 +110,6 @@ def group_power_plants(power_plants, renew_feedin, etrago_gen_orig, cfg): def add_marginal_costs(power_plants): - scenarios = power_plants.scenario.unique() pp = pd.DataFrame() @@ -124,7 +144,6 @@ def add_marginal_costs(power_plants): def fill_etrago_gen_table(etrago_pp2, etrago_gen_orig, cfg, con): - etrago_pp = etrago_pp2[ ["carrier", "el_capacity", "bus_id", "scenario", "marginal_cost"] ] @@ -243,7 +262,6 @@ def power_timeser(weather_data): def adjust_renew_feedin_table(renew_feedin, cfg): - # Define carrier 'pv' as 'solar' carrier_pv_mask = renew_feedin["carrier"] == "pv" renew_feedin.loc[carrier_pv_mask, "carrier"] = "solar" diff --git a/src/egon/data/datasets/power_plants/__init__.py b/src/egon/data/datasets/power_plants/__init__.py index 71213e66f..39f68ad40 100755 --- a/src/egon/data/datasets/power_plants/__init__.py +++ b/src/egon/data/datasets/power_plants/__init__.py @@ -56,10 +56,50 @@ class EgonPowerPlants(Base): class PowerPlants(Dataset): + """ + This module creates all electrical generators for different scenarios. It + also calculates the weather area for each weather dependent generator. + + *Dependencies* + * :py:class:`Chp ` + * :py:class:`CtsElectricityDemand + ` + * :py:class:`HouseholdElectricityDemand + ` + * :py:class:`mastr_data ` + * :py:func:`define_mv_grid_districts + ` + * :py:class:`RePotentialAreas + ` + * :py:class:`ZensusVg250 + ` + * :py:class:`ScenarioCapacities + ` + * :py:class:`ScenarioParameters + ` + * :py:func:`Setup ` + * :py:class:`substation_extraction + ` + * :py:class:`Vg250MvGridDistricts + ` + * :py:class:`ZensusMvGridDistricts + ` + + *Resulting tables* + * :py:class:`supply.egon_power_plants + ` is filled + + """ + + #: + name: str = "PowerPlants" + #: + version: str = "0.0.18" + def __init__(self, dependencies): super().__init__( - name="PowerPlants", - version="0.0.18", + name=self.name, + version=self.version, dependencies=dependencies, tasks=( create_tables, @@ -347,7 +387,6 @@ def insert_hydro_plants(scenario): } for carrier in map_carrier.keys(): - # import target values target = select_target(carrier, scenario) @@ -500,9 +539,7 @@ def assign_voltage_level(mastr_loc, cfg, mastr_working_dir): def assign_voltage_level_by_capacity(mastr_loc): - for i, row in mastr_loc[mastr_loc.voltage_level.isnull()].iterrows(): - if row.Nettonennleistung > 120: level = 1 elif row.Nettonennleistung > 20: @@ -610,7 +647,6 @@ def insert_hydro_biomass(): def allocate_conventional_non_chp_power_plants(): - carrier = ["oil", "gas"] cfg = egon.data.config.datasets()["power_plants"] @@ -625,14 +661,12 @@ def allocate_conventional_non_chp_power_plants(): ) for carrier in carrier: - nep = select_nep_power_plants(carrier) if nep.empty: print(f"DataFrame from NEP for carrier {carrier} is empty!") else: - mastr = select_no_chp_combustion_mastr(carrier) # Assign voltage level to MaStR @@ -771,7 +805,6 @@ def allocate_conventional_non_chp_power_plants(): def allocate_other_power_plants(): - # Get configuration cfg = egon.data.config.datasets()["power_plants"] boundary = egon.data.config.settings()["egon-data"]["--dataset-boundary"]