diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 160ddd430..34d88c305 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,12 +25,9 @@ jobs: strategy: matrix: python-version: - - "3.7" - "3.8" platform: [ubuntu-latest, macos-latest] exclude: - - platform: macos-latest - python-version: "3.7" - platform: macos-latest python-version: "3.8" max-parallel: 4 diff --git a/.readthedocs.yml b/.readthedocs.yml index 59ff5c04f..a6cb80d29 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -8,3 +8,8 @@ python: - requirements: docs/requirements.txt - method: pip path: . +# Set the version of Python +build: + os: ubuntu-22.04 + tools: + python: "3.8" diff --git a/CHANGELOG.rst b/CHANGELOG.rst index b65013c00..1e1495390 100755 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -29,11 +29,12 @@ Added returns the current configuration settings. See `PR #159`_ for more details. * You can now use tasks which are not part of a ``Dataset``, i.e. which - are unversioned, as dependencies of a dataset. See `PR #318`_ for more + are unversioned, as dependencies of a dataset. See + `#318 `_ for more details. * You can now force the tasks of a ``Dataset`` to be always executed by - giving the version of the ``Dataset`` a ``".dev"`` suffix. See `PR - #318`_ for more details. + giving the version of the ``Dataset`` a ``".dev"`` suffix. See + `#318 `_ for more details. * OSM data import as done in open_ego `#1 `_ which was updated to the latest long-term data set of the 2021-01-01 diff --git a/docs/conf.py b/docs/conf.py index 3a1c2fa84..0be1e3dd7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -30,10 +30,10 @@ "pr": ("https://github.com/openego/eGon-data/pull/%s", "PR #"), } # on_rtd is whether we are on readthedocs.org -on_rtd = os.environ.get("READTHEDOCS", None) == "True" +# on_rtd = os.environ.get("READTHEDOCS", None) == "True" -if not on_rtd: # only set the theme if we're building docs locally - html_theme = "sphinx_rtd_theme" +#if not on_rtd: # only set the theme if we're building docs locally +html_theme = "sphinx_rtd_theme" html_use_smartypants = True html_last_updated_fmt = "%b %d, %Y" diff --git a/docs/data.rst b/docs/data.rst index b529e7938..72234850f 100644 --- a/docs/data.rst +++ b/docs/data.rst @@ -15,7 +15,7 @@ and their processing within the eGon-data pipeline are described here. Grid models =========== -Power grid models of different voltage levels form a central part of the eGon data model, which is required for cross-grid-level optimization. +Power grid models of different voltage levels form a central part of the eGon-data model, which is required for cross-grid-level optimization. In addition, sector coupling necessitates the representation of the gas grid infrastructure, which is also described in this section. Electricity grid @@ -41,6 +41,8 @@ Electricity .. include:: data/electricity_demand.rst +.. _heat-demand-ref: + Heat ---- @@ -97,8 +99,10 @@ Dynamic line rating .. include:: data/DLR.rst -E-Mobility ----------- +.. _flexible-charging-ref: + +Flexible charging of EVs +--------------------------- .. include:: data/e-mobility.rst diff --git a/docs/data/DLR.rst b/docs/data/DLR.rst index 5414db22a..95d987177 100644 --- a/docs/data/DLR.rst +++ b/docs/data/DLR.rst @@ -1,10 +1,6 @@ -==================================================== -Methods to include dynamic line rating in our model -==================================================== - -To calculate the transmission capacity of each transmission line in the 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: +German Transmission Network** [NEP2021a]_ 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 @@ -16,8 +12,8 @@ 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] + +Figure 1: Representative regions in Germany for DLR analysis [NEP2021a]_ 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 @@ -35,13 +31,11 @@ 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] + +Figure 2: transmission capacity based on max temperature and min wind speed [NEP2021a]_ 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 +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/data/e-mobility.rst b/docs/data/e-mobility.rst index 0f4be98c9..d62003100 100644 --- a/docs/data/e-mobility.rst +++ b/docs/data/e-mobility.rst @@ -1 +1,35 @@ -What flexibilities does e-mobility provide to the system. How did we implement it? +The flexibility potential of EVs is determined on the basis of the trip data +created with SimBEV (see :ref:`mobility-demand-mit-ref`). +It is assumed, that only charging at private charging points, comprising charging points at +home and at the workplace, can be flexibilized. Public fast (e.g. gas stations) and slow charging (e.g. schools +and shopping facilities) stations are assumed not to provide demand-side flexibility. +Further, vehicle-to-grid is not considered and it is assumed that charging can only be shifted +within a charging event. Shifting charging demand to a later charging event, for example +from charging at work during working hours to charging at home in the evening, is therefore +not possible. In the generation of the trip data itself it is already considered, that +EVs are not charged everytime a charging point is available, but only if a certain +lower state of charge (SoC) is reached or the energy level is not sufficient for the next ride. + +In `eTraGo `_, the flexibility of the EVs is modeled +using a storage model based on [Brown2018]_ and [Wulff2020]_. +The used model is visualised in the upper right in figure :ref:`mit-model`. +Its parametrization is for both the eGon2035 and eGon100RE scenario conducted in the +:py:class:`MotorizedIndividualTravel` +dataset in the function +:py:func:`generate_load_time_series`. +The model consists of loads for static driving demands and stores for the fleet’s batteries. +The stores are constrained by hourly lower and upper SoC limits. +The lower SoC limit represents the inflexible charging demand while the +SoC band between the lower and upper SoC limit represents the flexible charging demand. +Further, the charging infrastructure is represented by unidirectional links from electricity +buses to EV buses. Its maximum charging power per hour is set to the available charging power +of grid-connected EVs. + +In `eDisGo `_, the flexibility potential for +controlled charging is modeled using +so-called flexibility bands. These bands comprise an upper and lower power band for +the charging power and an upper and lower energy band for the energy to be recharged +for each charging point in an hourly resolution. These flexibility bands are not +set up in eGon-data but in eDisGo, using the trip data from eGon-data. +For further information on the flexibility bands see +`eDisGo documentation `_. diff --git a/docs/data/electricity_demand.rst b/docs/data/electricity_demand.rst index 3e82adbe2..39a6dbdbe 100644 --- a/docs/data/electricity_demand.rst +++ b/docs/data/electricity_demand.rst @@ -1,91 +1,181 @@ -.. _elec_demand_ref: -The electricity demand considered includes demand from the residential, commercial and industrial sector. +The electricity demand considered includes demand from the residential, commercial and industrial sector. The target values for scenario *eGon2035* are taken from the German grid development plan from 2021 [NEP2021]_, -whereas the distribution on NUTS3-levels corresponds to the data from the research project *DemandRegio* [demandregio]_. -The following table lists the electricity demands per sector: +whereas the distribution on NUTS3-levels corresponds to the data from the research project *DemandRegio* [demandregio]_. +The following table lists the electricity demands per sector: .. list-table:: Electricity demand per sector :widths: 25 50 :header-rows: 1 - + * - Sector - Annual electricity demand in TWh * - residential - 115.1 - * - commercial - - 123.5 + * - commercial + - 123.5 * - industrial - 259.5 - -A further spatial and temporal distribution of the electricity demand is needed to fullfil all requirements of the -subsequent grid optimization. Therefore different, sector-specific distributions methods were developed and applied. + +A further spatial and temporal distribution of the electricity demand is needed for the +subsequent grid optimization. Therefore different sector-specific distributions methods were developed and applied. Residential electricity demand -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++++++++++++++++++++++++++++++++++ -The annual electricity demands of households on NUTS3-level from *DemandRegio* are scaled to meet the national target -values for the respective scenario in dataset :py:class:`DemandRegio `. -A further spatial and temporal distribution of residential electricity demands is performed in -:py:class:`HouseholdElectricityDemand ` as described +The annual electricity demands of households on NUTS3-level from *DemandRegio* are scaled to meet the national target +values for the respective scenario in dataset :py:class:`DemandRegio `. +A further spatial and temporal distribution of residential electricity demands is performed in +:py:class:`HouseholdElectricityDemand ` as described in [Buettner2022]_. -The result is a consistent dataset across aggregation levels with an hourly resolution. + +The allocation of the chosen electricity profiles in each census cell to buildings +is conducted in the dataset +:py:class:`Demand_Building_Assignment `. +For each cell, the profiles are randomly assigned to an OSM building within this cell. +If there are more profiles than buildings, all additional profiles are further randomly +allocated to buildings within the cell. +Therefore, multiple profiles can be assigned to one building, making it a +multi-household building. +In case there are no OSM buildings that profiles can be assigned to, synthetic buildings +are generated with a dimension of 5m x 5m. +The number of synthetically created buildings per census cell is determined using +the Germany-wide average of profiles per building (value is rounded up and only +census cells with buildings are considered). +The profile ID each building is assigned is written to data base table +:py:class:`demand.egon_household_electricity_profile_of_buildings `. +Synthetically created buildings are written to data base table +:py:class:`openstreetmap.osm_buildings_synthetic `. +The household electricity peak load per building is written to database table +:py:class:`demand.egon_building_electricity_peak_loads `. +Drawbacks and limitations of the allocation to specific buildings +are discussed in the dataset docstring of +:py:class:`Demand_Building_Assignment `. + +The result is a consistent dataset across aggregation levels with an hourly resolution. .. figure:: /images/S27-3.png :name: spatial_distribution_electricity_demand :width: 400 - + Electricity demand on NUTS 3-level (upper left); Exemplary MVGD (upper right); Study region in Flensburg (20 Census cells, bottom) from [Buettner2022]_ .. figure:: /images/S27-4a.png :name: aggregation_level_electricity_demand :width: 400 - - Electricity demand time series on different aggregation levels from [Buettner2022]_ - + Electricity demand time series on different aggregation levels from [Buettner2022]_ Commercial electricity demand -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++++++++++++++++++++++++++++++++++ -The distribution of electricity demand from the commercial, trade and service (CTS) sector is also based on data from -*DemandRegio*, which provides annual electricity demands on NUTS3-level for Germany. In dataset +The distribution of electricity demand from the commercial, trade and service (CTS) sector is also based on data from +*DemandRegio*, which provides annual electricity demands on NUTS3-level for Germany. In dataset :py:class:`CtsElectricityDemand ` the annual electricity -demands are further distributed to census cells (100x100m cells from [Census]_) based on the distribution of heat demands, -which is taken from the Pan-European Thermal Altlas version 5.0.1 [Peta]_. For further information refer to section -ref:`heat_demand`. -The applied methods for a futher spatial and temporal distribution to buildings is described in [Buettner2022]_ and -performed in dataset :py:class:`CtsDemandBuildings ` +demands are further distributed to census cells (100x100m cells from [Census]_) based on the distribution of heat demands, +which is taken from the Pan-European Thermal Atlas (PETA) version 5.0.1 [Peta]_. For further information refer to section +:ref:`heat-demand-ref`. + +.. _disagg-cts-elec-ref: + +Spatial disaggregation of CTS demand to buildings +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The spatial disaggregation of the annual CTS demand to buildings is conducted in the dataset +:py:class:`CtsDemandBuildings `. +Both the electricity demand as well as the heat demand is disaggregated +in the dataset. Here, only the disaggregation of the electricity demand is described. +The disaggregation of the heat demand is analogous to it. More information on the resulting +tables is given in section :ref:`heat-demand-ref`. + +The workflow generally consists of three steps. First, the annual demand from +Peta5 [Peta]_ is used to identify census cells with demand. +Second, Openstreetmap [OSM]_ data on buildings and amenities is used to map the demand to single buildings. +If no sufficient OSM data are available, new synthetic buildings and if necessary +synthetic amenities are generated. +Third, each building's share of the HV-MV substation demand profile is determined +based on the number of amenities within the building and the census cell(s) it is in. + +The workflow is in more detail shown in figure +:ref:`disaggregation-cts-model` and described in the following. + +.. figure:: /images/flowchart_cts_disaggregation.jpg + :name: disaggregation-cts-model + :width: 800 + + Workflow for the disaggregation of the annual CTS demand to buildings + +In the :py:class:`OpenStreetMap ` dataset, we filtered all +OSM buildings and amenities for tags we relate to the CTS sector. Amenities are mapped +to intersecting buildings and then intersected with the annual demand at census cell level. We obtain +census cells with demand that have amenities within and census cells with demand that +don't have amenities within. +If there is no data on amenities, synthetic ones are assigned to existing buildings. We use +the median value of amenities per census cell in the respective MV grid district +to determine the number of synthetic amenities. +If no building data is available, a synthetic building with a dimension of 5m x 5m is randomly generated. +This also happens for amenities that couldn't be assigned to any OSM building. +We obtain four different categories of buildings with amenities: + +* Buildings with amenities +* Synthetic buildings with amenities +* Buildings with synthetic amenities +* Synthetic buildings with synthetic amenities + +Synthetically created buildings are written to data base table +:py:class:`openstreetmap.osm_buildings_synthetic `. +Information on the number of amenities within each building with CTS, comprising OSM +buildings and synthetic buildings, is written to database table +:py:class:`openstreetmap.egon_cts_buildings `. + +To determine each building's share of the HV-MV substation demand profile, +first, the share of each building on the demand per census cell is calculated +using the number of amenities per building. +Then, the share of each census cell on the demand per HV-MV substation is determined +using the annual demand defined by Peta5. +Both shares are finally multiplied and summed per building ID to determine each +building's share of the HV-MV substation demand profile. The summing per building ID is +necessary, as buildings can lie in multiple census cells and are therefore assigned +a share in each of these census cells. +The share of each CTS building on the CTS electricity demand profile per HV-MV substation +in each scenario is saved to the database table +:py:class:`demand.egon_cts_electricity_demand_building_share `. +The CTS electricity peak load per building is written to database table +:py:class:`demand.egon_building_electricity_peak_loads `. + +Drawbacks and limitations as well as assumptions and challenges of the disaggregation +are discussed in the dataset docstring of +:py:class:`CtsDemandBuildings `. Industrial electricity demand -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++++++++++++++++++++++++++++++++++ -To distribute the annual industrial electricity demand OSM landuse data as well as information on industrial sites are -taken into account. +To distribute the annual industrial electricity demand OSM landuse data as well as information on industrial sites are +taken into account. In a first step (:py:class:`CtsElectricityDemand `) -different sources providing information about specific sites and further information on the industry sector in which -the respective industrial site operates are combined. Here, the three data sources [Hotmaps]_, [sEEnergies]_ and -[Schmidt2018]_ are aligned and joined. +different sources providing information about specific sites and further information on the industry sector in which +the respective industrial site operates are combined. Here, the three data sources [Hotmaps]_, [sEEnergies]_ and +[Schmidt2018]_ are aligned and joined. Based on the resulting list of industrial sites in Germany and information on industrial landuse areas from OSM [OSM]_ which where extracted and processed in :py:class:`OsmLanduse ` the annual demands were distributed. -The spatial and temporal distribution is performed in -:py:class:`IndustrialDemandCurves `. -For the spatial distribution of annual electricity demands from *DemandRegio* [demandregio]_ which are available on +The spatial and temporal distribution is performed in +:py:class:`IndustrialDemandCurves `. +For the spatial distribution of annual electricity demands from *DemandRegio* [demandregio]_ which are available on NUTS3-level are in a first step evenly split 50/50 between industrial sites and OSM-polygons tagged as industrial areas. -Per NUTS-3 area the respective shares are then distributed linearily based on the area of the corresponding landuse polygons +Per NUTS-3 area the respective shares are then distributed linearily based on the area of the corresponding landuse polygons and evenly to the identified industrial sites. In a next step the temporal disaggregation of the annual demands is carried out taking information about the industrial sectors and sector-specific standard load profiles from [demandregio]_ into account. -Based on the resulting time series and their peak loads the corresponding grid level and grid connections point is -identified. +Based on the resulting time series and their peak loads the corresponding grid level and grid connections point is +identified. Electricity demand in neighbouring countries -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++++++++++++++++++++++++++++++++++++++++++++++++++++ The neighbouring countries considered in the model are represented in a lower spatial resolution of one or two buses per -country. The national demand timeseries in an hourly resolution of the respective countries is taken from the Ten-Year +country. The national demand timeseries in an hourly resolution of the respective countries is taken from the Ten-Year Network Development Plan, Version 2020 [TYNDP]_. In case no data for the target year is available the data is is -interpolated linearly. -Refer to the corresponding dataset for detailed information: -:py:class:`ElectricalNeighbours ` +interpolated linearly. +Refer to the corresponding dataset for detailed information: +:py:class:`ElectricalNeighbours `. diff --git a/docs/data/electricity_grids.rst b/docs/data/electricity_grids.rst index 8c94693c8..c6059fb50 100644 --- a/docs/data/electricity_grids.rst +++ b/docs/data/electricity_grids.rst @@ -23,10 +23,9 @@ country in dataset :py:class:`ElectricalNeighbours `. The resulting grid topology is shown in the following figure. -..figure:: images/Stromnetz.png - :scale: 50 % +.. figure:: /images/grid_topology_ehv_hv.png :name: gridtopology_ehv_hv - :alt: Grid topology extra-high and high voltage grid + :width: 400 diff --git a/docs/data/electricity_supply.rst b/docs/data/electricity_supply.rst index f8e490429..6c4ea2cab 100644 --- a/docs/data/electricity_supply.rst +++ b/docs/data/electricity_supply.rst @@ -33,7 +33,7 @@ The following steps are conducted: #. If expansion of wind onshore capacity is required, capacities are calculated depending on the area size of the formerly selected potential areas. 21.05 MW/km² and 16.81 MW/km² are used for federal states in the north and in the south of the country respectively. The resulting parks are therefore located on the selected potential areas. -#. The resulting capacities are compared to the target values for the specific scenario per federal state. If the target value is exceeded, a linear downscaling is conducted. If the target value is not reached yet, the remaining capacity is distributed linearly among the rest of the potential areas within the state. +#. The resulting capacities are compared to the target values for the specific scenario per federal state. If the target value is exceeded, a linear downscaling is conducted. If the target value is not reached yet, the remaining capacity is distributed linearly among the rest of the potential areas within the state. Offshore wind ++++++++++++++ @@ -52,10 +52,11 @@ The following steps are conducted: .. figure:: /images/offshore_power_plants_areas.png :name: offshore_power_plants_areas - :width: 400 - + :width: 400 + Areas for offshore wind park in North and Baltic sea. Source: NEP +.. _pv-rooftop-ref: PV ground mounted ++++++++++++++++++ @@ -74,12 +75,12 @@ The following steps are conducted: #. If expansion of PV ground mounted capacity is required, capacities are calculated depending on the area size of the formerly selected potential areas. The resulting parks are therefore located on the selected potential areas. -#. The resulting capacities are compared to the target values for the specific scenario per federal state. If the target value is exceeded, a linear downscaling is conducted. If the target value is not reached yet, the remaining capacity is distributed linearly among the rest of the potential areas within the state. +#. The resulting capacities are compared to the target values for the specific scenario per federal state. If the target value is exceeded, a linear downscaling is conducted. If the target value is not reached yet, the remaining capacity is distributed linearly among the rest of the potential areas within the state. .. figure:: /images/PV_freiflaeche.png :name: pv_ground_mounted-example - :width: 400 - + :width: 400 + Example: sites of existing PV ground mounted parks and potential areas PV rooftop @@ -140,18 +141,18 @@ Disaggregation of PV rooftop scenario capacities: Hydro +++++ -In the case of hydropower plants, a distinction is made between the carrier run-of-river -and reservoir. +In the case of hydropower plants, a distinction is made between the carrier run-of-river +and reservoir. The methods to distribute and allocate are the same for both carriers. -In a first step all suitable power plants (correct carrier, valid geolocation, information +In a first step all suitable power plants (correct carrier, valid geolocation, information about federal state) are selected and their installed capacity is scaled to meet the target -values for the respective federal state and scenario. -Information about the voltage level the power plants are connected to is obtained. In case -no information is availabe the voltage level is identified using threshold values for the -installed capacity (see :func:`assign_voltage_level `). +values for the respective federal state and scenario. +Information about the voltage level the power plants are connected to is obtained. In case +no information is availabe the voltage level is identified using threshold values for the +installed capacity (see :func:`assign_voltage_level `). In a next step the correct grid connection point is identified based on the voltage level and geolocation of the power plants (see :func:`assign_bus_id `) -The resulting list of power plants it added to table +The resulting list of power plants it added to table :py:class:`EgonPowerPlants `. Biomass @@ -172,9 +173,9 @@ Conventional In function :func:`allocate_conventional_non_chp_power_plants ` -capacities for conventional power plants, which are no chp plants, with carrier *oil* and +capacities for conventional power plants, which are no chp plants, with carrier *oil* and *gas* are allocated. - + diff --git a/docs/data/gas_grids.rst b/docs/data/gas_grids.rst index 471218c0a..cf415afe2 100644 --- a/docs/data/gas_grids.rst +++ b/docs/data/gas_grids.rst @@ -1,20 +1,20 @@ The gas grid data stems from the *SciGRID_gas project* (https://www.gas.scigrid.de/) which covers the European Gas -Transmission Grid. All data generated in the *SciGRID_gas* project is licenced under +Transmission Grid. All data generated in the *SciGRID_gas* project is licenced under *Creative Commons Attribution 4.0 International Public License*. The specific dataset version is IGGIELGN and can be downloaded at https://zenodo.org/record/4767098. -*SciGRID_gas* contains extensive data on pipelines, storages, LNGs, productions, consumers and more. +*SciGRID_gas* contains extensive data on pipelines, storages, LNGs, productions, consumers and more. Further information can be obtained in the IGGIELGN documentation. For eGon-data, *SciGRID_gas* infrastructure data in Germany has been extracted and used in full resolution while data of neighboring countries has been aggregated. -Methane grid -~~~~~~~~~~~~ -In the eGon2035 scenario the methane grid is, apart from minor adjustments, equivalent to the gas grid described in the +Methane grid +++++++++++++++ +In the eGon2035 scenario the methane grid is, apart from minor adjustments, equivalent to the gas grid described in the *SciGRID_gas IGGIELGN* dataset. Hydrogen grid -~~~~~~~~~~~~~ +++++++++++++++ In the eGon2035 scenario H2 nodes are present at every methane bus (H2_grid) and at locations where there -are possible H2 cavern storages available (H2_saltcavern). There is no explicit H2 pipeline grid available but H2 can -be transported using the methane grid. +are possible H2 cavern storages available (H2_saltcavern). There is no explicit H2 pipeline grid available but H2 can +be transported using the methane grid. diff --git a/docs/data/heat_demand.rst b/docs/data/heat_demand.rst index d03dac90c..74a7faec4 100644 --- a/docs/data/heat_demand.rst +++ b/docs/data/heat_demand.rst @@ -1,22 +1,21 @@ -.. _heat_demand: -Heat demands comprise space heating and drinking hot water demands from -residential and comertial trade and service (CTS) buildings. +Heat demands comprise space heating and drinking hot water demands from +residential and commercial trade and service (CTS) buildings. Process heat demands from the industry are, depending on the required temperature -level, modelled as electrcity, hydrogen or methane demand. +level, modelled as electricity, hydrogen or methane demand. -The spatial distribution of annual heat demands is taken from the Pan-European -Thermal Altlas version 5.0.1 [Peta]_. -This source provides data on annual european residential and CTS heat demands -per hectar cell for the year 2015. -In order to model future demands, the demand distribution extracted by Peta is -then scaled to meet a national annual demand from external sources. -The following national demands are taken for the selected scenarios: +The spatial distribution of annual heat demands is taken from the Pan-European +Thermal Atlas version 5.0.1 [Peta]_. +This source provides data on annual European residential and CTS heat demands +per census cell for the year 2015. +In order to model future demands, the demand distribution extracted by Peta is +then scaled to meet a national annual demand from external sources. +The following national demands are taken for the selected scenarios: .. list-table:: Heat demands per sector and scenario :widths: 25 25 25 25 :header-rows: 1 - * - + * - - Residential sector - CTS sector - Sources @@ -32,28 +31,52 @@ The following national demands are taken for the selected scenarios: - [Energiereferenzprognose]_ -The resulting data is stored in the database table :py:class:`demand.egon_peta_heat `. -The implementation of these dataprocessing steps can be found in :py:class:`HeatDemandImport `. +The resulting annual heat demand data per census cell is stored in the database table +:py:class:`demand.egon_peta_heat `. +The implementation of these data processing steps can be found in :py:class:`HeatDemandImport `. -Figure :ref:`residential-heat-demand-annual` shows the distribution of residential heat demands for scenario ``eGon2035``, +Figure :ref:`residential-heat-demand-annual` shows the census cell distribution of residential heat demands for scenario ``eGon2035``, categorized for different levels of annual demands. .. figure:: /images/residential_heat_demand.png :name: residential-heat-demand-annual :width: 400 - - Spatial distribution of residential heat demand in scenario ``eGon2035`` - -Afterwards, the annual heat demands are used to create hourly heat demand profiles. -For residential heat demand profiles a pool of synthetical created bottom-up demand -profiles is used. Depending on the mean temperature per day, these profiles are -randomly assigned to each residential building. The methodology is described in + Spatial distribution of residential heat demand per census cell in scenario ``eGon2035`` + +In a next step, the annual demand per census cell is further disaggregated to buildings. +In case of residential buildings the demand is equally distributed to all residential +buildings within the census cell. The annual demand per residential building is not +saved in any database table but needs to be calculated from the annual demand in the census +cell in table :py:class:`demand.egon_peta_heat ` +and the number of residential buildings in table +:py:class:`demand.egon_heat_timeseries_selected_profiles ` +(see also query below). +The disaggregation of the annual CTS heat demand per census cell to buildings is +done analogous to the disaggregation of the electricity demand, which is in detail +described in section :ref:`disagg-cts-elec-ref`. +The share of each CTS building of the corresponding HV-MV substation's heat profile is +for both the eGon2035 and eGon100RE scenario written to the database table +:py:class:`EgonCtsHeatDemandBuildingShare`. +The peak heat demand per building, including residential and CTS demand, in the two +scenarios eGon2035 and eGon100RE is calculated in the datasets +:py:class:`HeatPumps2035 ` and +:py:class:`HeatPumpsPypsaEurSec `, +respectively, and written to table +:py:class:`demand.egon_building_heat_peak_loads `. + +The hourly heat demand profiles are for both sectors created in the Dataset +:py:class:`HeatTimeSeries `. +For residential heat demand profiles a pool of synthetically created bottom-up demand +profiles is used. Depending on the mean temperature per day, these profiles are +randomly assigned to each residential building. The methodology is described in detail in [Buettner2022]_. - - -Data on residential heat demand profiles is stored in the database within the tables :py:class:`demand.egon_heat_timeseries_selected_profiles `, :py:class:`demand.egon_daily_heat_demand_per_climate_zone `, :py:class:`boundaries.egon_map_zensus_climate_zones `. To create the profiles for a selected buidling, these tables -have to be combined, e.g. like this: +Data on residential heat demand profiles is stored in the database within the tables +:py:class:`demand.egon_heat_timeseries_selected_profiles `, +:py:class:`demand.egon_daily_heat_demand_per_climate_zone `, +:py:class:`boundaries.egon_map_zensus_climate_zones `. +To create the profiles for a selected building, these tables +have to be combined, e.g. like this: .. code-block:: none @@ -78,24 +101,20 @@ have to be combined, e.g. like this: AND b.sector = 'residential'; -Exemplary resulting residential heat demand time series for a selected day in winter and +Exemplary resulting residential heat demand time series for a selected day in winter and summer considering different aggregation levels are visualized in figures :ref:`residential-heat-demand-timeseries-winter` and :ref:`residential-heat-demand-timeseries-summer`. .. figure:: /images/residential_heat_demand_profile_winter.png :name: residential-heat-demand-timeseries-winter :width: 400 - + Temporal distribution of residential heat demand for a selected day in winter - + .. figure:: /images/residential_heat_demand_profile_summer.png :name: residential-heat-demand-timeseries-summer :width: 400 - + Temporal distribution of residential heat demand for a selected day in summer The temporal disaggregation of CTS heat demand is done using Standard Load Profiles Gas -from ``demandregio`` [demandregio]_ considering different profiles per CTS branch. - - -The heat demand time series for both sectors creation is done in the Dataset -:py:class:`HeatTimeSeries `. +from ``demandregio`` [demandregio]_ considering different profiles per CTS branch. diff --git a/docs/data/heat_supply.rst b/docs/data/heat_supply.rst index f0c633edb..e49797b65 100644 --- a/docs/data/heat_supply.rst +++ b/docs/data/heat_supply.rst @@ -1,12 +1,12 @@ -Heat demand of residential as well as commercial, trade and service (CTS) buildings can be supplied by different technologies and carriers. Within the data model creation, capacities of supply technologies are assigned to specific locations and their demands. The hourly dispatch of heat supply is not part of the data model, but a result of the grid optimization tools. +Heat demand of residential as well as commercial, trade and service (CTS) buildings can be supplied by different technologies and carriers. Within the data model creation, capacities of supply technologies are assigned to specific locations and their demands. The hourly dispatch of heat supply is not part of the data model, but a result of the grid optimization tools. -In general, heat supply can be divided into three categories which include specific technologies: residential and CTS buildings in a district heating area, buildings supplied by individual heat pumps, and buildings supplied by conventional gas boilers. The shares of these categories are taken from external sources for each scenario. +In general, heat supply can be divided into three categories which include specific technologies: residential and CTS buildings in a district heating area, buildings supplied by individual heat pumps, and buildings supplied by conventional gas boilers. The shares of these categories are taken from external sources for each scenario. .. list-table:: Heat demands of different supply categories :widths: 20 20 20 20 :header-rows: 1 - * - + * - - District heating - Individual heat pumps - Individual gas boilers @@ -19,61 +19,135 @@ In general, heat supply can be divided into three categories which include speci * - eGon100RE - 61.5 TWh - 311.5 TWh - - 0 TWh + - 0 TWh -The following subsections describe the heat supply methodology for each category. +The following subsections describe the heat supply methodology for each category. .. _district-heating: District heating -~~~~~~~~~~~~~~~~ ++++++++++++++++++ -First, district heating areas are defined for each scenario based on existing district heating areas and an overall district heating share per scenario. To reduce the model complexity, district heating areas are defined per Census cell, either all buildings within a cell are supplied by district heat or none. The first step of the extraction of district heating areas is the identification of Census cells with buildings that are currently supplied by district heating using the ``building`` dataset of Census. All Census cells where more than 30% of the buildings are currently supplied by district heat are defined as cells inside a district heating area. -The identified cells are then summarized by combining cells that have a maximum distance of 500m. +First, district heating areas are defined for each scenario based on existing district heating areas and an overall district heating share per scenario. To reduce the model complexity, district heating areas are defined per Census cell, either all buildings within a cell are supplied by district heat or none. The first step of the extraction of district heating areas is the identification of Census cells with buildings that are currently supplied by district heating using the ``building`` dataset of Census. All Census cells where more than 30% of the buildings are currently supplied by district heat are defined as cells inside a district heating area. +The identified cells are then summarized by combining cells that have a maximum distance of 500m. -Second, additional Census cells are assigned to district heating areas considering the heat demand density. Assuming that new district heating grids are more likely in cells with high demand, the remaining Census cells outside of a district heating grid are sorted by their demands. Until the pre-defined national district heating demand is met, cells from that list are assigned to district heating areas. This can also result in new district heating grids which cover only a few Census cells. +Second, additional Census cells are assigned to district heating areas considering the heat demand density. Assuming that new district heating grids are more likely in cells with high demand, the remaining Census cells outside of a district heating grid are sorted by their demands. Until the pre-defined national district heating demand is met, cells from that list are assigned to district heating areas. This can also result in new district heating grids which cover only a few Census cells. To avoid unrealistic large district heating grids in areas with many cities close to each other (e.g. the Ruhr Area), district heating areas with an annual demand > 4 TWh are split by NUTS3 boundaries. -The implementation of the district heating area demarcation is done in :py:class:`DistrictHeatingAreas `, the resulting data is stored in the tables :py:class:`demand.egon_map_zensus_district_heating_areas ` and :py:class:`demand.egon_district_heating_areas `. -The resulting district heating grids for the scenario eGon2035 are visualized in figure :ref:`district-heating-areas`, which also includes a zoom on the district heating grid in Berlin. +The implementation of the district heating area demarcation is done in :py:class:`DistrictHeatingAreas `, the resulting data is stored in the tables :py:class:`demand.egon_map_zensus_district_heating_areas ` and :py:class:`demand.egon_district_heating_areas `. +The resulting district heating grids for the scenario eGon2035 are visualized in figure :ref:`district-heating-areas`, which also includes a zoom on the district heating grid in Berlin. .. figure:: /images/district_heating_areas.png :name: district-heating-areas :width: 800 - + Defined district heating grids in scenario ``eGon2035`` The national capacities for each supply technology are taken from the Grid Development Plan (GDP) for the scenario ``eGon2035``, in the ``eGon100RE`` scenario they are the result of the ``pypsa-eur-sec`` run. The distribution of the capacities to district heating grids is done similarly based on [FfE2017]_, which is also used in the GDP. The basic idea of this method is to use a cascade of heat supply technologies until the heat demand can be covered. -#. Combined heat and power (CHP) plants are assigned to nearby district heating grids first. Their location and thermal capacities are from Marktstammdatenregister [MaStR]_. To identify district heating grids that need additional suppliers, the remaining annual heat demand is calculated using the thermal capacities of the CHP plants and assumed full load hours. +#. Combined heat and power (CHP) plants are assigned to nearby district heating grids first. Their location and thermal capacities are from Marktstammdatenregister [MaStR]_. To identify district heating grids that need additional suppliers, the remaining annual heat demand is calculated using the thermal capacities of the CHP plants and assumed full load hours. #. Large district heating grids with an annual demand that is higher than 96GWh can be supplied by geothermal plants, in case of an intersection of geothermal potential areas and the district heating grid. Smaller district heating grids can be supplied by solar thermal power plants. The national capacities are distributed proportionally to the remaining heat demands. After assigning these plants, the remaining heat demands are reduced by the thermal output and assumed full load hours. -#. Next, the national capacities for central heat pumps and resistive heaters are distributed to all district heating areas proportionally to their remaining demands. Heat pumps are modeled with a time-dependent coefficient of performance depending on the temperature data. +#. Next, the national capacities for central heat pumps and resistive heaters are + distributed to all district heating areas proportionally to their remaining demands. + Heat pumps are modeled with a time-dependent coefficient of performance (COP) depending on the temperature data. + The COP is determined in function + :py:func:`heat_pump_cop ` + as part of the + :py:class:`RenewableFeedin ` + dataset and written to database table + :py:class:`supply.egon_era5_renewable_feedin `. -#. In the last step, gas boilers are assigned to every district heating grid regardless of the remaining demand. In the optimization, this can be used as a fall-back option to not run into infeasibilities. +#. In the last step, gas boilers are assigned to every district heating grid regardless of the remaining demand. In the optimization, this can be used as a fall-back option to not run into infeasibilities. -The distribution of CHP plants for different carriers is shown in figure :ref:`chp-plants`. +The distribution of CHP plants for different carriers is shown in figure :ref:`chp-plants`. .. figure:: /images/combined_heat_and_power_plants.png :name: chp-plants :width: 400 - + Spatial distribution of CHP plants in scenario ``eGon2035`` +.. _dec-heat-pumps-ref: Individual heat pumps -~~~~~~~~~~~~~~~~~~~~~ ++++++++++++++++++++++++++ + +Heat pumps supplying individual buildings are first distributed to each medium-voltage grid district. +These capacities are later on further disaggregated to single buildings. Similar to central heat pumps, +individual heat pumps are modeled with a time-dependent coefficient of performance +depending on the temperature data. + +The distribution of the national capacities to each medium-voltage grid district is +proportional to the heat demand outside of district heating grids. + +The heat pump capacity per MV grid district is further disaggregated to individual +buildings based on the building's peak heat demand. +For the eGon2035 scenario this is conducted in the dataset +:py:class:`HeatPumps2035 ` +and for the eGon100RE scenario in the dataset +:py:class:`HeatPumps2050 `. +The heat pump capacity per building is for both scenarios written to database table +:py:class:`demand.egon_hp_capacity_buildings +`. +The peak heat demand per building is written to database table +:py:class:`demand.egon_building_heat_peak_loads +`. + +To disaggregate the total heat pump capacity per MV grid, first, the minimum required +heat pump capacity per building is determined. To this end, an approach from the +`network development plan `_ +(pp.46-47) is used where the heat pump capacity of a building is calculated by multiplying the peak heat +demand of the building by a minimum assumed COP of 1.7 and a flexibility factor of +24/18 that is taking into account that power supply of heat pumps can be interrupted for up +to six hours by the local distribution grid operator. + +After the determination of the minimum required heat pump capacity per building, the +total heat pump capacity per MV grid district is distributed to buildings inside the +grid district based on the minimum required heat pump capacity. +In the eGon2035 scenario, heat pumps and gas boilers can be +used for individual heating. Therefore, it needs to be chosen which buildings +are assigned a heat pump and which are assigned a gas boiler. To this end, +buildings are randomly chosen until the MV grid's total +heat pump capacity is reached (see +:py:func:`determine_buildings_with_hp_in_mv_grid +`). +Buildings with PV rooftop plants are set to be more likely to be assigned a heat pump. In case +the minimum heat pump capacity of all chosen buildings is smaller than the total +heat pump capacity of the MV grid but adding another building would exceed the total +heat pump capacity of the MV grid, the remaining capacity is distributed to all +buildings with heat pumps proportionally to their respective minimum required +heat pump capacity. + +In the eGon100RE scenario, heat pumps are assumed to be the only technology for +individual heating, wherefore all buildings outside of district heating areas are +assigned a heat pump. The total heat pump capacity in the MV grid district is distributed +to all buildings with individual heating proportionally to the minimum required heat pump +capacity. +To assure that the heat pump capacity per MV grid district, that is in case +of the eGon100RE scenario optimised using PyPSA-EUR, is sufficient to meet the +minimum required heat pump capacity of each building, the minimum required heat pump capacity per +MV grid district is given as an input to the PyPSA-EUR optimisation. +Therefore, the minimum heat pump capacity per +building in the eGon100RE scenario is calculated and aggregated per grid district in the dataset +:py:class:`HeatPumpsPypsaEurSec ` +and written to csv file ``input-pypsa-eur-sec/minimum_hp_capacity_mv_grid_100RE.csv``. + +Drawbacks and limitations as well as challenges of the determination of the minimum +required heat pump capacity and the disaggregation to individual buildings +are discussed in the respective dataset docstrings of +:py:class:`HeatPumps2035 `, +:py:class:`HeatPumps2050 ` and +:py:class:`HeatPumpsPypsaEurSec `. + -Heat pumps supplying individual buildings are first distributed to each medium-voltage grid district, these capacities are later on further disaggregated to single buildings. Similar to central heat pumps they are modeled with a time-dependent coefficient of performance depending on the temperature data. -The distribution of the national capacities to each medium-voltage grid district is proportional to the heat demand outside of district heating grids. -@RLI: Distribution on building level Individual gas boilers -~~~~~~~~~~~~~~~~~~~~~~ ++++++++++++++++++++++++ All residential and CTS buildings that are neither supplied by a district heating grid nor an individual heat pump are supplied by gas boilers. The demand time series of these buildings are multiplied by the efficiency of gas boilers and aggregated per methane grid node. diff --git a/docs/data/input_data.rst b/docs/data/input_data.rst index c86ce0c82..406413d8f 100644 --- a/docs/data/input_data.rst +++ b/docs/data/input_data.rst @@ -4,7 +4,7 @@ Data bundle ----------- The data bundle is published on -`zenodo `_. It contains several data +`zenodo `_. It contains several data sets, which serve as a basis for egon-data: * Climate zones in Germany diff --git a/docs/data/mobility_demand.rst b/docs/data/mobility_demand.rst index e3b5310fe..e1e466b41 100644 --- a/docs/data/mobility_demand.rst +++ b/docs/data/mobility_demand.rst @@ -4,28 +4,53 @@ Motorized individual travel ++++++++++++++++++++++++++++ The electricity demand data of motorized individual travel (MIT) for both the eGon2035 -and eGon100RE scenario is set up -in the :py:class:`MotorizedIndividualTravel` +and eGon100RE scenario is set up in the +:py:class:`MotorizedIndividualTravel` dataset. +For the eGon2035, the workflow is visualised in figure :ref:`mit-model`. The workflow +for the eGon100RE scenario is analogous to the workflow for the eGon2035 scenario. +In a first step, pre-generated SimBEV trip data, including information on driving, parking and +(user-oriented) charging times is downloaded. +In the second step, the number of EVs in each MV grid district in the future scenarios is determined. +Last, based on the trip data and the EV numbers, charging time series as well as +time series to model the flexibility of EVs are set up. +In the following, these steps are explained in more detail. -The profiles are generated using a modified version of +.. figure:: /images/eGon_emob_MIT_model.png + :name: mit-model + :width: 800 + + Workflow to set up charging demand data for MIT in the eGon2035 scenario + + +The trip data are generated using a modified version of `SimBEV v0.1.3 `_. -SimBEV generates driving profiles for battery electric vehicles (BEVs) and +SimBEV generates driving and parking profiles for battery electric vehicles (BEVs) and plug-in hybrid electric vehicles (PHEVs) based on MID survey data [MiD2017]_ per RegioStaR7 region type [RegioStaR7_2020]_. -These profiles include driving, parking and (user-oriented) charging times. +The data contain information on energy consumption during the drive, as well as on +the availability of charging points at the parking +location and in case of an available charging point the corresponding charging demand, +charging power and charging point use case +(home charging point, workplace charging point, public charging point and fast charging +point). Different vehicle classes are taken into account whose assumed technical data is given in table :ref:`ev-types-data`. Moreover, charging probabilities for multiple types of charging infrastructure are presumed based on [NOW2020]_ and [Helfenbein2021]_. -Given these assumptions, a pool of 33.000 EVs-types is pre-generated and provided through the data bundle -(see :ref:`data-bundle-ref`) as well as written -to table :py:class:`EgonEvTrip`. -The complete tech data and assumptions of the run can be found in the -metadata_simbev_run.json file, that is provided along with the trip data. - -.. csv-table:: EV types - :header: "Tecnnology", "Size", "Max. charging capacity slow in kW", "Max. charging capacity fast in kW", "Battery capacity in kWh", "Energy consumption in kWh/km" +Given these assumptions, trip data for a pool of 33.000 EV-types is pre-generated and provided through the data bundle +(see :ref:`data-bundle-ref`). The data is as well written to database tables +:py:class:`EgonEvTrip`, +containing information on the driving and parking times of each EV, +and :py:class:`EgonEvPool`, +containing information on the type of EV and RegioStaR7 region the trip data corresponds to. +The complete technical data and assumptions of the SimBEV run can be found in the +metadata_simbev_run.json file, that is provided along with the trip data through the data bundle. +The metadata is as well written to the database table +:py:class:`EgonEvMetadata`. + +.. csv-table:: Differentiated EV types and corresponding technical data + :header: "Technology", "Size", "Max. slow charging capacity in kW", "Max. fast charging capacity in kW", "Battery capacity in kWh", "Energy consumption in kWh/km" :widths: 10, 10, 30, 30, 25, 10 :name: ev-types-data @@ -36,6 +61,74 @@ metadata_simbev_run.json file, that is provided along with the trip data. "PHEV", "medium", 11, 40, 20, 0.1782 "PHEV", "luxury", 11, 120, 30, 0.2138 +The assumed total number of EVs in Germany is 15.1 million in the eGon2035 scenario (according +to the network development plan [NEP2021]_ (Scenario C 2035)) and 25 million in the +eGon100RE scenario (own assumption). +To spatially disaggregate the charging demand, the total number of EVs per EV type +is first allocated to MV grid districts based on vehicle registration [KBA]_ and population [Census]_ data +(see function :py:func:`allocate_evs_numbers`). +The resulting number of EVs per EV type in each MV grid district in each scenario is written to the database table +:py:class:`EgonEvCountMvGridDistrict`. +Each MV grid district is then assigned a random pool of EV profiles from the pre-generated +trip data based on the RegioStaR7 region [RegioStaR7_2020]_ the grid district is assigned to and the counts +per EV type +(see function :py:func:`allocate_evs_to_grid_districts`). +The results are written to table +:py:class:`EgonEvMvGridDistrict`. + +On the basis of the assigned EVs per MV grid district and the trip data, charging demand +time series in each MV grid district can be determined. For inflexible charging +(see lower right in figure :ref:`mit-model`) it is +assumed that the EVs are charged with full power as soon as they arrive at a charging +station until they are fully charged. The respective charging power and demand is obtained +from the trip data. The individual charging demand time series per EV are summed up +to obtain the charging time series per MV grid district. +The generation of time series to model flexible charging of EVs (upper right in figure +:ref:`mit-model`) is described in section :ref:`flexible-charging-ref`. + +For grid analyses of the MV and LV level, the charging demand needs to be further disaggregated +within the MV grid districts. To this end, potential charging sites are determined. +These potential charging sites are then used to allocate the charging demand of the +EVs in each MV grid district to specific charging points. This allocation is not done in +eGon-data but in the `eDisGo `_ tool and further +described in the +`eDisGo documentation `_. + +The determination of potential charging sites is conducted in class +:py:class:`MITChargingInfrastructure`. +The results are written to database table +:py:class:`EgonEmobChargingInfrastructure`. +The approach used to determine potential charging sites is based on the method implemented in +`TracBEV `_. +Four use cases for charging points are differentiated - home, work, public and high-power charging (hpc). +The potential charging sites are determined based on geographical data. Each +possible charging site is assigned an attractivity that represents the likelihood that a +charging point is installed at that site. +The used approach is for each use case shortly described in the following: + +* Home charging: The allocation of home charging stations is based on the number of apartments in each + 100 x 100 m grid given by the Census 2011 [Census]_. The cell with the highest + number of apartments receives the highest attractivity. +* Work charging: The allocation of work charging stations is based on the area classification obtained from + OpenStreetMap [OSM]_ using the landuse key. Work charging stations are allocated to areas + tagged with commercial, retail or industrial. The attractivity of each area + depends on the size of the area as well as the classification. + Commercial areas receive the highest attractivity, followed + by retail areas. Industrial areas are ranked lowest. +* Public charging (slow): The basis for the allocation + of public charging stations are points of interest (POI) from + OSM [OSM]_. POI can be schools, shopping malls, supermarkets, + etc. The attractivity of each POI is determined by empirical + studies conducted in previous projects. +* High-power charging: The basis for the allocation of fast + charging stations are the locations of existing petrol stations + obtained from OSM [OSM]_. The locations are ranked randomly at the moment. + +The necessary input data is downloaded from `zenodo `_. + + +.. _mobility-demand-hdt-ref: + Heavy-duty transport +++++++++++++++++++++ @@ -49,7 +142,7 @@ assumed to be 6.68 kgH2 per 100 km with an additional supply chain leakage rate (see `here `_). For the eGon2035 scenario the ramp-up figures are taken from the -`network development plan (version 2021) `_ +network development plan [NEP2021]_ (Scenario C 2035). According to this, 100,000 e-trucks are expected in Germany in 2035, each covering an average of 100,000 km per year. In total this means 10 Billion km. diff --git a/docs/images/S27-3.png b/docs/images/S27-3.png new file mode 100644 index 000000000..413dd79ed Binary files /dev/null and b/docs/images/S27-3.png differ diff --git a/docs/images/S27-4a.png b/docs/images/S27-4a.png new file mode 100644 index 000000000..7d52a51c5 Binary files /dev/null and b/docs/images/S27-4a.png differ diff --git a/docs/images/eGon_emob_MIT_model.png b/docs/images/eGon_emob_MIT_model.png new file mode 100644 index 000000000..f9e0a32f7 Binary files /dev/null and b/docs/images/eGon_emob_MIT_model.png differ diff --git a/docs/images/flowchart_cts_disaggregation.jpg b/docs/images/flowchart_cts_disaggregation.jpg new file mode 100644 index 000000000..27fdb0cab Binary files /dev/null and b/docs/images/flowchart_cts_disaggregation.jpg differ diff --git a/docs/images/Stromnetz.png b/docs/images/grid_topology_ehv_hv.png similarity index 100% rename from docs/images/Stromnetz.png rename to docs/images/grid_topology_ehv_hv.png diff --git a/docs/literature.rst b/docs/literature.rst index 9bb2b9fff..93889f47e 100644 --- a/docs/literature.rst +++ b/docs/literature.rst @@ -8,6 +8,8 @@ Literature .. [Buettner2022] C. Büttner, J. Amme, J. Endres, A. Malla, B. Schachler, I. Cußmann, Open modeling of electricity and heat demand curves for all residential buildings in Germany, Energy Informatics 5 (1) (2022) 21. doi:10.1186/s42162-022-00201-y. URL https://doi.org/10.1186/s42162-022-00201-y +.. [Brown2018] T. Brown, D. Schlachtenberger, A. Kies, S. Schramm, M. Greiner, Synergies of sector coupling and transmission reinforcement in a cost-optimised, highly renewable European energy system, Energy Volume 160 (2018). URL https://doi.org/10.1016/j.energy.2018.06.222 + .. [Census] S. B. (Destatis), Datensatzbeschreibung ”Haushalte im 100 Meter-Gitter” (2018). URL https://www.zensus2011.de/SharedDocs/Downloads/DE/Pressemitteilung/DemografischeGrunddaten/Datensatzbeschreibung_Haushalt_100m_Gitter.html .. [DAE_store] Danish Energy Agency, Technology Data – Energy storage, First published 2018 by the Danish Energy Agency and Energinet, URL https://ens.dk/en/our-services/projections-and-models/technology-data/technology-data-energy-storage @@ -30,6 +32,8 @@ Literature .. [Huelk2017] L. Hülk, L. Wienholt, I. Cußmann, U.P. Müller, C. Matke, E. Kötter, Allocation of annual electricity consumption and power generation capacities across multiple voltage levels in a high spatial resolution, International Journal of Sustainable Energy Planning and Management Vol. 13 2017 79–92. URL https://journals.aau.dk/index.php/sepm/article/view/1833 +.. [KBA] Kraftfahrt-Bundesamt, Fahrzeugzulassungen (FZ) - Bestand an Kraftfahrzeugen und Kraftfahrzeuganhängern nach Zulassungsbezirken (2021). URL https://www.kba.de/SharedDocs/Downloads/DE/Statistik/Fahrzeuge/FZ1/fz1_2021.xlsx?__blob=publicationFile&v=2 + .. [Kleinhans] D. Kleinhans, Towards a systematic characterization of the potential of demand side management, arXiv (2014), doi: 10.48550/ARXIV.1401.4121. URL https://arxiv.org/abs/1401.4121 .. [MaStR] Bundesnetzagentur für Elektrizität, Gas, Telekommunikation, Post und Eisenbahnen, Marktstammdatenregister - Datendownload (Nov. 2022). URL https://www.marktstammdatenregister.de/MaStR/Datendownload @@ -40,6 +44,8 @@ Literature .. [NEP2021] Übertragungsnetzbetreiber Deutschland (2021): *Netzentwicklungsplan Strom 2035*, Version 2021, 1. Entwurf. 2021. +.. [NEP2021a] Principles for the Expansion Planning of the German Transmission Network https://www.netzentwicklungsplan.de/ + .. [NOW2020] Nationale Leitstelle Ladeinfrastruktur, Ladeinfrastruktur nach 2025/2030: Szenarien für den Markthochlauf (2020). URL https://www.now-gmbh.de/wp-content/uploads/2020/11/Studie_Ladeinfrastruktur-nach-2025-2.pdf .. [OSM] Geofabrik GmbH and OpenStreetMap-Contributors, OpenStreetMap Data Extracts, Stand 01.01.2022 (2022). URL https://download.geofabrik.de/europe/germany-220101.osm.pbf @@ -53,3 +59,5 @@ Literature .. [sEEnergies] T. Fleiter, P. Manz, N. Neuwirth, F. Mildner, K. Persson, U.AND Kermeli, W. Crijns-Graus, C. Rutten, seenergies d5.1 dataset web-app.seenergies arcgis online web-apps hosted by europa-universität flensburg (2020). URL https://tinyurl.com/sEEnergies-D5-1 .. [TYNDP] European Network of Transmission System Operators for Electricity, European Network of Transmission System Operators for Gas, Ten-Year Network Development Plans - “TYNDP 2020 Scenarios” (2020) + +.. [Wulff2020] N. Wulff, F. Steck, H. C. Gils, C. Hoyer-Klick, B. van den Adel, J. E. Anderson, Comparing Power-System and User-Oriented Battery Electric Vehicle Charging Representation and Its Implications on Energy System Modeling, Energies (2020), 13, URL https://doi.org/10.3390/en13051093 diff --git a/docs/reference/egon.data.airflow.rst b/docs/reference/egon.data.airflow.rst index dc39c05bc..17e1653a6 100644 --- a/docs/reference/egon.data.airflow.rst +++ b/docs/reference/egon.data.airflow.rst @@ -3,8 +3,7 @@ airflow ======= +.. toctree:: + :maxdepth: 1 -.. automodule:: egon.data.airflow - :members: - :undoc-members: - :show-inheritance: + egon.data.airflow.dags diff --git a/docs/reference/egon.data.dataset_configuration.rst b/docs/reference/egon.data.dataset_configuration.rst deleted file mode 100644 index 7d3de7314..000000000 --- a/docs/reference/egon.data.dataset_configuration.rst +++ /dev/null @@ -1,7 +0,0 @@ -dataset\_configuration -====================== - -.. automodule:: egon.data.dataset_configuration - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/reference/egon.data.rst b/docs/reference/egon.data.rst index c35dbe9ef..1ae732748 100644 --- a/docs/reference/egon.data.rst +++ b/docs/reference/egon.data.rst @@ -10,7 +10,6 @@ egon.data egon.data.airflow egon.data.cli egon.data.config - egon.data.dataset_configuration egon.data.datasets egon.data.db egon.data.metadata diff --git a/setup.py b/setup.py index c073ae376..22b96435c 100755 --- a/setup.py +++ b/setup.py @@ -59,7 +59,6 @@ def read(*names, **kwargs): "Operating System :: Microsoft :: Windows", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: Implementation :: CPython", # uncomment if you test on these interpreters: @@ -79,7 +78,7 @@ def read(*names, **kwargs): keywords=[ # eg: 'keyword1', 'keyword2', 'keyword3', ], - python_requires=">=3.7", + python_requires=">=3.8", install_requires=[ # eg: 'aspectlib==1.1.1', 'six>=1.7', "apache-airflow>=1.10.14,<2.0", # See accompanying commit message diff --git a/src/egon/data/datasets/DSM_cts_ind.py b/src/egon/data/datasets/DSM_cts_ind.py index a74ae11da..abad1b823 100644 --- a/src/egon/data/datasets/DSM_cts_ind.py +++ b/src/egon/data/datasets/DSM_cts_ind.py @@ -5,7 +5,7 @@ The sum of the individual time series is a more accurate value than the aggregated time series used so far and should replace it in the future. Since the deviations are relatively small, a tolerance is currently accepted in the -sanity checks. See [#1120](https://github.com/openego/eGon-data/issues/1120) +sanity checks. See `#1120 `_ for updates. """ from sqlalchemy import ARRAY, Column, Float, Integer, String @@ -210,6 +210,7 @@ def cts_data_import(cts_cool_vent_ac_share): """ Import CTS data necessary to identify DSM-potential. + Parameters ---------- cts_share: float Share of cooling, ventilation and AC in CTS demand @@ -251,7 +252,9 @@ def cts_data_import(cts_cool_vent_ac_share): def ind_osm_data_import(ind_vent_cool_share): """ Import industry data per osm-area necessary to identify DSM-potential. - ---------- + + Parameters + ---------- ind_share: float Share of considered application in industry demand """ @@ -287,7 +290,9 @@ def ind_osm_data_import(ind_vent_cool_share): def ind_osm_data_import_individual(ind_vent_cool_share): """ Import industry data per osm-area necessary to identify DSM-potential. - ---------- + + Parameters + ---------- ind_share: float Share of considered application in industry demand """ @@ -323,7 +328,9 @@ def ind_osm_data_import_individual(ind_vent_cool_share): def ind_sites_vent_data_import(ind_vent_share, wz): """ Import industry sites necessary to identify DSM-potential. - ---------- + + Parameters + ---------- ind_vent_share: float Share of considered application in industry demand wz: int @@ -360,7 +367,9 @@ def ind_sites_vent_data_import(ind_vent_share, wz): def ind_sites_vent_data_import_individual(ind_vent_share, wz): """ Import industry sites necessary to identify DSM-potential. - ---------- + + Parameters + ---------- ind_vent_share: float Share of considered application in industry demand wz: int @@ -520,9 +529,10 @@ def ind_sites_data_import(): def calculate_potentials(s_flex, s_util, s_inc, s_dec, delta_t, dsm): """ Calculate DSM-potential per bus using the methods by Heitkoetter et. al.: - https://doi.org/10.1016/j.adapen.2020.100001 + https://doi.org/10.1016/j.adapen.2020.100001 + Parameters - ---------- + ---------- s_flex: float Feasability factor to account for socio-technical restrictions s_util: float @@ -615,8 +625,9 @@ def create_dsm_components( ): """ Create components representing DSM. + Parameters - ---------- + ---------- con : Connection to database p_max: DataFrame @@ -990,8 +1001,8 @@ def delete_dsm_entries(carrier): new ones. Parameters - ---------- - carrier: str + ---------- + carrier: str Remark in column 'carrier' identifying DSM-potential """ @@ -1059,14 +1070,15 @@ def dsm_cts_ind( ): """ Execute methodology to create and implement components for DSM considering + a) CTS per osm-area: combined potentials of cooling, ventilation and air - conditioning + conditioning b) Industry per osm-are: combined potentials of cooling and ventilation c) Industrial Sites: potentials of ventilation in sites of - "Wirtschaftszweig" (WZ) 23 + "Wirtschaftszweig" (WZ) 23 d) Industrial Sites: potentials of sites specified by subsectors - identified by Schmidt (https://zenodo.org/record/3613767#.YTsGwVtCRhG): - Paper, Recycled Paper, Pulp, Cement + identified by Schmidt (https://zenodo.org/record/3613767#.YTsGwVtCRhG): + Paper, Recycled Paper, Pulp, Cement Modelled using the methods by Heitkoetter et. al.: https://doi.org/10.1016/j.adapen.2020.100001 @@ -1374,14 +1386,15 @@ def dsm_cts_ind_individual( ): """ Execute methodology to create and implement components for DSM considering + a) CTS per osm-area: combined potentials of cooling, ventilation and air - conditioning + conditioning b) Industry per osm-are: combined potentials of cooling and ventilation c) Industrial Sites: potentials of ventilation in sites of - "Wirtschaftszweig" (WZ) 23 + "Wirtschaftszweig" (WZ) 23 d) Industrial Sites: potentials of sites specified by subsectors - identified by Schmidt (https://zenodo.org/record/3613767#.YTsGwVtCRhG): - Paper, Recycled Paper, Pulp, Cement + identified by Schmidt (https://zenodo.org/record/3613767#.YTsGwVtCRhG): + Paper, Recycled Paper, Pulp, Cement Modelled using the methods by Heitkoetter et. al.: https://doi.org/10.1016/j.adapen.2020.100001 diff --git a/src/egon/data/datasets/ch4_prod.py b/src/egon/data/datasets/ch4_prod.py index 786d879ea..8cf775d25 100755 --- a/src/egon/data/datasets/ch4_prod.py +++ b/src/egon/data/datasets/ch4_prod.py @@ -287,25 +287,26 @@ def import_gas_generators(scn_name="eGon2035"): To insert the gas production units into the database, the following steps are followed: - * cleaning of the database table grid.egon_etrago_generator of the - CH4 generators of the specific scenario (eGon2035), - * call of the functions :py:func:`load_NG_generators` and - :py:func:`load_biogas_generators` that respectively return - dataframes containing the natural- an bio-gas production units - in Germany, - * attribution of the bus_id to which each generator is connected - (call the function :func:`assign_gas_bus_id ` - from :py:mod:`egon.data.db `), - * aggregation of the CH4 productions with same properties at the - same bus. The properties that should be the same in order that - different generators are aggregated are: - * scenario - * carrier - * marginal cost: this parameter differentiates the natural gas - generators from the biogas generators, - * addition of the missing columns: scn_name, carrier and - generator_id, - * insertion of the generators into the database. + * cleaning of the database table grid.egon_etrago_generator of the + CH4 generators of the specific scenario (eGon2035), + * call of the functions :py:func:`load_NG_generators` and + :py:func:`load_biogas_generators` that respectively return + dataframes containing the natural- an bio-gas production units + in Germany, + * attribution of the bus_id to which each generator is connected + (call the function :func:`assign_gas_bus_id ` + from :py:mod:`egon.data.db `), + * aggregation of the CH4 productions with same properties at the + same bus. The properties that should be the same in order that + different generators are aggregated are: + + * scenario + * carrier + * marginal cost: this parameter differentiates the natural gas + generators from the biogas generators, + * addition of the missing columns: scn_name, carrier and + generator_id, + * insertion of the generators into the database. Parameters ---------- diff --git a/src/egon/data/datasets/ch4_storages.py b/src/egon/data/datasets/ch4_storages.py index 18e1db935..d6003b6d3 100755 --- a/src/egon/data/datasets/ch4_storages.py +++ b/src/egon/data/datasets/ch4_storages.py @@ -271,15 +271,16 @@ def insert_ch4_stores(scn_name): Insert non extendable gas stores for specific scenario in Germany by executing the following steps: - * Clean the database. - * For CH4 stores, call the functions - :py:func:`import_installed_ch4_storages` to get the CH4 - cavern stores and :py:func:`import_ch4_grid_capacity` to - get the CH4 stores modelling the storage capacity of the - grid. - * Aggregate the stores attached to the same bus. - * Add the missing columns: store_id, scn_name, carrier, e_cyclic. - * Insert the stores into the database. + + * Clean the database. + * For CH4 stores, call the functions + :py:func:`import_installed_ch4_storages` to get the CH4 + cavern stores and :py:func:`import_ch4_grid_capacity` to + get the CH4 stores modelling the storage capacity of the + grid. + * Aggregate the stores attached to the same bus. + * Add the missing columns: store_id, scn_name, carrier, e_cyclic. + * Insert the stores into the database. Parameters ---------- @@ -302,12 +303,12 @@ def insert_ch4_stores(scn_name): # Clean table db.execute_sql( f""" - DELETE FROM {target['stores']['schema']}.{target['stores']['table']} + DELETE FROM {target['stores']['schema']}.{target['stores']['table']} WHERE "carrier" = 'CH4' AND scn_name = '{scn_name}' AND bus IN ( SELECT bus_id FROM {source['buses']['schema']}.{source['buses']['table']} - WHERE scn_name = '{scn_name}' + WHERE scn_name = '{scn_name}' AND country = 'DE' ); """ diff --git a/src/egon/data/datasets/district_heating_areas/__init__.py b/src/egon/data/datasets/district_heating_areas/__init__.py index 660692443..690078a05 100644 --- a/src/egon/data/datasets/district_heating_areas/__init__.py +++ b/src/egon/data/datasets/district_heating_areas/__init__.py @@ -353,14 +353,6 @@ def area_grouping( join: geopandas.geodataframe.GeoDataFrame cell polygons with area id - Notes - ----- - None - - TODO - ---- - - """ buffer_distance = distance + 1 diff --git a/src/egon/data/datasets/electricity_demand_timeseries/cts_buildings.py b/src/egon/data/datasets/electricity_demand_timeseries/cts_buildings.py index 748ddac94..c15518bc5 100644 --- a/src/egon/data/datasets/electricity_demand_timeseries/cts_buildings.py +++ b/src/egon/data/datasets/electricity_demand_timeseries/cts_buildings.py @@ -127,12 +127,13 @@ class CtsDemandBuildings(Dataset): Generates CTS electricity and heat demand time series for scenarios in 2035 and 2050 assigned to OSM-buildings. - Disaggregation of CTS heat & electricity demand time series from MV Substation - to census cells via annual demand and then to OSM buildings via + Disaggregation of CTS heat & electricity demand time series from HV-MV substation + to census cells via annual demand per census cell and then to OSM buildings via amenity tags or randomly if no sufficient OSM-data is available in the respective census cell. If no OSM-buildings or synthetic residential buildings are available new synthetic 5x5m buildings are generated. + For more information see data documentation on :ref:`disagg-cts-elec-ref`. *Dependencies* * :py:class:`OsmBuildingsStreets ` @@ -142,53 +143,43 @@ class CtsDemandBuildings(Dataset): *Resulting tables* * :py:class:`openstreetmap.osm_buildings_synthetic ` is extended - * :py:class:`openstreetmap.egon_cts_buildings is created + * :py:class:`openstreetmap.egon_cts_buildings ` is created * :py:class:`demand.egon_cts_electricity_demand_building_share ` is created * :py:class:`demand.egon_cts_heat_demand_building_share ` is created * :py:class:`demand.egon_building_electricity_peak_loads ` is extended * :py:class:`boundaries.egon_map_zensus_mvgd_buildings ` is extended. - **The following datasets from the database are mainly used for creation:** * `openstreetmap.osm_buildings_filtered`: - Table of OSM-buildings filtered by tags to selecting residential and cts - buildings only. + Table of OSM-buildings filtered by tags to selecting residential and cts + buildings only. * `openstreetmap.osm_amenities_shops_filtered`: - Table of OSM-amenities filtered by tags to select cts only. + Table of OSM-amenities filtered by tags to select cts only. * `openstreetmap.osm_amenities_not_in_buildings_filtered`: - Table of amenities which do not intersect with any building from - `openstreetmap.osm_buildings_filtered` + Table of amenities which do not intersect with any building from + `openstreetmap.osm_buildings_filtered` * `openstreetmap.osm_buildings_synthetic`: - Table of synthetic residential buildings + Table of synthetic residential buildings * `boundaries.egon_map_zensus_buildings_filtered_all`: - Mapping table of census cells and buildings filtered even if population - in census cell = 0. + Mapping table of census cells and buildings filtered even if population + in census cell = 0. * `demand.egon_demandregio_zensus_electricity`: - Table of annual electricity load demand for residential and cts at census - cell level. Residential load demand is derived from aggregated residential - building profiles. DemandRegio CTS load demand at NUTS3 is distributed to - census cells linearly to heat demand from peta5. + Table of annual electricity load demand for residential and cts at census + cell level. Residential load demand is derived from aggregated residential + building profiles. DemandRegio CTS load demand at NUTS3 is distributed to + census cells linearly to heat demand from peta5. * `demand.egon_peta_heat`: - Table of annual heat load demand for residential and cts at census cell - level from peta5. + Table of annual heat load demand for residential and cts at census cell + level from peta5. * `demand.egon_etrago_electricity_cts`: - Scaled cts electricity time series for every MV substation. Derived from - DemandRegio SLP for selected economic sectors at nuts3. Scaled with annual - demand from `demand.egon_demandregio_zensus_electricity` + Scaled cts electricity time series for every MV substation. Derived from + DemandRegio SLP for selected economic sectors at nuts3. Scaled with annual + demand from `demand.egon_demandregio_zensus_electricity` * `demand.egon_etrago_heat_cts`: - Scaled cts heat time series for every MV substation. Derived from - DemandRegio SLP Gas for selected economic sectors at nuts3. Scaled with - annual demand from `demand.egon_peta_heat`. - - **What is the goal?** - - To disaggregate cts heat and electricity time series from MV substation level - to geo-referenced buildings, the annual demand from DemandRegio and Peta5 is - used to identify census cells with load demand. We use Openstreetmap data and - filter tags to identify buildings and count the amenities within. The number - of amenities and the annual demand serve to assign a demand share of the MV - substation profile to the building. + Scaled cts heat time series for every MV substation. Derived from + DemandRegio SLP Gas for selected economic sectors at nuts3. Scaled with + annual demand from `demand.egon_peta_heat`. **What is the challenge?** @@ -202,41 +193,6 @@ class CtsDemandBuildings(Dataset): be addressed. For example: not yet tagged buildings or amenities in OSM, or building shapes exceeding census cells. - - **How are these datasets combined?** - - - The methodology for heat and electricity is the same and only differs in the - annual demand and MV/HV Substation profile. In a previous dataset - (openstreetmap), we filter all OSM buildings and amenities for tags, we relate - to the cts sector. Amenities are mapped to intersecting buildings and then - intersected with the annual demand which exists at census cell level. We obtain - census cells with demand and amenities and without amenities. If there is no - data on amenities, n synthetic ones are assigned to existing buildings. We use - the median value of amenities/census cell for n and all filtered buildings + - synthetic residential buildings. If no building data is available a synthetic - buildings is randomly generated. This also happens for amenities which couldn't - be assigned to any osm building. All census cells with an annual demand are - covered this way, and we obtain four different categories of buildings with - amenities: - - * Buildings with amenities - * Synthetic buildings with amenities - * Buildings with synthetic amenities - * Synthetics buildings with synthetic amenities - - The amenities are summed per census cell (of amenity) and building to derive - the building amenity share per census cell. Multiplied with the annual demand, - we receive the profile demand share for each cell. Some buildings exceed the - census cell shape and have amenities in different cells although mapped to one - building only. To have unique buildings the demand share is summed once more - per building id. This factor can now be used to obtain the profile for each - building. - - A schematic flow chart exist in the correspondent issue #671: - https://github.com/openego/eGon-data/issues/671#issuecomment-1260740258 - - **What are central assumptions during the data processing?** * We assume OSM data to be the most reliable and complete open source dataset. @@ -245,7 +201,6 @@ class CtsDemandBuildings(Dataset): * Missing OSM buildings are generated for each amenity. * Missing amenities are generated by median value of amenities/census cell. - **Drawbacks and limitations of the data** * Shape of profiles for each building is similar within a MVGD and only scaled @@ -446,9 +401,9 @@ def buildings_with_amenities(): """ Amenities which are assigned to buildings are determined and grouped per building and zensus cell. Buildings covering multiple cells therefore - exists multiple times but in different zensus cells. This is necessary to + exist multiple times but in different zensus cells. This is necessary to cover as many cells with a cts demand as possible. If buildings exist in - multiple mvgds (bus_id) , only the amenities within the same as the + multiple mvgds (bus_id), only the amenities within the same as the building centroid are kept. If as a result, a census cell is uncovered by any buildings, a synthetic amenity is placed. The buildings are aggregated afterwards during the calculation of the profile_share. @@ -1210,7 +1165,7 @@ def cts_buildings(): building nor amenity is available, random synthetic buildings are generated. The demand share is stored in the database. - Note: + Note ----- Cells with CTS demand, amenities and buildings do not change within the scenarios, only the demand itself. Therefore scenario eGon2035 diff --git a/src/egon/data/datasets/electricity_demand_timeseries/hh_buildings.py b/src/egon/data/datasets/electricity_demand_timeseries/hh_buildings.py index 89ac83c50..fd873baca 100755 --- a/src/egon/data/datasets/electricity_demand_timeseries/hh_buildings.py +++ b/src/egon/data/datasets/electricity_demand_timeseries/hh_buildings.py @@ -651,8 +651,8 @@ def map_houseprofiles_to_buildings(): buildings and supplementary data as well as the mapping table is stored in the db. - Tables: - ---------- + **Tables** + synthetic_buildings: schema: openstreetmap tablename: osm_buildings_synthetic @@ -661,8 +661,6 @@ def map_houseprofiles_to_buildings(): schema: demand tablename: egon_household_electricity_profile_of_buildings - Notes - ----- """ # egon_map_zensus_buildings_residential = Table( @@ -757,13 +755,15 @@ def map_houseprofiles_to_buildings(): class setup(Dataset): """ - Household electricity demand time series for scenarios in 2035 and 2050 - assigned to OSM-buildings. + Household electricity demand profiles for scenarios in 2035 and 2050 + assigned to buildings. Assignment of household electricity demand timeseries to OSM buildings and generation of randomly placed synthetic 5x5m buildings if no sufficient OSM-data available in the respective census cell. + For more information see data documentation on :ref:`electricity-demand-ref`. + *Dependencies* * :py:func:`houseprofiles_in_census_cells ` @@ -798,31 +798,19 @@ class setup(Dataset): **What is the goal?** - To assign every household demand timeseries, which already exist at cell - level, to a specific OSM building. + To assign every household demand profile allocated each census cell to a + specific building. **What is the challenge?** The census and the OSM dataset differ from each other. The census uses statistical methods and therefore lacks accuracy at high spatial - resolution. The OSM datasets is community based dataset which is + resolution. The OSM dataset is a community based dataset which is extended throughout and does not claim to be complete. By merging these datasets inconsistencies need to be addressed. For example: not yet tagged buildings in OSM or new building areas not considered in census 2011. - **How are these datasets combined?** - - The assignment of household demand timeseries to buildings takes place - at cell level. Within each cell a pool of profiles exists, produced by - the 'HH Demand" module. These profiles are randomly assigned to a - filtered list of OSM buildings within this cell. Every profile is - assigned to a building and every building get a profile assigned if - there is enough households by the census data. If there are more - profiles than buildings, all additional profiles are randomly assigned. - Therefore, multiple profiles can be assigned to one building, making it a - multi-household building. - **What are central assumptions during the data processing?** * Mapping zensus data to OSM data is not trivial. @@ -840,11 +828,10 @@ class setup(Dataset): is ceiled to the next higher integer. Ceiling is applied to avoid rounding to amount of 0 buildings. - * As this datasets is a cascade after profile assignement at census - cells also check drawbacks and limitations in hh_profiles.py. + * As this dataset uses the load profile assignment at census cell level + conducted in hh_profiles.py, also check drawbacks and limitations in that module. - Example Query - ----- + **Example Query** * Get a list with number of houses, households and household types per census cell diff --git a/src/egon/data/datasets/electricity_demand_timeseries/hh_profiles.py b/src/egon/data/datasets/electricity_demand_timeseries/hh_profiles.py index 6598e7695..e2166cec1 100644 --- a/src/egon/data/datasets/electricity_demand_timeseries/hh_profiles.py +++ b/src/egon/data/datasets/electricity_demand_timeseries/hh_profiles.py @@ -137,6 +137,7 @@ class HouseholdDemands(Dataset): (see :func:`get_iee_hh_demand_profiles_raw`) * Spatial information about people living in households by Zensus 2011 at federal state level + * Type of household (family status) * Age * Number of people @@ -165,6 +166,7 @@ class HouseholdDemands(Dataset): * Spatial information about people living in households by zensus (2011) at federal state NUTS1 level `df_zensus` is aggregated to be compatible to IEE household profile specifications. + * exclude kids and reduce to adults and seniors * group as defined in `HH_TYPES` * convert data from people living in households to number of households @@ -217,6 +219,7 @@ class HouseholdDemands(Dataset): specific population value. *Helper functions* + * To access the DB, select specific profiles at various aggregation levels use :py:func:`get_hh_profiles_from_db` * To access the DB, select specific profiles at various aggregation levels @@ -447,7 +450,7 @@ def get_census_households_nuts1_raw(): * Choose table code: "1000A-3016" with title "Personen: Alter (11 Altersklassen) - Größe des privaten Haushalts - Typ des privaten Haushalts (nach Familien/Lebensform)" - - Change setting "GEOLK1" to "Bundesländer (16)" + * Change setting "GEOLK1" to "Bundesländer (16)" Data would be available in higher resolution ("Landkreise und kreisfreie Städte (412)"), but only after registration. @@ -1135,15 +1138,27 @@ def refine_census_data_at_cell_level( IEE profiles specifications. To do this, proportionate allocation is applied at nuts1 level and within household type clusters. - .. csv-table:: Mapping table - :header: "characteristics_code", "characteristics_text", "mapping" - - "1", "Einpersonenhaushalte (Singlehaushalte)", "SR; SO" - "2", "Paare ohne Kind(er)", "PR; PO" - "3", "Paare mit Kind(ern)", "P1; P2; P3" - "4", "Alleinerziehende Elternteile", "SK" - "5", "Mehrpersonenhaushalte ohne Kernfamilie", "OR; OO" - + .. list-table:: Mapping table + :header-rows: 1 + + * - characteristics_code + - characteristics_text + - mapping + * - 1 + - Einpersonenhaushalte (Singlehaushalte) + - SR; SO + * - 2 + - Paare ohne Kind(er) + - PR; PO + * - 3 + - Paare mit Kind(ern) + - P1; P2; P3 + * - 4 + - Alleinerziehende Elternteile + - SK + * - 5 + - Mehrpersonenhaushalte ohne Kernfamilie + - OR; OO Parameters ---------- diff --git a/src/egon/data/datasets/emobility/heavy_duty_transport/__init__.py b/src/egon/data/datasets/emobility/heavy_duty_transport/__init__.py index 46a1e51ca..0d0863f36 100644 --- a/src/egon/data/datasets/emobility/heavy_duty_transport/__init__.py +++ b/src/egon/data/datasets/emobility/heavy_duty_transport/__init__.py @@ -81,7 +81,9 @@ def download_hgv_data(): class HeavyDutyTransport(Dataset): """ Class for preparation of static and timeseries data for heavy duty transport. - + + For more information see data documentation on :ref:`mobility-demand-hdt-ref`. + *Dependencies* * :py:class:`Vg250 ` * :py:class:`EtragoSetup ` @@ -101,40 +103,6 @@ class HeavyDutyTransport(Dataset): The config of this dataset can be found in *datasets.yml* in section *mobility_hgv*. - *Scenarios and variations* - - Assumptions can be changed within the *datasets.yml*. - - In the context of the eGon project, it is assumed that e-trucks will be - completely hydrogen-powered and in both scenarios the hydrogen consumption is - assumed to be 6.68 kg H2 per 100 km with an additional - `supply chain leakage rate of 0.5 % - `_. - - ### Scenario NEP C 2035 - - The ramp-up figures are taken from - `Scenario C 2035 Grid Development Plan 2021-2035 - `_. According to this, 100,000 e-trucks are - expected in Germany in 2035, each covering an average of 100,000 km per year. - In total this means 10 billion km. - - ### Scenario eGon100RE - - In the case of the eGon100RE scenario it is assumed that the HGV traffic is - completely hydrogen-powered. The total freight traffic with 40 Billion km is - taken from the - `BMWK Langfristszenarien GHG-emission free scenarios (SNF > 12 t zGG) - `_. - - *Methodology* - - Using a Voronoi interpolation, the censuses of the BASt data is distributed - according to the area fractions of the Voronoi fields within each mv grid or - any other geometries like NUTS-3. - """ #: name: str = "HeavyDutyTransport" diff --git a/src/egon/data/datasets/emobility/motorized_individual_travel/db_classes.py b/src/egon/data/datasets/emobility/motorized_individual_travel/db_classes.py index 95744835b..64096febb 100644 --- a/src/egon/data/datasets/emobility/motorized_individual_travel/db_classes.py +++ b/src/egon/data/datasets/emobility/motorized_individual_travel/db_classes.py @@ -31,8 +31,8 @@ class EgonEvPool(Base): Each row is one EV, uniquely defined by either (`ev_id`) or (`rs7_id`, `type`, `simbev_id`). - Columns - ------- + **Columns** + ev_id: Unique id of EV rs7_id: @@ -73,8 +73,8 @@ class EgonEvTrip(Base): Each row is one event of a specific electric vehicle which is uniquely defined by `rs7_id`, `ev_id` and `event_id`. - Columns - ------- + **Columns** + scenario: Scenario event_id: diff --git a/src/egon/data/datasets/emobility/motorized_individual_travel/ev_allocation.py b/src/egon/data/datasets/emobility/motorized_individual_travel/ev_allocation.py index 61c2ecfb4..471395398 100644 --- a/src/egon/data/datasets/emobility/motorized_individual_travel/ev_allocation.py +++ b/src/egon/data/datasets/emobility/motorized_individual_travel/ev_allocation.py @@ -403,7 +403,7 @@ def calc_evs_per_grid_district(ev_data_muns): def allocate_evs_numbers(): """Allocate electric vehicles to different spatial levels. - Accocation uses today's vehicles registration data per registration + Allocation uses today's vehicles registration data per registration district from KBA and scales scenario's EV targets (BEV and PHEV) linearly using population. Furthermore, a RegioStaR7 code (BMVI) is assigned. diff --git a/src/egon/data/datasets/emobility/motorized_individual_travel/model_timeseries.py b/src/egon/data/datasets/emobility/motorized_individual_travel/model_timeseries.py index 3496a4a9e..8a9fa5e78 100644 --- a/src/egon/data/datasets/emobility/motorized_individual_travel/model_timeseries.py +++ b/src/egon/data/datasets/emobility/motorized_individual_travel/model_timeseries.py @@ -2,13 +2,16 @@ Generate timeseries for eTraGo and pypsa-eur-sec Call order - * generate_model_data_eGon2035() / generate_model_data_eGon100RE() - * generate_model_data() - * generate_model_data_grid_district() - * load_evs_trips() - * data_preprocessing() - * generate_load_time_series() - * write_model_data_to_db() +* generate_model_data_eGon2035() / generate_model_data_eGon100RE() + + * generate_model_data() + + * generate_model_data_grid_district() + + * load_evs_trips() + * data_preprocessing() + * generate_load_time_series() + * write_model_data_to_db() Notes ----- @@ -23,6 +26,7 @@ linearly extrapolated based upon https://nationale-leitstelle.de/wp-content/pdf/broschuere-lis-2025-2030-final.pdf (p.92): + * eGon2035: home=0.8, work=1.0 * eGon100RE: home=1.0, work=1.0 """ diff --git a/src/egon/data/datasets/emobility/motorized_individual_travel_charging_infrastructure/__init__.py b/src/egon/data/datasets/emobility/motorized_individual_travel_charging_infrastructure/__init__.py index 96a16e042..b8ede626e 100644 --- a/src/egon/data/datasets/emobility/motorized_individual_travel_charging_infrastructure/__init__.py +++ b/src/egon/data/datasets/emobility/motorized_individual_travel_charging_infrastructure/__init__.py @@ -107,6 +107,8 @@ class MITChargingInfrastructure(Dataset): home, work, public and hpc per MV grid district * Write results to DB + For more information see data documentation on :ref:`mobility-demand-mit-ref`. + *Dependencies* * :py:class:`MvGridDistricts ` * :py:func:`map_houseprofiles_to_buildings ` diff --git a/src/egon/data/datasets/era5.py b/src/egon/data/datasets/era5.py index ffd6085fe..ec7f9eb3b 100644 --- a/src/egon/data/datasets/era5.py +++ b/src/egon/data/datasets/era5.py @@ -54,6 +54,10 @@ def __init__(self, dependencies): class EgonEra5Cells(Base): + """ + Class definition of table supply.egon_era5_weather_cells. + + """ __tablename__ = "egon_era5_weather_cells" __table_args__ = {"schema": "supply"} w_id = Column(Integer, primary_key=True) @@ -62,6 +66,10 @@ class EgonEra5Cells(Base): class EgonRenewableFeedIn(Base): + """ + Class definition of table supply.egon_era5_renewable_feedin. + + """ __tablename__ = "egon_era5_renewable_feedin" __table_args__ = {"schema": "supply"} w_id = Column(Integer, primary_key=True) diff --git a/src/egon/data/datasets/fill_etrago_gen.py b/src/egon/data/datasets/fill_etrago_gen.py index cae8fff4f..a7c3533a0 100644 --- a/src/egon/data/datasets/fill_etrago_gen.py +++ b/src/egon/data/datasets/fill_etrago_gen.py @@ -21,9 +21,9 @@ class Egon_etrago_gen(Dataset): *Resulting tables* * :py:class:`grid.egon_etrago_generator - ` is extended + ` is extended * :py:class:`grid.egon_etrago_generator_timeseries - ` is filled + ` is filled """ #: diff --git a/src/egon/data/datasets/gas_grid.py b/src/egon/data/datasets/gas_grid.py index 6fc3c18bd..f4338b41a 100755 --- a/src/egon/data/datasets/gas_grid.py +++ b/src/egon/data/datasets/gas_grid.py @@ -3,7 +3,7 @@ The module contains code used to insert the methane grid into the database The central module contains all code dealing with the import of data -from SciGRID_gas (IGGIELGN dataset) and inserting the CH4 buses and links +from SciGRID_gas (IGGIELGN dataset) and inserting the CH4 buses and links into the database for the scenarios eGon2035 and eGon100RE. The SciGRID_gas data downloaded with :py:func:`download_SciGRID_gas_data` @@ -77,11 +77,12 @@ def download_SciGRID_gas_data(): The following data for CH4 is downloaded into the folder ./datasets/gas_data/data: - * Buses (file IGGIELGN_Nodes.csv), - * Pipelines (file IGGIELGN_PipeSegments.csv), - * Productions (file IGGIELGN_Productions.csv), - * Storages (file IGGIELGN_Storages.csv), - * LNG terminals (file IGGIELGN_LNGs.csv). + + * Buses (file IGGIELGN_Nodes.csv), + * Pipelines (file IGGIELGN_PipeSegments.csv), + * Productions (file IGGIELGN_Productions.csv), + * Storages (file IGGIELGN_Storages.csv), + * LNG terminals (file IGGIELGN_LNGs.csv). For more information on this data refer, to the `SciGRID_gas IGGIELGN documentation `_. @@ -198,11 +199,12 @@ def insert_CH4_nodes_list(gas_nodes_list): Insert the list of German CH4 nodes into the database by executing the following steps: - * Receive the buses as parameter (from SciGRID_gas IGGIELGN data) - * Add the missing information: scn_name and carrier - * Clean the database table grid.egon_etrago_bus of the - CH4 buses of the specific scenario (eGon2035) in Germany - * Insert the buses in the table grid.egon_etrago_bus + + * Receive the buses as parameter (from SciGRID_gas IGGIELGN data) + * Add the missing information: scn_name and carrier + * Clean the database table grid.egon_etrago_bus of the + CH4 buses of the specific scenario (eGon2035) in Germany + * Insert the buses in the table grid.egon_etrago_bus Parameters ---------- @@ -299,18 +301,19 @@ def define_gas_buses_abroad(scn_name="eGon2035"): Define central CH4 buses in foreign countries for eGon2035 For the scenario eGon2035, define central CH4 buses in foreign - countries. The considered foreign countries are the direct + countries. The considered foreign countries are the direct neighbouring countries, with the addition of Russia that is considered as a source of fossil CH4. Therefore, the following steps are executed: - * Definition of the foreign buses with the function - :py:func:`central_buses_egon100 ` from - the module :py:mod:`electrical_neighbours ` - * Removal of the superfluous buses in order to have only one bus - in each neighbouring country - * Removal of the irrelevant columns - * Addition of the missing information: scn_name and carrier - * Attribution of an id to each bus + + * Definition of the foreign buses with the function + :py:func:`central_buses_egon100 ` from + the module :py:mod:`electrical_neighbours ` + * Removal of the superfluous buses in order to have only one bus + in each neighbouring country + * Removal of the irrelevant columns + * Addition of the missing information: scn_name and carrier + * Attribution of an id to each bus Parameters ---------- @@ -396,11 +399,11 @@ def insert_gas_buses_abroad(scn_name="eGon2035"): """ Insert CH4 buses in neighbouring countries into database for eGon2035 - * Definition of the CH4 buses abroad with the function - :py:func:`define_gas_buses_abroad` - * Cleaning of the database table grid.egon_etrago_bus of the - foreign CH4 buses of the specific scenario (eGon2035) - * Insertion of the neighbouring buses into the table grid.egon_etrago_bus. + * Definition of the CH4 buses abroad with the function + :py:func:`define_gas_buses_abroad` + * Cleaning of the database table grid.egon_etrago_bus of the + foreign CH4 buses of the specific scenario (eGon2035) + * Insertion of the neighbouring buses into the table grid.egon_etrago_bus. Parameters ---------- @@ -458,10 +461,11 @@ def define_gas_pipeline_list( related to the pipeline diameter given in the SciGRID_gas dataset. The manual corrections allow to: - * Delete gas pipelines disconnected of the rest of the gas grid - * Connect one pipeline (also connected to Norway) disconnected of - the rest of the gas grid - * Correct countries of some erroneous pipelines + + * Delete gas pipelines disconnected of the rest of the gas grid + * Connect one pipeline (also connected to Norway) disconnected of + the rest of the gas grid + * Correct countries of some erroneous pipelines Parameters ---------- @@ -827,7 +831,7 @@ def insert_gas_pipeline_list(gas_pipelines_list, scn_name="eGon2035"): Dataframe containing the gas pipelines in Germany scn_name : str Name of the scenario - + Returns ------- None @@ -917,16 +921,17 @@ def insert_gas_data(): This function imports the methane data (buses and pipelines) for eGon2035, by executing the following steps: - * Download the SciGRID_gas datasets with the function :py:func:`download_SciGRID_gas_data` - * Define CH4 buses with the function :py:func:`define_gas_nodes_list` - * Insert the CH4 buses in Germany into the database with the - function :py:func:`insert_CH4_nodes_list` - * Insert the CH4 buses abroad into the database with the function - :py:func:`insert_gas_buses_abroad` - * Insert the CH4 links representing the CH4 pipeline into the - database with the function :py:func:`insert_gas_pipeline_list` - * Remove the isolated CH4 buses directly from the database using - the function :py:func:`remove_isolated_gas_buses` + + * Download the SciGRID_gas datasets with the function :py:func:`download_SciGRID_gas_data` + * Define CH4 buses with the function :py:func:`define_gas_nodes_list` + * Insert the CH4 buses in Germany into the database with the + function :py:func:`insert_CH4_nodes_list` + * Insert the CH4 buses abroad into the database with the function + :py:func:`insert_gas_buses_abroad` + * Insert the CH4 links representing the CH4 pipeline into the + database with the function :py:func:`insert_gas_pipeline_list` + * Remove the isolated CH4 buses directly from the database using + the function :py:func:`remove_isolated_gas_buses` Returns ------- diff --git a/src/egon/data/datasets/gas_neighbours/eGon100RE.py b/src/egon/data/datasets/gas_neighbours/eGon100RE.py index 16d6f8ff2..451d3b131 100755 --- a/src/egon/data/datasets/gas_neighbours/eGon100RE.py +++ b/src/egon/data/datasets/gas_neighbours/eGon100RE.py @@ -6,12 +6,13 @@ Dependecies (pipeline) ====================== - * :dataset: PypsaEurSec, GasNodesandPipes, HydrogenBusEtrago, - ElectricalNeighbours + +* :dataset: PypsaEurSec, GasNodesandPipes, HydrogenBusEtrago, ElectricalNeighbours Resulting tables ================ - * grid.egon_etrago_link is completed + +* grid.egon_etrago_link is completed """ @@ -43,22 +44,23 @@ def insert_gas_neigbours_eGon100RE(): This function insert the cross border pipelines for H2 and CH4, exclusively between Germany and its neighbouring countries, for eGon100RE in the database by executing the following steps: - * call of the function - :py:func:`define_DE_crossbording_pipes_geom_eGon100RE`, that - defines the cross border pipelines (H2 and CH4) between - Germany and its neighbouring countries - * call of the function - :py:func:`read_DE_crossbordering_cap_from_pes`, that calculates - the cross border total exchange capactities for H2 and CH4 - between Germany and its neighbouring countries based on the - pypsa-eur-sec results - * call of the function - :py:func:`calculate_crossbordering_gas_grid_capacities_eGon100RE`, - that attributes to each cross border pipeline (H2 and CH4) - between Germany and its neighbouring countries its capacity - * insertion of the H2 and CH4 pipelines between Germany and its - neighbouring countries in the database with function - :py:func:`insert_gas_grid_capacities` + + * call of the function + :py:func:`define_DE_crossbording_pipes_geom_eGon100RE`, that + defines the cross border pipelines (H2 and CH4) between + Germany and its neighbouring countries + * call of the function + :py:func:`read_DE_crossbordering_cap_from_pes`, that calculates + the cross border total exchange capactities for H2 and CH4 + between Germany and its neighbouring countries based on the + pypsa-eur-sec results + * call of the function + :py:func:`calculate_crossbordering_gas_grid_capacities_eGon100RE`, + that attributes to each cross border pipeline (H2 and CH4) + between Germany and its neighbouring countries its capacity + * insertion of the H2 and CH4 pipelines between Germany and its + neighbouring countries in the database with function + :py:func:`insert_gas_grid_capacities` Returns ------- @@ -117,29 +119,29 @@ def define_DE_crossbording_pipes_geom_eGon100RE(scn_name="eGon100RE"): f""" SELECT * FROM grid.egon_etrago_link WHERE ("bus0" IN ( - SELECT bus_id FROM + SELECT bus_id FROM {sources['buses']['schema']}.{sources['buses']['table']} WHERE country != 'DE' AND country != 'RU' AND carrier = 'CH4' AND scn_name = 'eGon2035') - AND "bus1" IN (SELECT bus_id FROM + AND "bus1" IN (SELECT bus_id FROM {sources['buses']['schema']}.{sources['buses']['table']} WHERE country = 'DE' - AND carrier = 'CH4' + AND carrier = 'CH4' AND scn_name = 'eGon2035')) OR ("bus0" IN ( - SELECT bus_id FROM + SELECT bus_id FROM {sources['buses']['schema']}.{sources['buses']['table']} WHERE country = 'DE' AND carrier = 'CH4' AND scn_name = 'eGon2035') AND "bus1" IN ( - SELECT bus_id FROM + SELECT bus_id FROM {sources['buses']['schema']}.{sources['buses']['table']} WHERE country != 'DE' AND country != 'RU' - AND carrier = 'CH4' + AND carrier = 'CH4' AND scn_name = 'eGon2035')) AND scn_name = 'eGon2035' AND carrier = 'CH4' diff --git a/src/egon/data/datasets/gas_neighbours/eGon2035.py b/src/egon/data/datasets/gas_neighbours/eGon2035.py index c488657b2..30ae1b345 100755 --- a/src/egon/data/datasets/gas_neighbours/eGon2035.py +++ b/src/egon/data/datasets/gas_neighbours/eGon2035.py @@ -621,9 +621,10 @@ def import_ch4_demandTS(): Import from the PyPSA-eur-sec run the time series of residential rural heat per neighbor country. This time series is used to calculate: - * the global (yearly) heat demand of Norway - (that will be supplied by CH4) - * the normalized CH4 hourly resolved demand profile + + * the global (yearly) heat demand of Norway + (that will be supplied by CH4) + * the normalized CH4 hourly resolved demand profile Returns ------- @@ -1420,21 +1421,24 @@ def tyndp_gas_demand(): Insert CH4 and H2 demands abroad for eGon2035 by executing the following steps: - * CH4 - * Calculation of the global CH4 demand in Norway and the - CH4 demand profile by executing the function - :py:func:`import_ch4_demandTS` - * Calculation of the global CH4 demands by executing the - function :py:func:`calc_global_ch4_demand` - * Insertion of the CH4 loads and their associated time - series in the database by executing the function - :py:func:`insert_ch4_demand` - * H2 - * Calculation of the global power demand abroad linked - to H2 production by executing the function - :py:func:`calc_global_power_to_h2_demand` - * Insertion of these loads in the database by executing the - function :py:func:`insert_power_to_h2_demand` + + * CH4 + + * Calculation of the global CH4 demand in Norway and the + CH4 demand profile by executing the function + :py:func:`import_ch4_demandTS` + * Calculation of the global CH4 demands by executing the + function :py:func:`calc_global_ch4_demand` + * Insertion of the CH4 loads and their associated time + series in the database by executing the function + :py:func:`insert_ch4_demand` + * H2 + + * Calculation of the global power demand abroad linked + to H2 production by executing the function + :py:func:`calc_global_power_to_h2_demand` + * Insertion of these loads in the database by executing the + function :py:func:`insert_power_to_h2_demand` Returns ------- diff --git a/src/egon/data/datasets/heat_demand_timeseries/__init__.py b/src/egon/data/datasets/heat_demand_timeseries/__init__.py index 3a8414a1b..f094c9329 100644 --- a/src/egon/data/datasets/heat_demand_timeseries/__init__.py +++ b/src/egon/data/datasets/heat_demand_timeseries/__init__.py @@ -1073,10 +1073,11 @@ class HeatTimeSeries(Dataset): Time series for residential buildings are created based on a variety of synthetical created individual demand profiles that are part of :py:class:`DataBundle `. This method is desribed within the functions and in this publication: - C. Büttner, J. Amme, J. Endres, A. Malla, B. Schachler, I. Cußmann, - Open modeling of electricity and heat demand curves for all - residential buildings in Germany, Energy Informatics 5 (1) (2022) 21. - doi:10.1186/s42162-022-00201-y. + + C. Büttner, J. Amme, J. Endres, A. Malla, B. Schachler, I. Cußmann, + Open modeling of electricity and heat demand curves for all + residential buildings in Germany, Energy Informatics 5 (1) (2022) 21. + doi:10.1186/s42162-022-00201-y. *Dependencies* diff --git a/src/egon/data/datasets/heat_demand_timeseries/idp_pool.py b/src/egon/data/datasets/heat_demand_timeseries/idp_pool.py index d3294ad15..7f6128f73 100644 --- a/src/egon/data/datasets/heat_demand_timeseries/idp_pool.py +++ b/src/egon/data/datasets/heat_demand_timeseries/idp_pool.py @@ -94,13 +94,13 @@ def temperature_classes(): def idp_pool_generator(): """ - Description: Create List of Dataframes for each temperature class for each household stock + Create List of Dataframes for each temperature class for each household stock - Returns - ------- - TYPE list - List of dataframes with each element representing a dataframe - for every combination of household stock and temperature class + Returns + ------- + list + List of dataframes with each element representing a dataframe + for every combination of household stock and temperature class """ path = os.path.join( @@ -364,8 +364,8 @@ def create(): def annual_demand_generator(): """ - Description: Create dataframe with annual demand and household count for each zensus cell + Returns ------- demand_count: pandas.DataFrame @@ -389,14 +389,14 @@ def annual_demand_generator(): house_count_MFH = db.select_dataframe( """ - - SELECT cell_id as zensus_population_id, COUNT(*) as number FROM + + SELECT cell_id as zensus_population_id, COUNT(*) as number FROM ( SELECT cell_id, COUNT(*), building_id FROM demand.egon_household_electricity_profile_of_buildings GROUP BY (cell_id, building_id) ) a - + WHERE a.count >1 GROUP BY cell_id """, @@ -405,13 +405,13 @@ def annual_demand_generator(): house_count_SFH = db.select_dataframe( """ - - SELECT cell_id as zensus_population_id, COUNT(*) as number FROM + + SELECT cell_id as zensus_population_id, COUNT(*) as number FROM ( SELECT cell_id, COUNT(*), building_id FROM demand.egon_household_electricity_profile_of_buildings GROUP BY (cell_id, building_id) - ) a + ) a WHERE a.count = 1 GROUP BY cell_id """, @@ -525,13 +525,13 @@ def select(): result_SFH["building_id"] = ( db.select_dataframe( """ - - SELECT cell_id as zensus_population_id, building_id FROM + + SELECT cell_id as zensus_population_id, building_id FROM ( SELECT cell_id, COUNT(*), building_id FROM demand.egon_household_electricity_profile_of_buildings GROUP BY (cell_id, building_id) - ) a + ) a WHERE a.count = 1 """, index_col="zensus_population_id", @@ -557,13 +557,13 @@ def select(): result_MFH["building_id"] = ( db.select_dataframe( """ - - SELECT cell_id as zensus_population_id, building_id FROM + + SELECT cell_id as zensus_population_id, building_id FROM ( SELECT cell_id, COUNT(*), building_id FROM demand.egon_household_electricity_profile_of_buildings GROUP BY (cell_id, building_id) - ) a + ) a WHERE a.count > 1 """, index_col="zensus_population_id", @@ -593,13 +593,13 @@ def select(): "building_id": ( db.select_dataframe( """ - - SELECT cell_id as zensus_population_id, building_id FROM + + SELECT cell_id as zensus_population_id, building_id FROM ( SELECT cell_id, COUNT(*), building_id FROM demand.egon_household_electricity_profile_of_buildings GROUP BY (cell_id, building_id) - ) a + ) a WHERE a.count = 1 """, index_col="zensus_population_id", @@ -645,13 +645,13 @@ def select(): "building_id": ( db.select_dataframe( """ - - SELECT cell_id as zensus_population_id, building_id FROM + + SELECT cell_id as zensus_population_id, building_id FROM ( SELECT cell_id, COUNT(*), building_id FROM demand.egon_household_electricity_profile_of_buildings GROUP BY (cell_id, building_id) - ) a + ) a WHERE a.count > 1 """, index_col="zensus_population_id", diff --git a/src/egon/data/datasets/heat_supply/individual_heating.py b/src/egon/data/datasets/heat_supply/individual_heating.py index 608a73a7e..d6de64775 100644 --- a/src/egon/data/datasets/heat_supply/individual_heating.py +++ b/src/egon/data/datasets/heat_supply/individual_heating.py @@ -2,181 +2,10 @@ The following main things are done in this module: -* .. +* ?? * Desaggregation of heat pump capacities to individual buildings * Determination of minimum required heat pump capacity for pypsa-eur-sec -The determination of the minimum required heat pump capacity for pypsa-eur-sec takes -place in the dataset 'HeatPumpsPypsaEurSec'. The goal is to ensure that the heat pump -capacities determined in pypsa-eur-sec are large enough to serve the heat demand of -individual buildings after the desaggregation from a few nodes in pypsa-eur-sec to the -individual buildings. -To determine minimum required heat pump capacity per building the buildings heat peak -load in the eGon100RE scenario is used (as pypsa-eur-sec serves as the scenario -generator for the eGon100RE scenario; see -:func:`determine_minimum_hp_capacity_per_building` for information on how minimum -required heat pump capacity is determined). As the heat peak load is not previously -determined, it is as well done in the course of this task. -Further, as determining heat peak load requires heat load -profiles of the buildings to be set up, this task is also utilised to set up -heat load profiles of all buildings with heat pumps within a grid in the eGon100RE -scenario used in eTraGo. -The resulting data is stored in separate tables respectively a csv file: - -* `input-pypsa-eur-sec/minimum_hp_capacity_mv_grid_100RE.csv`: - This csv file contains minimum required heat pump capacity per MV grid in MW as - input for pypsa-eur-sec. It is created within :func:`export_min_cap_to_csv`. -* `demand.egon_etrago_timeseries_individual_heating`: - This table contains aggregated heat load profiles of all buildings with heat pumps - within an MV grid in the eGon100RE scenario used in eTraGo. It is created within - :func:`individual_heating_per_mv_grid_tables`. -* `demand.egon_building_heat_peak_loads`: - Mapping of peak heat demand and buildings including cell_id, - building, area and peak load. This table is created in - :func:`delete_heat_peak_loads_100RE`. - -The desaggregation of heat pump capcacities to individual buildings takes place in two -separate datasets: 'HeatPumps2035' for eGon2035 scenario and 'HeatPumps2050' for -eGon100RE. -It is done separately because for one reason in case of the eGon100RE scenario the -minimum required heat pump capacity per building can directly be determined using the -heat peak load per building determined in the dataset 'HeatPumpsPypsaEurSec', whereas -heat peak load data does not yet exist for the eGon2035 scenario. Another reason is, -that in case of the eGon100RE scenario all buildings with individual heating have a -heat pump whereas in the eGon2035 scenario buildings are randomly selected until the -installed heat pump capacity per MV grid is met. All other buildings with individual -heating but no heat pump are assigned a gas boiler. - -In the 'HeatPumps2035' dataset the following things are done. -First, the building's heat peak load in the eGon2035 scenario is determined for sizing -the heat pumps. To this end, heat load profiles per building are set up. -Using the heat peak load per building the minimum required heat pump capacity per -building is determined (see :func:`determine_minimum_hp_capacity_per_building`). -Afterwards, the total heat pump capacity per MV grid is desaggregated to individual -buildings in the MV grid, wherefore buildings are randomly chosen until the MV grid's total -heat pump capacity is reached (see :func:`determine_buildings_with_hp_in_mv_grid`). -Buildings with PV rooftop plants are more likely to be assigned a heat pump. In case -the minimum heat pump capacity of all chosen buildings is smaller than the total -heat pump capacity of the MV grid but adding another building would exceed the total -heat pump capacity of the MV grid, the remaining capacity is distributed to all -buildings with heat pumps proportionally to the size of their respective minimum -heat pump capacity. Therefore, the heat pump capacity of a building can be larger -than the minimum required heat pump capacity. -The generated heat load profiles per building are in a last step utilised to set up -heat load profiles of all buildings with heat pumps within a grid as well as for all -buildings with a gas boiler (i.e. all buildings with decentral heating system minus -buildings with heat pump) needed in eTraGo. -The resulting data is stored in the following tables: - -* `demand.egon_hp_capacity_buildings`: - This table contains the heat pump capacity of all buildings with a heat pump. - It is created within :func:`delete_hp_capacity_2035`. -* `demand.egon_etrago_timeseries_individual_heating`: - This table contains aggregated heat load profiles of all buildings with heat pumps - within an MV grid as well as of all buildings with gas boilers within an MV grid in - the eGon100RE scenario used in eTraGo. It is created within - :func:`individual_heating_per_mv_grid_tables`. -* `demand.egon_building_heat_peak_loads`: - Mapping of heat demand time series and buildings including cell_id, - building, area and peak load. This table is created in - :func:`delete_heat_peak_loads_2035`. - -In the 'HeatPumps2050' dataset the total heat pump capacity in each MV grid can be -directly desaggregated to individual buildings, as the building's heat peak load was -already determined in the 'HeatPumpsPypsaEurSec' dataset. Also in contrast to the -'HeatPumps2035' dataset, all buildings with decentral heating system are assigned a -heat pump, wherefore no random sampling of buildings needs to be conducted. -The resulting data is stored in the following table: - -* `demand.egon_hp_capacity_buildings`: - This table contains the heat pump capacity of all buildings with a heat pump. - It is created within :func:`delete_hp_capacity_2035`. - -**The following datasets from the database are mainly used for creation:** - -* `boundaries.egon_map_zensus_grid_districts`: - - -* `boundaries.egon_map_zensus_district_heating_areas`: - - -* `demand.egon_peta_heat`: - Table of annual heat load demand for residential and cts at census cell - level from peta5. -* `demand.egon_heat_timeseries_selected_profiles`: - - -* `demand.egon_heat_idp_pool`: - - -* `demand.egon_daily_heat_demand_per_climate_zone`: - - -* `boundaries.egon_map_zensus_mvgd_buildings`: - A final mapping table including all buildings used for residential and - cts, heat and electricity timeseries. Including census cells, mvgd bus_id, - building type (osm or synthetic) - -* `supply.egon_individual_heating`: - - -* `demand.egon_cts_heat_demand_building_share`: - Table including the mv substation heat profile share of all selected - cts buildings for scenario eGon2035 and eGon100RE. This table is created - within :func:`cts_heat()` - - -**What is the goal?** - -The goal is threefold. Primarily, heat pump capacity of individual buildings is -determined as it is necessary for distribution grid analysis. Secondly, as heat -demand profiles need to be set up during the process, the heat demand profiles of all -buildings with individual heat pumps respectively gas boilers per MV grid are set up -to be used in eTraGo. Thirdly, minimum heat pump capacity is determined as input for -pypsa-eur-sec to avoid that heat pump capacity per building is too little to meet -the heat demand after desaggregation to individual buildings. - -**What is the challenge?** - -The main challenge lies in the set up of heat demand profiles per building in -:func:`aggregate_residential_and_cts_profiles()` as it takes alot of time and -in grids with a high number of buildings requires alot of RAM. Both runtime and -RAM usage needed to be improved several times. To speed up the process, tasks are set -up to run in parallel. This currently leads to alot of connections being opened and -at a certain point to a runtime error due to too many open connections. - -**What are central assumptions during the data processing?** - -Central assumption for determining minimum heat pump capacity and desaggregating -heat pump capacity to individual buildings is that the required heat pump capacity -is determined using an approach from the -`network development plan `_ -(pp.46-47) (see :func:`determine_minimum_hp_capacity_per_building()`). There, the heat -pump capacity is determined by multiplying the heat peak -demand of the building by a minimum assumed COP of 1.7 and a flexibility factor of -24/18, taking into account that power supply of heat pumps can be interrupted for up -to six hours by the local distribution grid operator. -Another central assumption is, that buildings with PV rooftop plants are more likely -to have a heat pump than other buildings (see -:func:`determine_buildings_with_hp_in_mv_grid()` for details) - -**Drawbacks and limitations of the data** - -In the eGon2035 scenario buildings with heat pumps are selected randomly with a higher -probability for a heat pump for buildings with PV rooftop (see -:func:`determine_buildings_with_hp_in_mv_grid()` for details). -Another limitation may be the sizing of the heat pumps, as in the eGon2035 scenario -their size rigidly depends on the heat peak load and a fixed flexibility factor. During -the coldest days of the year, heat pump flexibility strongly depends on this -assumption and cannot be dynamically enlarged to provide more flexibility (or only -slightly through larger heat storage units). - -Notes ------ - -This module docstring is rather a dataset documentation. Once, a decision -is made in ... the content of this module docstring needs to be moved to -docs attribute of the respective dataset class. """ @@ -227,6 +56,14 @@ class EgonEtragoTimeseriesIndividualHeating(Base): + """ + Class definition of table demand.egon_etrago_timeseries_individual_heating. + + This table contains aggregated heat load profiles of all buildings with heat pumps + within an MV grid as well as of all buildings with gas boilers within an MV grid for + the different scenarios. The data is used in eTraGo. + + """ __tablename__ = "egon_etrago_timeseries_individual_heating" __table_args__ = {"schema": "demand"} bus_id = Column(Integer, primary_key=True) @@ -236,6 +73,12 @@ class EgonEtragoTimeseriesIndividualHeating(Base): class EgonHpCapacityBuildings(Base): + """ + Class definition of table demand.egon_hp_capacity_buildings. + + This table contains the heat pump capacity of all buildings with a heat pump. + + """ __tablename__ = "egon_hp_capacity_buildings" __table_args__ = {"schema": "demand"} building_id = Column(Integer, primary_key=True) @@ -244,6 +87,68 @@ class EgonHpCapacityBuildings(Base): class HeatPumpsPypsaEurSec(Dataset): + """ + Class to determine minimum heat pump capcacities per building for the PyPSA-EUR run. + + The goal is to ensure that the heat pump capacities determined in PyPSA-EUR are + sufficient to serve the heat demand of individual buildings after the + desaggregation from a few nodes in PyPSA-EUR to the individual buildings. + As the heat peak load is not previously determined, it is as well done in this + dataset. Further, as determining heat peak load requires heat load + profiles of the buildings to be set up, this task is also utilised to set up + heat load profiles of all buildings with heat pumps within a grid in the eGon100RE + scenario used in eTraGo. + + For more information see data documentation on :ref:`dec-heat-pumps-ref`. + + *Dependencies* + * :py:class:`CtsDemandBuildings + ` + * :py:class:`DistrictHeatingAreas + ` + * :py:class:`HeatTimeSeries + ` + + *Resulting tables* + * `input-pypsa-eur-sec/minimum_hp_capacity_mv_grid_100RE.csv` file is created, + containing the minimum required heat pump capacity per MV grid in MW as + input for PyPSA-EUR (created within :func:`export_min_cap_to_csv`) + * :py:class:`demand.egon_etrago_timeseries_individual_heating + ` + is created and filled + * :py:class:`demand.egon_building_heat_peak_loads + ` + is created and filled + + **What is the challenge?** + + The main challenge lies in the set up of heat demand profiles per building in + :func:`aggregate_residential_and_cts_profiles()` as it takes alot of time and + in grids with a high number of buildings requires alot of RAM. Both runtime and RAM + usage needed to be improved several times. To speed up the process, tasks are set + up to run in parallel. This currently leads to alot of connections being opened and + at a certain point to a runtime error due to too many open connections. + + **What are central assumptions during the data processing?** + + Central assumption for determining the minimum required heat pump capacity + is that heat pumps can be dimensioned using an approach from the network development + plan that uses the building's peak heat demand and a fixed COP (see + data documentation on :ref:`dec-heat-pumps-ref`). + + **Drawbacks and limitations of the data** + + The heat demand profiles used here to determine the heat peak load have very few + very high peaks that lead to large heat pump capacities. This should be solved + somehow. Cutting off the peak is not possible, as the time series of each building + is not saved but generated on the fly. Also, just using smaller heat pumps would + lead to infeasibilities in eDisGo. + + """ + #: + name: str = "HeatPumpsPypsaEurSec" + #: + version: str = "0.0.2" def __init__(self, dependencies): def dyn_parallel_tasks_pypsa_eur_sec(): """Dynamically generate tasks @@ -283,8 +188,8 @@ def dyn_parallel_tasks_pypsa_eur_sec(): return tasks super().__init__( - name="HeatPumpsPypsaEurSec", - version="0.0.2", + name=self.name, + version=self.version, dependencies=dependencies, tasks=( delete_pypsa_eur_sec_csv_file, @@ -296,6 +201,90 @@ def dyn_parallel_tasks_pypsa_eur_sec(): class HeatPumps2035(Dataset): + """ + Class for desaggregation of heat pump capcacities per MV grid district to individual + buildings for eGon2035 scenario. + + The heat pump capacity per MV grid district is disaggregated to buildings + with individual heating based on the buildings heat peak demand. The buildings are + chosen randomly until the target capacity per MV grid district is reached. Buildings + with PV rooftop have a higher probability to be assigned a heat pump. As the + building's heat peak load is not previously determined, it is as well done in this + dataset. Further, as determining heat peak load requires heat load + profiles of the buildings to be set up, this task is also utilised to set up + aggregated heat load profiles of all buildings with heat pumps within a grid as + well as for all buildings with a gas boiler (i.e. all buildings with decentral + heating system minus buildings with heat pump) needed in eTraGo. + + For more information see data documentation on :ref:`dec-heat-pumps-ref`. + + Heat pump capacity per building in the eGon100RE scenario is set up in a separate + dataset, :py:class:`HeatPumps2050 `, as for one reason in case of the + eGon100RE scenario the minimum required heat pump capacity per building can directly + be determined using the peak heat demand per building determined in the dataset + :py:class:`HeatPumpsPypsaEurSec `, whereas peak heat + demand data does not yet exist for the eGon2035 scenario. Another reason is, + that in case of the eGon100RE scenario all buildings with individual heating have a + heat pump whereas in the eGon2035 scenario buildings are randomly selected until the + installed heat pump capacity per MV grid is met. All other buildings with individual + heating but no heat pump are assigned a gas boiler. + + *Dependencies* + * :py:class:`CtsDemandBuildings + ` + * :py:class:`DistrictHeatingAreas + ` + * :py:class:`HeatSupply ` + * :py:class:`HeatTimeSeries + ` + * :py:class:`HeatPumpsPypsaEurSec + ` + * :py:func:`pv_rooftop_to_buildings + ` + + *Resulting tables* + * :py:class:`demand.egon_hp_capacity_buildings + ` + is created (if it doesn't yet exist) and filled + * :py:class:`demand.egon_etrago_timeseries_individual_heating + ` + is created (if it doesn't yet exist) and filled + * :py:class:`demand.egon_building_heat_peak_loads + ` + is created (if it doesn't yet exist) and filled + + **What is the challenge?** + + The main challenge lies in the set up of heat demand profiles per building in + :func:`aggregate_residential_and_cts_profiles()` as it takes alot of time and + in grids with a high number of buildings requires alot of RAM. Both runtime and RAM + usage needed to be improved several times. To speed up the process, tasks are set + up to run in parallel. This currently leads to alot of connections being opened and + at a certain point to a runtime error due to too many open connections. + + **What are central assumptions during the data processing?** + + Central assumption for desaggregating the heat pump capacity to individual buildings + is that heat pumps can be dimensioned using an approach from the network development + plan that uses the building's peak heat demand and a fixed COP (see + data documentation on :ref:`dec-heat-pumps-ref`). + Another central assumption is, that buildings with PV rooftop plants are more likely + to have a heat pump than other buildings (see + :func:`determine_buildings_with_hp_in_mv_grid()` for details). + + **Drawbacks and limitations of the data** + + The heat demand profiles used here to determine the heat peak load have very few + very high peaks that lead to large heat pump capacities. This should be solved + somehow. Cutting off the peak is not possible, as the time series of each building + is not saved but generated on the fly. Also, just using smaller heat pumps would + lead to infeasibilities in eDisGo. + + """ + #: + name: str = "HeatPumps2035" + #: + version: str = "0.0.2" def __init__(self, dependencies): def dyn_parallel_tasks_2035(): """Dynamically generate tasks @@ -335,8 +324,8 @@ def dyn_parallel_tasks_2035(): return tasks super().__init__( - name="HeatPumps2035", - version="0.0.2", + name=self.name, + version=self.version, dependencies=dependencies, tasks=( delete_heat_peak_loads_2035, @@ -348,10 +337,59 @@ def dyn_parallel_tasks_2035(): class HeatPumps2050(Dataset): + """ + Class for desaggregation of heat pump capcacities per MV grid district to individual + buildings for eGon100RE scenario. + + Optimised heat pump capacity from PyPSA-EUR run is disaggregated to all buildings + with individual heating (as heat pumps are the only option for individual heating + in the eGon100RE scenario) based on buildings heat peak demand. The heat peak demand + per building does in this dataset, in contrast to the + :py:class:`HeatPumps2035 ` dataset, + not need to be determined, as it was already determined in the + :py:class:`PypsaEurSec ` dataset. + + For more information see data documentation on :ref:`dec-heat-pumps-ref`. + + Heat pump capacity per building for the eGon2035 scenario is set up in a separate + dataset, :py:class:`HeatPumps2035 `. See there for further + information as to why. + + *Dependencies* + * :py:class:`PypsaEurSec ` + * :py:class:`HeatPumpsPypsaEurSec + ` + * :py:class:`HeatSupply ` + + *Resulting tables* + * :py:class:`demand.egon_hp_capacity_buildings + ` + is created (if it doesn't yet exist) and filled + + **What are central assumptions during the data processing?** + + Central assumption for desaggregating the heat pump capacity to individual buildings + is that heat pumps can be dimensioned using an approach from the network development + plan that uses the building's peak heat demand and a fixed COP (see + data documentation on :ref:`dec-heat-pumps-ref`). + + **Drawbacks and limitations of the data** + + The heat demand profiles used here to determine the heat peak load have very few + very high peaks that lead to large heat pump capacities. This should be solved + somehow. Cutting off the peak is not possible, as the time series of each building + is not saved but generated on the fly. Also, just using smaller heat pumps would + lead to infeasibilities in eDisGo. + + """ + #: + name: str = "HeatPumps2050" + #: + version: str = "0.0.2" def __init__(self, dependencies): super().__init__( - name="HeatPumps2050", - version="0.0.2", + name=self.name, + version=self.version, dependencies=dependencies, tasks=( delete_hp_capacity_100RE, @@ -361,6 +399,13 @@ def __init__(self, dependencies): class BuildingHeatPeakLoads(Base): + """ + Class definition of table demand.egon_building_heat_peak_loads. + + Table with peak heat demand of residential and CTS heat demand combined for + each building. + + """ __tablename__ = "egon_building_heat_peak_loads" __table_args__ = {"schema": "demand"} @@ -497,12 +542,12 @@ def cascade_per_technology( def cascade_heat_supply_indiv(scenario, distribution_level, plotting=True): """Assigns supply strategy for individual heating in four steps. - 1.) all small scale CHP are connected. - 2.) If the supply can not meet the heat demand, solar thermal collectors - are attached. This is not implemented yet, since individual - solar thermal plants are not considered in eGon2035 scenario. - 3.) If this is not suitable, the mv grid is also supplied by heat pumps. - 4.) The last option are individual gas boilers. + 1. all small scale CHP are connected. + 2. If the supply can not meet the heat demand, solar thermal collectors + are attached. This is not implemented yet, since individual + solar thermal plants are not considered in eGon2035 scenario. + 3. If this is not suitable, the mv grid is also supplied by heat pumps. + 4. The last option are individual gas boilers. Parameters ---------- @@ -1565,7 +1610,7 @@ def export_to_db(df_peak_loads_db, df_heat_mvgd_ts_db, drop=False): """ Function to export the collected results of all MVGDs per bulk to DB. - Parameters + Parameters ---------- df_peak_loads_db : pd.DataFrame Table of building peak loads of all MVGDs per bulk diff --git a/src/egon/data/datasets/hydrogen_etrago/__init__.py b/src/egon/data/datasets/hydrogen_etrago/__init__.py index 5ca7162dd..aa3efbff9 100755 --- a/src/egon/data/datasets/hydrogen_etrago/__init__.py +++ b/src/egon/data/datasets/hydrogen_etrago/__init__.py @@ -80,14 +80,15 @@ class HydrogenStoreEtrago(Dataset): Insert the H2 stores in Germany into the database for the scenarios eGon2035 and eGon100RE: - * H2 overground stores or steel tanks at each H2_grid bus with the - function :py:func:`insert_H2_overground_storage ` - for the scenario eGon2035, - * H2 underground stores or saltcavern stores at each H2_saltcavern - bus with the function :py:func:`insert_H2_saltcavern_storage ` - for the scenario eGon2035, - * H2 stores (overground and underground) for the scenario eGon100RE - with the function :py:func:`insert_H2_storage_eGon100RE `. + + * H2 overground stores or steel tanks at each H2_grid bus with the + function :py:func:`insert_H2_overground_storage ` + for the scenario eGon2035, + * H2 underground stores or saltcavern stores at each H2_saltcavern + bus with the function :py:func:`insert_H2_saltcavern_storage ` + for the scenario eGon2035, + * H2 stores (overground and underground) for the scenario eGon100RE + with the function :py:func:`insert_H2_storage_eGon100RE `. *Dependencies* * :py:class:`SaltcavernData ` diff --git a/src/egon/data/datasets/hydrogen_etrago/bus.py b/src/egon/data/datasets/hydrogen_etrago/bus.py index c83bcd910..73a105c16 100755 --- a/src/egon/data/datasets/hydrogen_etrago/bus.py +++ b/src/egon/data/datasets/hydrogen_etrago/bus.py @@ -6,11 +6,12 @@ The H2 buses in the neighbouring countries (only present in eGon100RE) are defined in :py:mod:`pypsaeursec `. In both scenarios, there are two types of H2 buses in Germany: - * H2_grid buses: defined in :py:func:`insert_H2_buses_from_CH4_grid`; - these buses are located at the places of the CH4 buses. - * H2_saltcavern buses: defined in :py:func:`insert_H2_buses_from_saltcavern`; - these buses are located at the intersection of AC buses and - potential H2 saltcaverns. + +* H2_grid buses: defined in :py:func:`insert_H2_buses_from_CH4_grid`; + these buses are located at the places of the CH4 buses. +* H2_saltcavern buses: defined in :py:func:`insert_H2_buses_from_saltcavern`; + these buses are located at the intersection of AC buses and + potential H2 saltcaverns. """ @@ -29,15 +30,15 @@ def insert_hydrogen_buses(scenario="eGon2035"): Insert hydrogen buses into the database (in etrago table) Hydrogen buses are inserted into the database using the functions: - * :py:func:`insert_H2_buses_from_CH4_grid` for H2_grid buses - * :py:func:`insert_H2_buses_from_saltcavern` for the H2_saltcavern - buses + + * :py:func:`insert_H2_buses_from_CH4_grid` for H2_grid buses + * :py:func:`insert_H2_buses_from_saltcavern` for the H2_saltcavern buses Parameters ---------- scenario : str, optional Name of the scenario, the default is 'eGon2035'. - + Returns ------- None @@ -150,11 +151,11 @@ def insert_H2_buses_from_CH4_grid(gdf, carrier, target, scn_name): Target schema and table information. scn_name : str Name of the scenario. - + Returns ------- None - + """ # Connect to local database engine = db.engine() @@ -190,11 +191,11 @@ def insert_H2_buses_from_CH4_grid(gdf, carrier, target, scn_name): def insert_hydrogen_buses_eGon100RE(): """Copy H2 buses from the eGon2035 to the eGon100RE scenario. - + Returns ------- - None - + None + """ copy_and_modify_buses( "eGon2035", "eGon100RE", {"carrier": ["H2_grid", "H2_saltcavern"]}, diff --git a/src/egon/data/datasets/hydrogen_etrago/h2_grid.py b/src/egon/data/datasets/hydrogen_etrago/h2_grid.py index ff0776d26..760894fd4 100755 --- a/src/egon/data/datasets/hydrogen_etrago/h2_grid.py +++ b/src/egon/data/datasets/hydrogen_etrago/h2_grid.py @@ -2,12 +2,14 @@ The central module containing all code dealing with the H2 grid in eGon100RE The H2 grid, present only in eGon100RE, is composed of two parts: + * a fixed part with the same topology as the CH4 grid and with carrier 'H2_retrofit' corresponding to the retrofitted share of the CH4 grid into a hydrogen grid, * an extendable part with carrier 'H2_gridextension', linking each H2_salcavern bus to the closest H2_grid bus: this part has no capacity (p_nom = 0) but it can be extended. + As for the CH4 grid, the H2 pipelines are modelled by PyPSA links. """ @@ -25,24 +27,25 @@ def insert_h2_pipelines(): Insert hydrogen grid (H2 links) into the database for eGon100RE. Insert the H2 grid by executing the following steps: - * Copy the CH4 links in Germany from eGon2035 - * Overwrite the followings columns: - * bus0 and bus1 using the grid.egon_etrago_ch4_h2 table - * carrier, scn_name - * p_nom: the value attributed there corresponds to the share - of p_nom of the specific pipeline that could be retrofited into - H2 pipeline. This share is the same for every pipeline and is - calculated in the PyPSA-eur-sec run. - * Create new extendable pipelines to link the existing grid to the - H2_saltcavern buses - * Clean database - * Attribute link_id to the links - * Insert into the database + + * Copy the CH4 links in Germany from eGon2035 + * Overwrite the followings columns: + + * bus0 and bus1 using the grid.egon_etrago_ch4_h2 table + * carrier, scn_name + * p_nom: the value attributed there corresponds to the share + of p_nom of the specific pipeline that could be retrofited into + H2 pipeline. This share is the same for every pipeline and is + calculated in the PyPSA-eur-sec run. + * Create new extendable pipelines to link the existing grid to the + H2_saltcavern buses + * Clean database + * Attribute link_id to the links + * Insert into the database Returns ------- None - """ H2_buses = db.select_geodataframe( diff --git a/src/egon/data/datasets/hydrogen_etrago/h2_to_ch4.py b/src/egon/data/datasets/hydrogen_etrago/h2_to_ch4.py index 6c26caea6..21202cc87 100755 --- a/src/egon/data/datasets/hydrogen_etrago/h2_to_ch4.py +++ b/src/egon/data/datasets/hydrogen_etrago/h2_to_ch4.py @@ -5,11 +5,11 @@ In this module the functions used to define and insert the links between H2 and CH4 buses into the database are to be found. These links are modelling: - * Methanisation (carrier name: 'H2_to_CH4'): technology to produce CH4 - from H2 - * H2_feedin: Injection of H2 into the CH4 grid - * Steam Methane Reaction (SMR, carrier name: 'CH4_to_H2'): techonology - to produce CH4 from H2 + +* Methanisation (carrier name: 'H2_to_CH4'): technology to produce CH4 from H2 +* H2_feedin: Injection of H2 into the CH4 grid +* Steam Methane Reaction (SMR, carrier name: 'CH4_to_H2'): techonology + to produce CH4 from H2 """ diff --git a/src/egon/data/datasets/hydrogen_etrago/power_to_h2.py b/src/egon/data/datasets/hydrogen_etrago/power_to_h2.py index 78e4a09b0..d5745617f 100755 --- a/src/egon/data/datasets/hydrogen_etrago/power_to_h2.py +++ b/src/egon/data/datasets/hydrogen_etrago/power_to_h2.py @@ -2,13 +2,12 @@ """ Module containing the definition of the AC grid to H2 links -In this module the functions used to define and insert the links +In this module the functions used to define and insert the links between H2 and AC buses into the database are to be found. These links are modelling: - * Electrolysis (carrier name: 'power_to_H2'): technology to produce H2 - from AC - * Fuel cells (carrier name: 'H2_to_power'): techonology to produce - power from H2 + +* Electrolysis (carrier name: 'power_to_H2'): technology to produce H2 from AC +* Fuel cells (carrier name: 'H2_to_power'): techonology to produce power from H2 """ from geoalchemy2.types import Geometry @@ -232,11 +231,11 @@ def map_buses(scn_name): def insert_power_to_h2_to_power_eGon100RE(): """Copy H2/power links from the eGon2035 to the eGon100RE scenario. - + Returns ------- None - + """ copy_and_modify_links( "eGon2035", "eGon100RE", ["H2_to_power", "power_to_H2"], "gas" diff --git a/src/egon/data/datasets/hydrogen_etrago/storage.py b/src/egon/data/datasets/hydrogen_etrago/storage.py index c85013d23..209cbb80c 100755 --- a/src/egon/data/datasets/hydrogen_etrago/storage.py +++ b/src/egon/data/datasets/hydrogen_etrago/storage.py @@ -3,11 +3,13 @@ This module contains the functions used to insert the two types of H2 store potentials in Germany: - * H2 overground stores (carrier: 'H2_overground'): steel tanks at - every H2_grid bus - * H2 underground stores (carrier: 'H2_underground'): saltcavern store - at every H2_saltcavern bus. - NB: the saltcavern locations define the H2_saltcavern buses locations. + +* H2 overground stores (carrier: 'H2_overground'): steel tanks at + every H2_grid bus +* H2 underground stores (carrier: 'H2_underground'): saltcavern store + at every H2_saltcavern bus. + NB: the saltcavern locations define the H2_saltcavern buses locations. + All these stores are modelled as extendable PyPSA stores. """ @@ -25,7 +27,7 @@ def insert_H2_overground_storage(scn_name="eGon2035"): Insert H2_overground stores into the database. Insert extendable H2_overground stores (steel tanks) at each H2_grid - bus. + bus. Returns ------- @@ -95,7 +97,7 @@ def insert_H2_saltcavern_storage(scn_name="eGon2035"): Insert extendable H2_underground stores (saltcavern potentials) at every H2_saltcavern bus. - + Returns ------- None @@ -379,11 +381,11 @@ def calculate_and_map_saltcavern_storage_potential(): def write_saltcavern_potential(): """Write saltcavern potentials into the database - + Returns ------- None - + """ potential_areas = calculate_and_map_saltcavern_storage_potential() @@ -401,11 +403,11 @@ def write_saltcavern_potential(): def insert_H2_storage_eGon100RE(): """Copy H2 storage from the eGon2035 to the eGon100RE scenario. - + Returns ------- None - + """ copy_and_modify_stores( "eGon2035", "eGon100RE", ["H2_underground", "H2_overground"], "gas" diff --git a/src/egon/data/datasets/industrial_gas_demand.py b/src/egon/data/datasets/industrial_gas_demand.py index d57ccfcba..bb54b083c 100755 --- a/src/egon/data/datasets/industrial_gas_demand.py +++ b/src/egon/data/datasets/industrial_gas_demand.py @@ -440,22 +440,24 @@ def insert_industrial_gas_demand_egon100RE(): previously downloaded in :py:func:`download_industrial_gas_demand` are adapted by executing the following steps: - * Clean the database with the function :py:func:`delete_old_entries` - * Read and prepare the CH4 and the H2 industrial demands and their - associated time series in Germany with the function :py:func:`read_and_process_demand` - * Identify and adjust the total industrial CH4 and H2 loads for Germany - generated by PyPSA-Eur-Sec - * For CH4, the time series used is the one from H2, because - the industrial CH4 demand in the opendata.ffe database is 0 - * In test mode, the total values are obtained by - evaluating the share of H2 demand in the test region - (NUTS1: DEF, Schleswig-Holstein) with respect to the H2 - demand in full Germany model (NUTS0: DE). This task has been - outsourced to save processing cost. - * Aggregate the demands with the same properties at the same gas bus - * Insert the loads into the database by executing :py:func:`insert_new_entries` - * Insert the time series associated to the loads into the database - by executing :py:func:`insert_industrial_gas_demand_time_series` + * Clean the database with the function :py:func:`delete_old_entries` + * Read and prepare the CH4 and the H2 industrial demands and their + associated time series in Germany with the function :py:func:`read_and_process_demand` + * Identify and adjust the total industrial CH4 and H2 loads for Germany + generated by PyPSA-Eur-Sec + + * For CH4, the time series used is the one from H2, because + the industrial CH4 demand in the opendata.ffe database is 0 + * In test mode, the total values are obtained by + evaluating the share of H2 demand in the test region + (NUTS1: DEF, Schleswig-Holstein) with respect to the H2 + demand in full Germany model (NUTS0: DE). This task has been + outsourced to save processing cost. + + * Aggregate the demands with the same properties at the same gas bus + * Insert the loads into the database by executing :py:func:`insert_new_entries` + * Insert the time series associated to the loads into the database + by executing :py:func:`insert_industrial_gas_demand_time_series` Returns ------- diff --git a/src/egon/data/datasets/mv_grid_districts.py b/src/egon/data/datasets/mv_grid_districts.py index d13e5fb5d..c968e6b5b 100644 --- a/src/egon/data/datasets/mv_grid_districts.py +++ b/src/egon/data/datasets/mv_grid_districts.py @@ -773,11 +773,11 @@ def define_mv_grid_districts(): is organized in three steps: 1. :func:`substations_in_municipalities`: The number of substations - located inside each municipality is calculated. + located inside each municipality is calculated. 2. :func:`split_multi_substation_municipalities`: The municipalities with - >1 substation inside are split by Voronoi polygons around substations. + >1 substation inside are split by Voronoi polygons around substations. 3. :func:`merge_polygons_to_grid_district`: All polygons are merged such - that one polygon has exactly one single substation inside. + that one polygon has exactly one single substation inside. Finally, intermediate tables used for storing data temporarily are deleted. """ diff --git a/src/egon/data/datasets/power_plants/__init__.py b/src/egon/data/datasets/power_plants/__init__.py index 39f68ad40..f7d70c13f 100755 --- a/src/egon/data/datasets/power_plants/__init__.py +++ b/src/egon/data/datasets/power_plants/__init__.py @@ -63,31 +63,31 @@ class PowerPlants(Dataset): *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 + ` is filled """ diff --git a/src/egon/data/datasets/power_plants/mastr.py b/src/egon/data/datasets/power_plants/mastr.py index 225c7c685..8bfa90a17 100644 --- a/src/egon/data/datasets/power_plants/mastr.py +++ b/src/egon/data/datasets/power_plants/mastr.py @@ -10,6 +10,7 @@ * hydro plants: table `supply.egon_power_plants_hydro` Handling of empty source data in MaStr dump: + * `voltage_level`: inferred based on nominal power (`capacity`) using the ranges from https://redmine.iks.cs.ovgu.de/oe/projects/ego-n/wiki/Definition_of_thresholds_for_voltage_level_assignment @@ -55,6 +56,7 @@ def isfloat(num: str): """ Determine if string can be converted to float. + Parameters ----------- num : str @@ -76,6 +78,7 @@ def zip_and_municipality_from_standort( ) -> tuple[str, bool]: """ Get zip code and municipality from Standort string split into a list. + Parameters ----------- standort : str @@ -125,7 +128,7 @@ def infer_voltage_level( ----------- units_gdf : geopandas.GeoDataFrame GeoDataFrame containing units with voltage levels from MaStR - Returnsunits_gdf: gpd.GeoDataFrame + Returns ------- geopandas.GeoDataFrame GeoDataFrame containing units all having assigned a voltage level. diff --git a/src/egon/data/datasets/power_plants/pv_rooftop_buildings.py b/src/egon/data/datasets/power_plants/pv_rooftop_buildings.py index 07c43489d..e12b848b7 100644 --- a/src/egon/data/datasets/power_plants/pv_rooftop_buildings.py +++ b/src/egon/data/datasets/power_plants/pv_rooftop_buildings.py @@ -261,6 +261,7 @@ def add_ags_to_gens( ) -> gpd.GeoDataFrame: """ Add information about AGS ID to generators. + Parameters ----------- mastr_gdf : geopandas.GeoDataFrame @@ -285,6 +286,7 @@ def drop_gens_outside_muns( ) -> gpd.GeoDataFrame: """ Drop all generators outside of municipalities. + Parameters ----------- mastr_gdf : geopandas.GeoDataFrame @@ -311,6 +313,7 @@ def load_mastr_data(): """Read PV rooftop data from MaStR CSV Note: the source will be replaced as soon as the MaStR data is available in DB. + Returns ------- geopandas.GeoDataFrame @@ -359,6 +362,7 @@ def osm_buildings( ) -> gpd.GeoDataFrame: """ Read OSM buildings data from eGo^n Database. + Parameters ----------- to_crs : pyproj.crs.crs.CRS @@ -386,6 +390,7 @@ def synthetic_buildings( ) -> gpd.GeoDataFrame: """ Read synthetic buildings data from eGo^n Database. + Parameters ----------- to_crs : pyproj.crs.crs.CRS @@ -414,6 +419,7 @@ def add_ags_to_buildings( ) -> gpd.GeoDataFrame: """ Add information about AGS ID to buildings. + Parameters ----------- buildings_gdf : geopandas.GeoDataFrame @@ -438,6 +444,7 @@ def drop_buildings_outside_muns( ) -> gpd.GeoDataFrame: """ Drop all buildings outside of municipalities. + Parameters ----------- buildings_gdf : geopandas.GeoDataFrame @@ -598,6 +605,7 @@ def sort_and_qcut_df( """ Determine the quantile of a given attribute in a (Geo)DataFrame. Sort the (Geo)DataFrame in ascending order for the given attribute. + Parameters ----------- df : pandas.DataFrame or geopandas.GeoDataFrame @@ -634,6 +642,7 @@ def allocate_pv( buildings than generators within a given AGS. Primarily generators are distributed with the same qunatile as the buildings. Multiple assignment is excluded. + Parameters ----------- q_mastr_gdf : geopandas.GeoDataFrame @@ -750,6 +759,7 @@ def frame_to_numeric( ) -> pd.DataFrame | gpd.GeoDataFrame: """ Try to convert all columns of a DataFrame to numeric ignoring errors. + Parameters ---------- df : pandas.DataFrame or geopandas.GeoDataFrame @@ -855,6 +865,7 @@ def allocate_to_buildings( ) -> tuple[gpd.GeoDataFrame, gpd.GeoDataFrame]: """ Allocate status quo pv rooftop generators to buildings. + Parameters ----------- mastr_gdf : geopandas.GeoDataFrame @@ -889,6 +900,7 @@ def grid_districts( """ Load mv grid district geo data from eGo^n Database as geopandas.GeoDataFrame. + Parameters ----------- epsg : int @@ -922,6 +934,7 @@ def scenario_data( ) -> pd.DataFrame: """ Get scenario capacity data from eGo^n Database. + Parameters ----------- carrier : str @@ -989,6 +1002,7 @@ class Vg250Lan(Base): def federal_state_data(to_crs: CRS) -> gpd.GeoDataFrame: """ Get feder state data from eGo^n Database. + Parameters ----------- to_crs : pyproj.crs.crs.CRS @@ -1019,6 +1033,7 @@ def overlay_grid_districts_with_counties( ) -> gpd.GeoDataFrame: """ Calculate the intersections of mv grid districts and counties. + Parameters ----------- mv_grid_district_gdf : gpd.GeoDataFrame @@ -1054,6 +1069,7 @@ def add_overlay_id_to_buildings( ) -> gpd.GeoDataFrame: """ Add information about overlay ID to buildings. + Parameters ----------- buildings_gdf : geopandas.GeoDataFrame @@ -1086,6 +1102,7 @@ def drop_buildings_outside_grids( ) -> gpd.GeoDataFrame: """ Drop all buildings outside of grid areas. + Parameters ----------- buildings_gdf : geopandas.GeoDataFrame @@ -1144,6 +1161,7 @@ def determine_end_of_life_gens( ) -> gpd.GeoDataFrame: """ Determine if an old PV system has reached its end of life. + Parameters ----------- mastr_gdf : geopandas.GeoDataFrame @@ -1239,6 +1257,7 @@ def calculate_building_load_factor( ) -> gpd.GeoDataFrame: """ Calculate the roof load factor from existing PV systems. + Parameters ----------- mastr_gdf : geopandas.GeoDataFrame @@ -1273,6 +1292,7 @@ def get_probability_for_property( """ Calculate the probability of the different options of a property of the existing PV plants. + Parameters ----------- mastr_gdf : geopandas.GeoDataFrame @@ -1322,6 +1342,7 @@ def probabilities( """ Calculate the probability of the different options of properties of the existing PV plants. + Parameters ----------- mastr_gdf : geopandas.GeoDataFrame @@ -1425,6 +1446,7 @@ def mean_load_factor_per_cap_range( """ Calculate the mean roof load factor per capacity range from existing PV plants. + Parameters ----------- mastr_gdf : geopandas.GeoDataFrame @@ -1469,6 +1491,7 @@ def building_area_range_per_cap_range( Estimate normal building area range per capacity range. Calculate the mean roof load factor per capacity range from existing PV plants. + Parameters ----------- mastr_gdf : geopandas.GeoDataFrame @@ -1555,6 +1578,7 @@ def desaggregate_pv_in_mv_grid( ) -> gpd.GeoDataFrame: """ Desaggregate PV capacity on buildings within a given grid district. + Parameters ----------- buildings_gdf : geopandas.GeoDataFrame @@ -1872,6 +1896,7 @@ def add_buildings_meta_data( ) -> gpd.GeoDataFrame: """ Randomly add additional metadata to desaggregated PV plants. + Parameters ----------- buildings_gdf : geopandas.GeoDataFrame @@ -1929,6 +1954,7 @@ def add_commissioning_date( ): """ Randomly and linear add start-up date to new pv generators. + Parameters ---------- buildings_gdf : geopandas.GeoDataFrame @@ -1963,6 +1989,7 @@ def allocate_scenarios( ): """ Desaggregate and allocate scenario pv rooftop ramp-ups onto buildings. + Parameters ---------- mastr_gdf : geopandas.GeoDataFrame diff --git a/src/egon/data/datasets/sanity_checks.py b/src/egon/data/datasets/sanity_checks.py index aae4702fa..7dba8093c 100755 --- a/src/egon/data/datasets/sanity_checks.py +++ b/src/egon/data/datasets/sanity_checks.py @@ -835,9 +835,10 @@ def sanitycheck_emobility_mit(): Checks data integrity for eGon2035, eGon2035_lowflex and eGon100RE scenario using assertions: - 1. Allocated EV numbers and EVs allocated to grid districts - 2. Trip data (original inout data from simBEV) - 3. Model data in eTraGo PF tables (grid.egon_etrago_*) + + 1. Allocated EV numbers and EVs allocated to grid districts + 2. Trip data (original inout data from simBEV) + 3. Model data in eTraGo PF tables (grid.egon_etrago_*) Parameters ---------- @@ -1437,10 +1438,11 @@ def sanity_check_gas_buses(scn): Returns print statements as sanity checks for the CH4, H2_grid and H2_saltcavern buses. - * For all of them, it is checked if they are not isolated. - * For the grid buses, the deviation is calculated between the - number of gas grid buses in the database and the original - Scigrid_gas number of gas buses in Germany. + + * For all of them, it is checked if they are not isolated. + * For the grid buses, the deviation is calculated between the + number of gas grid buses in the database and the original + Scigrid_gas number of gas buses in Germany. Parameters ---------- @@ -1534,13 +1536,15 @@ def sanity_check_CH4_stores(scn): Returns print statements as sanity checks for the CH4 stores capacity in Germany. The deviation is calculated between: + * the sum of the capacities of the stores with carrier 'CH4' in the database (for one scenario) and * the sum of: - * the capacity the gas grid allocated to CH4 (total capacity - in eGon2035 and capacity reduced the share of the grid - allocated to H2 in eGon100RE) - * the total capacity of the CH4 stores in Germany (source: GIE) + + * the capacity the gas grid allocated to CH4 (total capacity + in eGon2035 and capacity reduced the share of the grid + allocated to H2 in eGon100RE) + * the total capacity of the CH4 stores in Germany (source: GIE) Parameters ---------- @@ -1592,13 +1596,15 @@ def sanity_check_H2_saltcavern_stores(scn): Returns print as sanity checks for the H2 saltcavern potential storage capacity in Germany. The deviation is calculated between: - * the sum of the of the H2 saltcavern potential storage capacity - (e_nom_max) in the database and - * the sum of the H2 saltcavern potential storage capacity - assumed to be the ratio of the areas of 500 m radius around - substations in each german federal state and the estimated - total hydrogen storage potential of the corresponding federal - state (data from InSpEE-DS report). + + * the sum of the of the H2 saltcavern potential storage capacity + (e_nom_max) in the database and + * the sum of the H2 saltcavern potential storage capacity + assumed to be the ratio of the areas of 500 m radius around + substations in each german federal state and the estimated + total hydrogen storage potential of the corresponding federal + state (data from InSpEE-DS report). + This test works also in test mode. Parameters @@ -1932,6 +1938,7 @@ def etrago_eGon2035_gas_DE(): Returns print statements as sanity checks for the gas sector in the eGon2035 scenario for the following components in Germany: + * Buses: with the function :py:func:`sanity_check_gas_buses` * Loads: for the carriers 'CH4_for_industry' and 'H2_for_industry' the deviation is calculated between the sum of the loads in the @@ -1944,16 +1951,18 @@ def etrago_eGon2035_gas_DE(): data) * Stores: deviations for stores with following carriers are calculated: + * 'CH4': with the function :py:func:`sanity_check_CH4_stores` * 'H2_underground': with the function :py:func:`sanity_check_H2_saltcavern_stores` * One-port components (loads, generators, stores): verification that they are all connected to a bus present in the data base with the function :py:func:`sanity_check_gas_one_port` * Links: verification: - * that the gas links are all connected to buses present in - the data base with the function :py:func:`sanity_check_gas_links` - * of the capacity of the gas grid with the function - :py:func:`sanity_check_CH4_grid` + + * that the gas links are all connected to buses present in + the data base with the function :py:func:`sanity_check_gas_links` + * of the capacity of the gas grid with the function + :py:func:`sanity_check_CH4_grid` """ scn = "eGon2035" @@ -2110,6 +2119,7 @@ def etrago_eGon2035_gas_abroad(): Returns print statements as sanity checks for the gas sector in the eGon2035 scenario for the following components in Germany: + * Buses * Loads: for the carriers 'CH4' and 'H2_for_industry' the deviation is calculated between the sum of the loads in the diff --git a/src/egon/data/datasets/storages/home_batteries.py b/src/egon/data/datasets/storages/home_batteries.py index 40d19c1ea..9191aedb2 100644 --- a/src/egon/data/datasets/storages/home_batteries.py +++ b/src/egon/data/datasets/storages/home_batteries.py @@ -5,6 +5,7 @@ depending on pv rooftop system size. **Contents of this module** + * Creation of DB tables * Allocate given home battery capacity per mv grid to buildings with pv rooftop systems. The sizing of the home battery system depends on the size of the diff --git a/src/egon/data/db.py b/src/egon/data/db.py index 665f2eb93..922d61da1 100755 --- a/src/egon/data/db.py +++ b/src/egon/data/db.py @@ -360,10 +360,10 @@ def commit(*args, **kwargs): def assign_gas_bus_id(dataframe, scn_name, carrier): - """Assign `bus_id`s to points according to location. + """Assign `bus_id`'s to points according to location. The points are taken from the given `dataframe` and the geometries by - which the `bus_id`s are assigned to them are taken from the + which the `bus_id`'s are assigned to them are taken from the `grid.egon_gas_voronoi` table. Parameters