diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000..fd64e164 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,92 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: ["master"] + pull_request: + branches: ["master"] + schedule: + - cron: '23 18 * * 5' + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: python + build-mode: none + # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/CITATION.cff b/CITATION.cff index c921a773..2caf4226 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -6,7 +6,7 @@ cff-version: 1.1.0 message: "If you use this package, please cite it in the following way." title: "PyPSA-Eur: An open sector-coupled optimisation model of the European energy system" repository: https://github.com/pypsa/pypsa-eur -version: 0.11.0 +version: 0.12.0 license: MIT authors: - family-names: Brown @@ -36,3 +36,17 @@ authors: - family-names: Hörsch given-names: Jonas orcid: https://orcid.org/0000-0001-9438-767X + - family-names: Schledorn + given-names: Amos + - family-names: Schauß + given-names: Caspar + - family-names: van Greevenbroek + given-names: Koen + - family-names: Millinger + given-names: Markus + - family-names: Glaum + given-names: Philipp + - family-names: Xiong + given-names: Bobby + - family-names: Seibold + given-names: Toni diff --git a/config/config.default.yaml b/config/config.default.yaml index 4060729d..246a15f4 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -3,7 +3,7 @@ # SPDX-License-Identifier: CC0-1.0 # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#top-level-configuration -version: 0.11.0 +version: 0.12.0 tutorial: false logging: @@ -155,7 +155,7 @@ renewable: resource: method: wind turbine: Vestas_V112_3MW - smooth: true + smooth: false add_cutout_windspeed: true capacity_per_sqkm: 3 # correction_factor: 0.93 @@ -175,7 +175,7 @@ renewable: resource: method: wind turbine: NREL_ReferenceTurbine_2020ATB_5.5MW - smooth: true + smooth: false add_cutout_windspeed: true capacity_per_sqkm: 2 correction_factor: 0.8855 @@ -192,7 +192,7 @@ renewable: resource: method: wind turbine: NREL_ReferenceTurbine_2020ATB_5.5MW - smooth: true + smooth: false add_cutout_windspeed: true capacity_per_sqkm: 2 correction_factor: 0.8855 @@ -209,7 +209,7 @@ renewable: resource: method: wind turbine: NREL_ReferenceTurbine_5MW_offshore - smooth: true + smooth: false add_cutout_windspeed: true # ScholzPhd Tab 4.3.1: 10MW/km^2 capacity_per_sqkm: 2 @@ -451,21 +451,18 @@ sector: district_heating_loss: 0.15 supply_temperature_approximation: max_forward_temperature: - default: 90 - DK: 70 - SE: 70 - NO: 70 + FR: 110 + DK: 75 + DE: 109 + CZ: 130 + FI: 115 + PL: 130 + SE: 102 + IT: 90 min_forward_temperature: - default: 68 - DK: 54 - SE: 54 - NO: 54 + DE: 82 return_temperature: - default: 50 - DK: 40 - SE: 40 - NO: 40 - FI: 40 + DE: 58 lower_threshold_ambient_temperature: 0 upper_threshold_ambient_temperature: 10 rolling_window_ambient_temperature: 72 @@ -590,7 +587,9 @@ sector: resistive_heaters: true oil_boilers: false biomass_boiler: true - overdimension_individual_heating: 1.1 #to cover demand peaks bigger than data + overdimension_heat_generators: + decentral: 1.1 #to cover demand peaks bigger than data + central: 1.0 chp: true micro_chp: false solar_thermal: true @@ -810,6 +809,7 @@ industry: MWh_MeOH_per_tMeOH: 5.528 hotmaps_locate_missing: false reference_year: 2019 + oil_refining_emissions: 0.013 # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#costs @@ -1090,6 +1090,8 @@ plotting: gas pipeline new: '#a87c62' # oil oil: '#c9c9c9' + oil primary: '#d2d2d2' + oil refining: '#e6e6e6' imported oil: '#a3a3a3' oil boiler: '#adadad' residential rural oil boiler: '#a9a9a9' @@ -1133,6 +1135,7 @@ plotting: services rural biomass boiler: '#c6cf98' services urban decentral biomass boiler: '#dde5b5' biomass to liquid: '#32CD32' + unsustainable solid biomass: '#998622' unsustainable bioliquids: '#32CD32' electrobiofuels: 'red' BioSNG: '#123456' diff --git a/data/transmission_projects/nep/new_links.csv b/data/transmission_projects/nep/new_links.csv index d237893f..7a551f36 100644 --- a/data/transmission_projects/nep/new_links.csv +++ b/data/transmission_projects/nep/new_links.csv @@ -10,3 +10,9 @@ DC40plus,Dörpen/West,Klostermansfeld/Sachsen-Anhalt,2000.0,426,confirmed,2037,T DC41,Alfstedt/Niedersachsen,Hüffenhardt/Baden-Württemberg,2000.0,607,confirmed,2037,True,"{""url"":""https://data.netzausbau.de/2037-2023/NEP/NEP_2037_2045_Bestaetigung.pdf"", ""status"":""confirmed"", ""origin"":""NEP"",""version"":2024,""location0"":""Alfstedt/Niedersachsen"",""location1"":""Hüffenhardt/Baden-Württemberg""",9.0666915,53.5499782,9.0827453,49.2908862 DC42,Sahms/Schleswig-Holstein,Böblingen/Baden-Württemberg,2000.0,737,confirmed,2037,True,"{""url"":""https://data.netzausbau.de/2037-2023/NEP/NEP_2037_2045_Bestaetigung.pdf"", ""status"":""confirmed"", ""origin"":""NEP"",""version"":2024,""location0"":""Sahms/Schleswig-Holstein"",""location1"":""Böblingen/Baden-Württemberg""",10.5331297,53.5252973,9.0113444,48.684969 DC42plus,Sahms/Schleswig-Holstein,Trennfeld/Bayern,2000.0,546,confirmed,2037,True,"{""url"":""https://data.netzausbau.de/2037-2023/NEP/NEP_2037_2045_Bestaetigung.pdf"", ""status"":""confirmed"", ""origin"":""NEP"",""version"":2024,""location0"":""Sahms/Schleswig-Holstein"",""location1"":""Trennfeld/Bayern""",10.5331297,53.5252973,9.6151453,49.7950676 +DC1,Emden Ost,Osterath,2000,297,in_permitting,2027,True,"{url:https://www.netzentwicklungsplan.de/sites/default/files/2024-04/NEP_2037_2045_V2023_Anhang_2E_Aktualisierung_April_2024_%28komprimiert%29.pdf,TYNDP 2022:132,""location0"":""Emden Ost"",""location1"":""Osterath""",7.2492328,53.3655941,6.6207151,51.2690922 +DC2,Osterath,Philippsburg,2000,299,in_permitting,2026,False,"{url:https://www.netzentwicklungsplan.de/sites/default/files/2024-04/NEP_2037_2045_V2023_Anhang_2E_Aktualisierung_April_2024_%28komprimiert%29.pdf,TYNDP 2022: 254,""location0"":""Osterath"",""location1"":""Philippsburg""",6.6207151,51.2690922,7.5514555,48.9953996 +DC3,Brunsbüttel,Großgartach,2000,694,in_permitting,2028,True,"{url:https://www.netzentwicklungsplan.de/sites/default/files/2024-04/NEP_2037_2045_V2023_Anhang_2E_Aktualisierung_April_2024_%28komprimiert%29.pdf,TYNDP 2022: 235,""location0"":""Brunsbüttel"",""location1"":""Großgartach""",9.1395423,53.8972549,9.1258701,49.1425406 +DC4,Wilster ,Bergrheinfeld,2000,540,in_permitting,2028,True,"{url:https://www.netzentwicklungsplan.de/sites/default/files/2024-04/NEP_2037_2045_V2023_Anhang_2E_Aktualisierung_April_2024_%28komprimiert%29.pdf,TYNDP 2022: 235,""location0"":""Wilster "",""location1"":""Bergrheinfeld""",9.3741366,53.9233519,10.1810033,50.0082136 +DC5,Wolmirstedt,Isar/Bayern,2000,539,in_permitting,2027,True,"{url:https://www.netzentwicklungsplan.de/sites/default/files/2024-04/NEP_2037_2045_V2023_Anhang_2E_Aktualisierung_April_2024_%28komprimiert%29.pdf,TYNDP 2022: 130, name:SuedOstLink,""location0"":""Wolmirstedt"",""location1"":""Isar/Bayern""",11.6267388,52.2484924,11.5745421,47.6691308 +DC20,Klein Rogahn,Isar/Bayern,2000,759,in_permitting,2030,False,"{url:https://www.netzentwicklungsplan.de/sites/default/files/2024-04/NEP_2037_2045_V2023_Anhang_2E_Aktualisierung_April_2024_%28komprimiert%29.pdf, name:SuedOstLink+,""location0"":""Klein Rogahn"",""location1"":""Isar/Bayern""",11.3482229,53.6044461,11.5745421,47.6691308 diff --git a/doc/conf.py b/doc/conf.py index f0d1ca37..bb929a46 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -92,9 +92,9 @@ author = "Tom Brown (KIT, TUB, FIAS), Jonas Hoersch (KIT, FIAS), Fabian Hofmann # built documents. # # The short X.Y version. -version = "0.11" +version = "0.12" # The full version, including alpha/beta/rc tags. -release = "0.11.0" +release = "0.12.0" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/configtables/atlite.csv b/doc/configtables/atlite.csv index 5e0d2bd0..10965eed 100644 --- a/doc/configtables/atlite.csv +++ b/doc/configtables/atlite.csv @@ -4,7 +4,7 @@ nprocesses,--,int,"Number of parallel processes in cutout preparation" show_progress,bool,true/false,"Whether progressbar for atlite conversion processes should be shown. False saves time." cutouts,,, -- {name},--,"Convention is to name cutouts like ``--`` (e.g. ``europe-2013-sarah3-era5``).","Name of the cutout netcdf file. The user may specify multiple cutouts under configuration ``atlite: cutouts:``. Reference is used in configuration ``renewable: {technology}: cutout:``. The cutout ``base`` may be used to automatically calculate temporal and spatial bounds of the network." --- -- module,--,"Subset of {'era5','sarah'}","Source of the reanalysis weather dataset (e.g. `ERA5 `_ or `SARAH-2 `_)" +-- -- module,--,"Subset of {'era5','sarah'}","Source of the reanalysis weather dataset (e.g. `ERA5 `_ or `SARAH-3 `_)" -- -- x,°,"Float interval within [-180, 180]","Range of longitudes to download weather data for. If not defined, it defaults to the spatial bounds of all bus shapes." -- -- y,°,"Float interval within [-90, 90]","Range of latitudes to download weather data for. If not defined, it defaults to the spatial bounds of all bus shapes." -- -- dx,°,"Larger than 0.25","Grid resolution for longitude" diff --git a/doc/configtables/industry.csv b/doc/configtables/industry.csv index 4187e118..fd80e804 100644 --- a/doc/configtables/industry.csv +++ b/doc/configtables/industry.csv @@ -35,3 +35,4 @@ MWh_CH4_per_tMeOH,MWhCH4/tMeOH,float,"The energy amount of methane needed to pro MWh_MeOH_per_tMeOH,LHV,float,"The energy amount per ton of methanol. From `DECHEMA (2017) `_, page 74." hotmaps_locate_missing,--,"{true,false}",Locate industrial sites without valid locations based on city and countries. reference_year,year,YYYY,The year used as the baseline for industrial energy demand and production. Data extracted from `JRC-IDEES 2015 `_ +oil_refining_emissions,tCO2/MWh,float,"The emissions from oil fuel processing (e.g. oil in petrochemical refinieries). The default value of 0.013 tCO2/MWh is based on DE statistics for 2019; the EU value is very similar." diff --git a/doc/configtables/sector.csv b/doc/configtables/sector.csv index f8bf0b1b..000927ce 100644 --- a/doc/configtables/sector.csv +++ b/doc/configtables/sector.csv @@ -89,7 +89,9 @@ boilers,--,"{true, false}",Add option for transforming gas into heat using gas b resistive_heaters,--,"{true, false}",Add option for transforming electricity into heat using resistive heaters (independently from gas boilers) oil_boilers,--,"{true, false}",Add option for transforming oil into heat using boilers biomass_boiler,--,"{true, false}",Add option for transforming biomass into heat using boilers -overdimension_individual_heating,--,float,Add option for overdimensioning individual heating systems by a certain factor. This allows them to cover heat demand peaks e.g. 10% higher than those in the data with a setting of 1.1. +overdimension_heat_generators,,,Add option for overdimensioning heating systems by a certain factor. This allows them to cover heat demand peaks e.g. 10% higher than those in the data with a setting of 1.1. +-- decentral,--,float,The factor for overdimensioning (increasing CAPEX) decentral heating systems +-- central,--,float,The factor for overdimensioning (increasing CAPEX) central heating systems chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP) micro_chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP) for decentral areas. solar_thermal,--,"{true, false}",Add option for using solar thermal to generate heat. diff --git a/doc/configtables/solar.csv b/doc/configtables/solar.csv index 21d7c2e4..933c1846 100644 --- a/doc/configtables/solar.csv +++ b/doc/configtables/solar.csv @@ -1,5 +1,5 @@ ,Unit,Values,Description -cutout,--,"Should be a folder listed in the configuration ``atlite: cutouts:`` (e.g. 'europe-2013-sarah3-era5') or reference an existing folder in the directory ``cutouts``. Source module can be ERA5 or SARAH-2.","Specifies the directory where the relevant weather data ist stored that is specified at ``atlite/cutouts`` configuration. Both ``sarah`` and ``era5`` work." +cutout,--,"Should be a folder listed in the configuration ``atlite: cutouts:`` (e.g. 'europe-2013-sarah3-era5') or reference an existing folder in the directory ``cutouts``. Source module can be ERA5 and/or SARAH-3.","Specifies the directory where the relevant weather data ist stored that is specified at ``atlite/cutouts`` configuration. Both ``sarah`` and ``era5`` work." resource,,, -- method,--,"Must be 'pv'","A superordinate technology type." -- panel,--,"One of {'Csi', 'CdTe', 'KANENA'} as defined in `atlite `_ . Can be a string or a dictionary with years as keys which denote the year another turbine model becomes available.","Specifies the solar panel technology and its characteristic attributes." diff --git a/doc/img/intro-workflow.png b/doc/img/intro-workflow.png index 4009fbcd..87cec61f 100644 Binary files a/doc/img/intro-workflow.png and b/doc/img/intro-workflow.png differ diff --git a/doc/preparation.rst b/doc/preparation.rst index 83f9781c..8de4af42 100644 --- a/doc/preparation.rst +++ b/doc/preparation.rst @@ -41,6 +41,17 @@ Rule ``build_cutout`` .. automodule:: build_cutout +Rule ``clean_osm_data`` +============================= + +.. automodule:: clean_osm_data + + +Rule ``build_osm_network`` +============================= + +.. automodule:: build_osm_network + .. _base: Rule ``base_network`` @@ -48,6 +59,12 @@ Rule ``base_network`` .. automodule:: base_network + +Rule ``build_transmission_projects`` +==================================== + +.. automodule:: build_transmission_projects + .. _shapes: Rule ``build_shapes`` @@ -55,6 +72,10 @@ Rule ``build_shapes`` .. automodule:: build_shapes +Rule ``build_gdp_pop_non_nuts3`` +============================= + +.. automodule:: build_gdp_pop_non_nuts3 .. _powerplants: diff --git a/doc/release_notes.rst b/doc/release_notes.rst index b2175bac..f14e4c5a 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -8,30 +8,41 @@ Release Notes ########################################## -Upcoming Release -================ +.. Upcoming Release + * Add technology options for methanol, like electricity production from methanol, biomass to methanol, methanol to kerosene, ... -* Bugfix for passing function arguments in rule :mod:`solve_operations_network`. +* Updated district heating supply temperatures based on `Euroheat's DHC Market Outlook 2024`__ and `AGFW-Hauptbericht 2022 `__. `min_forward_temperature` and `return_temperature` (not given by Euroheat) are extrapolated based on German values. +* Made the overdimensioning factor for heating systems specific for central/decentral heating, defaults to no overdimensionining for central heating and no changes to decentral heating compared to previous version. -* Represent Kosovo (XK) as separate country. +* bugfix: The carrier of stores was silently overwritten by their bus_carrier as a side effect when building the co2 constraints -* Added data on the locations and capacities of ammonia plants in Europe. - This data is used as a spatial distribution key for the ammonia demand. - The data manually collected with sources noted in ``data/ammonia_plants.csv``. +* bugfix: The oil generator was incorrectly dropped when the config `oil_refining_emissions` was greater than zero. This was the default behaviour in 0.12.0. -* Added data on the locations and capacities of cement plants in Europe that are - not included in the Hotmaps industrial database. The data sourced from the - `USGS 2019 Minerals Yearbooks - `__ - of specific countries is used as a spatial distribution key for the cement - demand. The data is stored in ``data/cement-plants-noneu.csv``. +PyPSA-Eur 0.12.0 (30th August 2024) +=================================== -* Added data on the locations and capacities of refineries in Europe that are - not included in the Hotmaps industrial database. The data is mostly sourced - from the `Wikipedia list of oil refineries - `__. The data is stored - in ``data/refineries-noneu.csv``. +**Data Updates and Extensions** + +* Switch to OpenStreetMap (OSM) data for modelling the high-voltage transmission + grid. The new OSM-based grid is is now the default. The previous ENTSO-E grid + data is now deprecated. It can still be used by setting ``electricity: + base_network: entsoegridkit``. The new default setting "osm-prebuilt" + downloads the latest prebuilt snapshots from Zenodo. The setting "osm-raw" + retrieves and cleans the raw OSM data and subsequently builds the network. + (https://github.com/PyPSA/pypsa-eur/pull/1079) + +* Update energy balances from JRC-IDEES-2015 to `JRC-IDEES-2021 + `__. The + reference year was changed from 2015 to 2019. + (https://github.com/PyPSA/pypsa-eur/pull/1167) + +* Updated pre-built `weather data cutouts + `__. These are now merged cutouts with + solar irradiation from the new SARAH-3 dataset while taking all other + variables from ERA5. Cutouts are now available for multiple years (2010, 2013, + 2019, and 2023). The overall download size was cut in half. + (https://github.com/PyPSA/pypsa-eur/pull/1176) * Included data from the `Global Steel Plant Tracker `__ @@ -40,103 +51,237 @@ Upcoming Release and capacities of steel plants in Europe. This data is used as a spatial distribution key for the steel production, which is now separated by process type (EAF, DRI + EAF, integrated). + (https://github.com/PyPSA/pypsa-eur/pull/1241) + +* Added data on the locations and capacities of ammonia plants in Europe. This + data is used as a spatial distribution key for the ammonia demand. The data + manually collected with sources noted in ``data/ammonia_plants.csv``. + (https://github.com/PyPSA/pypsa-eur/pull/1241) + +* Added data on the locations and capacities of cement plants in Europe that are + not included in the Hotmaps industrial database. The data sourced from the + `USGS 2019 Minerals Yearbooks + `__ + of specific countries is used as a spatial distribution key for the cement + demand. The data is stored in ``data/cement-plants-noneu.csv``. + (https://github.com/PyPSA/pypsa-eur/pull/1241) + +* Added data on the locations and capacities of refineries in Europe that are + not included in the Hotmaps industrial database. The data is mostly sourced + from the `Wikipedia list of oil refineries + `__. The data is stored + in ``data/refineries-noneu.csv``. + (https://github.com/PyPSA/pypsa-eur/pull/1241) * Retrieve share of urban population from `World Bank API `__. The data originates from the United Nations Population Division. Previously, a file ``data/urban_percent.csv`` with an undocumented source was used. + (https://github.com/PyPSA/pypsa-eur/pull/1248) + +* Updated Global Energy Monitor's Europe Gas Tracker to May 2024 version. + (https://github.com/PyPSA/pypsa-eur/pull/1235) * Updated country-specific Energy Availability Factors (EAFs) for nuclear power plants based on `IAEA 2021-2023 reported country averages `__. + (https://github.com/PyPSA/pypsa-eur/pull/1236) -* Update GEM Europe Gas Tracker to May 2024 version. +* Updated technology-data to v0.9.2, with added methanol and biomass + assumptions. -* Add investment period dependent CO2 sequestration potentials +* Updated EEZ shapes to v12. This data is now automatically retrieved and was + removed from the data bundle. (https://github.com/PyPSA/pypsa-eur/pull/1188, + https://github.com/PyPSA/pypsa-eur/pull/1210) -* Add option to produce hydrogen from solid biomass (flag ``solid biomass to hydrogen``), combined with carbon capture +* The country shapes from Naturalearth are now automatically retrieved and are + removed from the data bundle. (https://github.com/PyPSA/pypsa-eur/pull/1190) -* Fixed PDF encoding in ``build_biomass_transport_costs`` with update of tabula-py and jpype1 +**New Features** -* More modular and flexible handling of transmission projects. One can now add new transmission projects in a subfolder of `data/transmission projects` similar to the files in the template folder. After adding the new files and updating the config section `transmission_projects:`, transmission projects will be included if they are not duplicates of existing lines or other projects. +* Improved biomass representation: -* Add option to apply a gaussian kernel density smoothing to wind turbine power curves. + * Added unsustainable biomass potentials for solid, gaseous, and liquid biomass + based on current consumption levels from Eurostat energy balances. The + potentials can be phased-out and/or substituted by the phase-in of sustainable + biomass types using the config parameters ``biomass: + share_unsustainable_use_retained`` and ``biomass: + share_sustainable_potential_available``. + (https://github.com/PyPSA/pypsa-eur/pull/1139) -* Update JRC-IDEES-2015 to `JRC-IDEES-2021 `__. The reference year is changed from 2015 to 2019. + * Added energy penalty for BECC applications. + (https://github.com/PyPSA/pypsa-eur/pull/1130) -* Made central heating supply temperatures dynamic based on an adaptation of a reference curve from Pieper et al. (2019) (https://www.sciencedirect.com/science/article/pii/S0360544219305857?via%3Dihub). + * Added option to enable the import of solid biomass. + (https://github.com/PyPSA/pypsa-eur/pull/1194) -* Added option to use country-specific district heating forward and return temperatures. Defaults to lower temperatures in Scandinavia. + * Added option to produce electrobiofuels from solid biomass and hydrogen. This + process combined BtL and Fischer-Tropsch to efficiently use the available + biogenic carbon. (https://github.com/PyPSA/pypsa-eur/pull/1193) -* Added unsustainable biomass potentials for solid, gaseous, and liquid biomass. The potentials can be phased-out and/or - substituted by the phase-in of sustainable biomass types using the config parameters - ``biomass: share_unsustainable_use_retained`` and ``biomass: share_sustainable_potential_available``. + * Added option to split municipal solid waste from solid biomass. + (https://github.com/PyPSA/pypsa-eur/pull/1195, + https://github.com/PyPSA/pypsa-eur/pull/1134) -* The rule ``prepare_links_p_nom`` was removed since it was outdated and not used. + * Added option to produce hydrogen from solid biomass with or without carbon + capture. (https://github.com/PyPSA/pypsa-eur/pull/1213) -* Changed heat pump COP approximation for central heating to be based on `Jensen et al. (2018) `__ and a default forward temperature of 90C. This is more realistic for district heating than the previously used approximation method. +* Improved district heating representation: -* split solid biomass potentials into solid biomass and municipal solid waste. Add option to use municipal solid waste. This option is only activated in combination with the flag ``waste_to_energy`` + * Added option to use country-specific district heating forward and return + temperatures. Defaults to lower temperatures in Scandinavia. + (https://github.com/PyPSA/pypsa-eur/pull/1180) -* Add option to import solid biomass + * Made central heating supply temperatures dynamic based on an adaptation of a + reference curve from Pieper et al. (2019) + (https://www.sciencedirect.com/science/article/pii/S0360544219305857?via%3Dihub). + (https://github.com/PyPSA/pypsa-eur/pull/1206/) -* Add option to produce electrobiofuels (flag ``electrobiofuels``) from solid biomass and hydrogen, as a combination of BtL and Fischer-Tropsch to make more use of the biogenic carbon + * Changed heat pump COP approximation for central heating to be based on + `Jensen et al. (2018) + `__ + and a default forward temperature of 90C. This is more realistic for + district heating than the previously used approximation method. + (https://github.com/PyPSA/pypsa-eur/pull/1176) -* Add flag ``sector: fossil_fuels`` in config to remove the option of importing fossil fuels + * Added option for various power-to-X processes to specify their share of waste + heat that can be used in district heating. The default was changed from 100% + to 25%. (https://github.com/PyPSA/pypsa-eur/pull/1141) -* Renamed the carrier of batteries in BEVs from `battery storage` to `EV battery` and the corresponding bus carrier from `Li ion` to `EV battery`. This is to avoid confusion with stationary battery storage. - -* Changed default assumptions about waste heat usage from PtX and fuel cells in district heating. - The default value for the link efficiency scaling factor was changed from 100% to 25%. - It can be set to other values in the configuration ``sector: use_TECHNOLOGY_waste_heat``. - -* In simplifying polygons in :mod:`build_shapes` default to no tolerance. - -* Set non-zero capital_cost for methanol stores to avoid unrealistic storage sizes - -* Set p_nom = p_nom_min for generators with baseyear == grouping_year in add_existing_baseyear. This has no effect on the optimization but helps n.statistics to correctly report already installed capacities. - -* Reverted outdated hotfix for doubled renewable capacity in myopic optimization. +* Added option to specify emissions fuel processing (e.g. oil in petrochemical + refinieries) with setting ``industry: oil_refining_emissions:``. * Added Enhanced Geothermal Systems for generation of electricity and district heat. Cost and available capacity assumptions based on `Aghahosseini et al. (2020) `__. See configuration ``sector: enhanced_geothermal`` for details; by default switched off. -* Partially revert https://github.com/PyPSA/pypsa-eur/pull/967 to return to old grouping year logic (which was mostly correct) +* Represent Kosovo (XK) as separate country. + (https://github.com/PyPSA/pypsa-eur/pull/1249) -* Bugfix: Correctly read in threshold capacity below which to remove components from previous planning horizons in :mod:`add_brownfield`. +* Add option to specify carbon sequestration potentials per investment period. + (https://github.com/PyPSA/pypsa-eur/pull/1228) -* For countries not contained in the NUTS3-specific datasets (i.e. MD and UA), the mapping of GDP per capita and population per bus region used to spatially distribute electricity demand is now endogenised in a new rule :mod:`build_gdp_ppp_non_nuts3`. https://github.com/PyPSA/pypsa-eur/pull/1146 +* Add option to completely eliminate the use of fossil fuels. + (https://github.com/PyPSA/pypsa-eur/pull/1187) -* The databundle has been updated to release v0.3.0, which includes raw GDP and population data for countries outside the NUTS system (UA, MD). https://github.com/PyPSA/pypsa-eur/pull/1146 +* Added more modular and flexible handling of planned transmission reinforcement + projects (e.g. TYNDP). See configuration settings ``transmission_projects:``. + (https://github.com/PyPSA/pypsa-eur/pull/1085) -* Updated filtering in :mod:`determine_availability_matrix_MD_UA.py` to improve speed. https://github.com/PyPSA/pypsa-eur/pull/1146 - -* Bugfix: Impose minimum value of zero for district heating progress between current and future market share in :mod:`build_district_heat_share`. - -* The ``{scope}`` wildcard was removed, since its outputs were not used. - -* Enable parallelism in :mod:`determine_availability_matrix_MD_UA.py` and remove plots. This requires the use of temporary files. - -* Added new major feature to create the base_network from OpenStreetMap (OSM) data (PR https://github.com/PyPSA/pypsa-eur/pull/1079). Note that a heuristics based cleaning process is used for lines and links where electrical parameters are incomplete, missing, or ambiguous. Through ``electricity["base_network"]``, the base network can be set to "entsoegridkit" (now deprecated), "osm-prebuilt" (default, downloads the latest prebuilt snapshot based on OSM data from Zenodo), or "osm-raw" which retrieves (once) and cleans the raw OSM data and subsequently builds the network. Note that this process may take a few minutes. - -* Updated pre-built `weather data cutouts - `__. These are now merged cutouts with - solar irradiation from the new SARAH-3 dataset while taking all other - variables from ERA5. Cutouts are now available for multiple years (2010, 2013, - 2019, and 2023). +* Added option to smooth wind turbine power curves with a Gaussian kernel density. + (https://github.com/PyPSA/pypsa-eur/pull/1209). * Added option ``solving: curtailment_mode``` which fixes the dispatch profiles of generators with time-varying p_max_pu by setting ``p_min_pu = p_max_pu`` and adds an auxiliary curtailment generator with negative sign (to absorb excess power) at every AC bus. This can speed up the solving process as the curtailment decision is aggregated into a single generator per region. + (https://github.com/PyPSA/pypsa-eur/pull/1177) + +* Added capital costs to all liquid carbonaceous fuel stores. + (https://github.com/PyPSA/pypsa-eur/pull/1234) + +**Breaking Changes** + +* Due to memory issues, the feature ``n.shapes`` is temporarily disabled. + (https://github.com/PyPSA/pypsa-eur/pull/1238) + +* Renamed the carrier of batteries in BEVs from `battery storage` to `EV + battery` and the corresponding bus carrier from `Li ion` to `EV battery`. This + is to avoid confusion with stationary battery storage. + (https://github.com/PyPSA/pypsa-eur/pull/1116) + +**Changes** + +* Powerplants can now be assigned to all buses, not just substations. + (https://github.com/PyPSA/pypsa-eur/pull/1239) + +* Avoid adding existing gas pipelines repeatedly for different planning + horizons. + (https://github.com/PyPSA/pypsa-eur/pull/1162https://github.com/PyPSA/pypsa-eur/pull/1162) + +* Move custom busmaps to + ``data/busmaps/elec_s{simpl}_{clusters}_{base_network}.csv``. This allows for + different busmaps depending on the base network. + (https://github.com/PyPSA/pypsa-eur/pull/1231) + +* For countries not contained in the NUTS3-specific datasets (i.e. MD and UA), + the mapping of GDP per capita and population per bus region used to spatially + distribute electricity demand is now endogenised in a new rule + :mod:`build_gdp_ppp_non_nuts3`. The databundle has been updated accordingly. + (https://github.com/PyPSA/pypsa-eur/pull/1146) + +* Enable parallelism in :mod:`determine_availability_matrix_MD_UA.py` and remove + plots. This requires the use of temporary files. + (https://github.com/PyPSA/pypsa-eur/pull/1170) * In :mod:`base_network`, replace own voronoi polygon calculation function with Geopandas `gdf.voronoi_polygons` method. + (https://github.com/PyPSA/pypsa-eur/pull/1172) + +* In simplifying polygons in :mod:`build_shapes` default to no tolerance. + (https://github.com/PyPSA/pypsa-eur/pull/1137) + +* Updated filtering in :mod:`determine_availability_matrix_MD_UA.py` to improve + speed. (https://github.com/PyPSA/pypsa-eur/pull/1146) + +* Removed unused data files and rules. + (https://github.com/PyPSA/pypsa-eur/pull/1246, + https://github.com/PyPSA/pypsa-eur/pull/1203) + +* The ``{scope}`` wildcard was removed, since its outputs were not used. + (https://github.com/PyPSA/pypsa-eur/pull/1171) + +* Unify how the oil bus is added. + +* Set ``p_nom = p_nom_min`` for generators with ``baseyear == grouping_year`` in + :mod:`add_existing_baseyear`. This has no effect on the optimization but helps + to correctly report already installed capacities using ``n.statistics()``. + +* Cutouts are no longer marked as ``protected()``. + (https://github.com/PyPSA/pypsa-eur/pull/1220) + +**Bugfixes and Compatibility** + +* Bugfix in :mod:`simplify_network` for spatially resolving Corsica. + (https://github.com/PyPSA/pypsa-eur/pull/1215) + +* Bugfix for running without spatial resolution. + (https://github.com/PyPSA/pypsa-eur/pull/1183) + +* Bugfix: Impose minimum value of zero for district heating progress between + current and future market share in :mod:`build_district_heat_share`. + (https://github.com/PyPSA/pypsa-eur/pull/1168) + +* Bugfix: Correctly read in threshold capacity below which to remove components + from previous planning horizons in :mod:`add_brownfield`. + +* Bugfix for passing function arguments in rule :mod:`solve_operations_network`. + +* Bugfix avoiding infinity values in the intermediate industry sector ratios. + (https://github.com/PyPSA/pypsa-eur/pull/1227) + +* Bugfix: Add floating wind to cost update function in + :mod:`prepare_sector_network`. (https://github.com/PyPSA/pypsa-eur/pull/1106) + +* Fixed PDF encoding in ``build_biomass_transport_costs``. + (https://github.com/PyPSA/pypsa-eur/pull/1219) + +* Dropped ``pycountry`` dependency in favour of ``country_converter``. + (https://github.com/PyPSA/pypsa-eur/pull/1188) + +* Use temporary mirror for broken link to Eurostat energy balances (April 2023). + (https://github.com/PyPSA/pypsa-eur/pull/1147) + +* Compatibility with geopandas 1.0+. + (https://github.com/PyPSA/pypsa-eur/pull/1136) + +* Compatibility with snakemake 8.14+. + (https://github.com/PyPSA/pypsa-eur/pull/1112) + +* Address various deprecations. -* Move custom busmaps to ```data/busmaps/elec_s{simpl}_{clusters}_{base_network}.csv``` (if enabled). This allows for different busmaps depending on the base network and scenario. PyPSA-Eur 0.11.0 (25th May 2024) ===================================== diff --git a/doc/retrieve.rst b/doc/retrieve.rst index 6b339355..a00a8c79 100644 --- a/doc/retrieve.rst +++ b/doc/retrieve.rst @@ -19,13 +19,43 @@ Rule ``retrieve_databundle`` .. automodule:: retrieve_databundle +Rule ``retrieve_eurostat_data`` +=============================== + +.. automodule:: retrieve_eurostat_data + + +Rule ``retrieve_jrc_idees`` +=============================== + +.. automodule:: retrieve_jrc_idees + + + +Rule ``retrieve_eurostat_household_data`` +========================================= + +.. automodule:: retrieve_eurostat_household_data + + +Rule ``retrieve_gas_infrastructure_data`` +========================================= + +.. automodule:: retrieve_gas_infrastructure_data + + +Rule ``retrieve_osm_data`` +========================================= + +.. automodule:: retrieve_osm_data + Rule ``retrieve_cutout`` ============================ .. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.6382570.svg :target: https://doi.org/10.5281/zenodo.6382570 -Cutouts are spatio-temporal subsets of the European weather data from the `ECMWF ERA5 `__ reanalysis dataset and the `CMSAF SARAH-2 `__ solar surface radiation dataset for the year 2013. +Cutouts are spatio-temporal subsets of the European weather data from the `ECMWF ERA5 `__ reanalysis dataset and the `CMSAF SARAH-3 `__ solar surface radiation dataset for the year 2013, 2019 or 2023. They have been prepared by and are for use with the `atlite `__ tool. You can either generate them yourself using the ``build_cutouts`` rule or retrieve them directly from `zenodo `__ through the rule ``retrieve_cutout``. The :ref:`tutorial` uses a smaller cutout than required for the full model (30 MB), which is also automatically downloaded. @@ -47,7 +77,7 @@ The :ref:`tutorial` uses a smaller cutout than required for the full model (30 M **Outputs** -- ``cutouts/{cutout}``: weather data from either the `ERA5 `__ reanalysis weather dataset or `SARAH-2 `__ satellite-based historic weather data. +- ``cutouts/{cutout}``: weather data from either the `ERA5 `__ reanalysis weather dataset and/or `SARAH-3 `__ satellite-based historic weather data. .. seealso:: For details see :mod:`build_cutout` and read the `atlite documentation `__. diff --git a/doc/sector.rst b/doc/sector.rst index e186ccf7..24f3c9e9 100644 --- a/doc/sector.rst +++ b/doc/sector.rst @@ -43,6 +43,11 @@ Rule ``build_biomass_potentials`` .. automodule:: build_biomass_potentials +Rule ``build_egs_potentials`` +============================================================================== + +.. automodule:: build_egs_potentials + Rule ``build_biomass_transport_costs`` ============================================================================== @@ -58,6 +63,11 @@ Rule ``build_cop_profiles`` .. automodule:: build_cop_profiles +Rule ``build_central_heating_temperature_profiles`` +============================================================================== + +.. automodule:: build_central_heating_temperature_profiles + Rule ``build_energy_totals`` ============================================================================== diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 4a07132b..f514491e 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -80,7 +80,7 @@ adapt the required range of coordinates to the selection of countries. We can also decide which weather data source should be used to calculate potentials and capacity factor time-series for each carrier. For example, we may -want to use the ERA-5 dataset for solar and not the default SARAH-2 dataset. +want to use the ERA-5 dataset for solar and not the default SARAH-3 dataset. .. literalinclude:: ../config/test/config.electricity.yaml :language: yaml @@ -132,88 +132,98 @@ This triggers a workflow of multiple preceding jobs that depend on each rule's i graph[bgcolor=white, margin=0]; node[shape=box, style=rounded, fontname=sans, fontsize=10, penwidth=2]; edge[penwidth=2, color=grey]; - 0[label = "solve_network", color = "0.21 0.6 0.85", style="rounded"]; - 1[label = "prepare_network\nll: copt\nopts: ", color = "0.51 0.6 0.85", style="rounded"]; - 2[label = "add_extra_components", color = "0.43 0.6 0.85", style="rounded"]; - 3[label = "cluster_network\nclusters: 6", color = "0.17 0.6 0.85", style="rounded"]; - 4[label = "simplify_network\nsimpl: ", color = "0.49 0.6 0.85", style="rounded"]; - 5[label = "add_electricity", color = "0.26 0.6 0.85", style="rounded"]; - 6[label = "build_renewable_profiles\ntechnology: solar", color = "0.02 0.6 0.85", style="rounded"]; - 7[label = "base_network", color = "0.35 0.6 0.85", style="rounded"]; - 8[label = "build_shapes", color = "0.62 0.6 0.85", style="rounded"]; - 9[label = "retrieve_databundle", color = "0.24 0.6 0.85", style="rounded"]; - 10[label = "retrieve_cutout\ncutout: be-03-2013-era5", color = "0.36 0.6 0.85", style="rounded"]; - 11[label = "build_renewable_profiles\ntechnology: solar-hsat", color = "0.02 0.6 0.85", style="rounded"]; - 12[label = "build_renewable_profiles\ntechnology: onwind", color = "0.02 0.6 0.85", style="rounded"]; - 13[label = "build_renewable_profiles\ntechnology: offwind-ac", color = "0.02 0.6 0.85", style="rounded"]; - 14[label = "build_ship_raster", color = "0.08 0.6 0.85", style="rounded"]; - 15[label = "retrieve_ship_raster", color = "0.28 0.6 0.85", style="rounded"]; - 16[label = "build_renewable_profiles\ntechnology: offwind-dc", color = "0.02 0.6 0.85", style="rounded"]; - 17[label = "build_renewable_profiles\ntechnology: offwind-float", color = "0.02 0.6 0.85", style="rounded"]; - 18[label = "build_line_rating", color = "0.07 0.6 0.85", style="rounded"]; - 19[label = "retrieve_cost_data\nyear: 2030", color = "0.47 0.6 0.85", style="rounded"]; - 20[label = "build_powerplants", color = "0.11 0.6 0.85", style="rounded"]; - 21[label = "build_electricity_demand", color = "0.05 0.6 0.85", style="rounded"]; - 22[label = "retrieve_electricity_demand", color = "0.58 0.6 0.85", style="rounded"]; - 23[label = "retrieve_synthetic_electricity_demand", color = "0.11 0.6 0.85", style="rounded"]; + 0[label = "solve_network", color = "0.16 0.6 0.85", style="rounded"]; + 1[label = "prepare_network\nll: copt\nopts: ", color = "0.40 0.6 0.85", style="rounded"]; + 2[label = "add_extra_components", color = "0.03 0.6 0.85", style="rounded"]; + 3[label = "cluster_network\nclusters: 6", color = "0.26 0.6 0.85", style="rounded"]; + 4[label = "simplify_network\nsimpl: ", color = "0.17 0.6 0.85", style="rounded"]; + 5[label = "add_electricity", color = "0.39 0.6 0.85", style="rounded"]; + 6[label = "build_renewable_profiles\ntechnology: solar", color = "0.13 0.6 0.85", style="rounded"]; + 7[label = "base_network", color = "0.01 0.6 0.85", style="rounded"]; + 8[label = "retrieve_osm_prebuilt", color = "0.27 0.6 0.85", style="rounded"]; + 9[label = "build_shapes", color = "0.18 0.6 0.85", style="rounded"]; + 10[label = "retrieve_naturalearth_countries", color = "0.41 0.6 0.85", style="rounded"]; + 11[label = "retrieve_eez", color = "0.14 0.6 0.85", style="rounded"]; + 12[label = "retrieve_databundle", color = "0.38 0.6 0.85", style="rounded"]; + 13[label = "retrieve_cutout\ncutout: be-03-2013-era5", color = "0.51 0.6 0.85", style="rounded"]; + 14[label = "build_renewable_profiles\ntechnology: solar-hsat", color = "0.13 0.6 0.85", style="rounded"]; + 15[label = "build_renewable_profiles\ntechnology: onwind", color = "0.13 0.6 0.85", style="rounded"]; + 16[label = "build_renewable_profiles\ntechnology: offwind-ac", color = "0.13 0.6 0.85", style="rounded"]; + 17[label = "build_ship_raster", color = "0.16 0.6 0.85", style="rounded"]; + 18[label = "retrieve_ship_raster", color = "0.53 0.6 0.85", style="rounded"]; + 19[label = "build_renewable_profiles\ntechnology: offwind-dc", color = "0.13 0.6 0.85", style="rounded"]; + 20[label = "build_renewable_profiles\ntechnology: offwind-float", color = "0.13 0.6 0.85", style="rounded"]; + 21[label = "build_line_rating", color = "0.46 0.6 0.85", style="rounded"]; + 22[label = "build_transmission_projects", color = "0.29 0.6 0.85", style="rounded"]; + 23[label = "retrieve_cost_data\nyear: 2030", color = "0.11 0.6 0.85", style="rounded"]; + 24[label = "build_powerplants", color = "0.18 0.6 0.85", style="rounded"]; + 25[label = "build_electricity_demand", color = "0.30 0.6 0.85", style="rounded"]; + 26[label = "retrieve_electricity_demand", color = "0.13 0.6 0.85", style="rounded"]; + 27[label = "retrieve_synthetic_electricity_demand", color = "0.43 0.6 0.85", style="rounded"]; 1 -> 0 2 -> 1 - 19 -> 1 + 23 -> 1 3 -> 2 - 19 -> 2 + 23 -> 2 4 -> 3 - 19 -> 3 + 23 -> 3 5 -> 4 - 19 -> 4 + 23 -> 4 7 -> 4 6 -> 5 - 11 -> 5 - 12 -> 5 - 13 -> 5 + 14 -> 5 + 15 -> 5 16 -> 5 - 17 -> 5 - 7 -> 5 - 18 -> 5 19 -> 5 20 -> 5 + 7 -> 5 21 -> 5 - 8 -> 5 + 22 -> 5 + 23 -> 5 + 24 -> 5 + 25 -> 5 + 9 -> 5 7 -> 6 + 12 -> 6 9 -> 6 - 8 -> 6 - 10 -> 6 + 13 -> 6 8 -> 7 - 9 -> 8 - 7 -> 11 - 9 -> 11 - 8 -> 11 - 10 -> 11 - 7 -> 12 - 9 -> 12 - 8 -> 12 - 10 -> 12 - 7 -> 13 - 9 -> 13 - 14 -> 13 - 8 -> 13 - 10 -> 13 - 15 -> 14 - 10 -> 14 + 9 -> 7 + 10 -> 9 + 11 -> 9 + 12 -> 9 + 7 -> 14 + 12 -> 14 + 9 -> 14 + 13 -> 14 + 7 -> 15 + 12 -> 15 + 9 -> 15 + 13 -> 15 7 -> 16 + 12 -> 16 + 17 -> 16 9 -> 16 - 14 -> 16 - 8 -> 16 - 10 -> 16 - 7 -> 17 - 9 -> 17 - 14 -> 17 - 8 -> 17 - 10 -> 17 - 7 -> 18 - 10 -> 18 + 13 -> 16 + 18 -> 17 + 13 -> 17 + 7 -> 19 + 12 -> 19 + 17 -> 19 + 9 -> 19 + 13 -> 19 7 -> 20 - 22 -> 21 - 23 -> 21 + 12 -> 20 + 17 -> 20 + 9 -> 20 + 13 -> 20 + 7 -> 21 + 13 -> 21 + 7 -> 22 + 9 -> 22 + 7 -> 24 + 26 -> 25 + 27 -> 25 } | @@ -235,17 +245,21 @@ In the terminal, this will show up as a list of jobs to be run: build_renewable_profiles 6 build_shapes 1 build_ship_raster 1 + build_transmission_projects 1 cluster_network 1 prepare_network 1 retrieve_cost_data 1 retrieve_cutout 1 retrieve_databundle 1 + retrieve_eez 1 retrieve_electricity_demand 1 + retrieve_naturalearth_countries 1 + retrieve_osm_prebuilt 1 retrieve_ship_raster 1 retrieve_synthetic_electricity_demand 1 simplify_network 1 solve_network 1 - total 24 + total 28 ``snakemake`` then runs these jobs in the correct order. diff --git a/doc/tutorial_sector.rst b/doc/tutorial_sector.rst index 450f1e69..a369356f 100644 --- a/doc/tutorial_sector.rst +++ b/doc/tutorial_sector.rst @@ -74,6 +74,7 @@ which were already included in the electricity-only tutorial: base_network 1 build_ammonia_production 1 build_biomass_potentials 1 + build_central_heating_temperature_profiles 1 build_clustered_population_layouts 1 build_cop_profiles 1 build_daily_heat_demand 1 @@ -102,8 +103,9 @@ which were already included in the electricity-only tutorial: build_ship_raster 1 build_shipping_demand 1 build_simplified_population_layouts 1 - build_solar_thermal_profiles 3 - build_temperature_profiles 3 + build_solar_thermal_profiles 1 + build_temperature_profiles 1 + build_transmission_projects 1 build_transport_demand 1 cluster_gas_network 1 cluster_network 1 @@ -118,16 +120,23 @@ which were already included in the electricity-only tutorial: retrieve_cost_data 1 retrieve_cutout 1 retrieve_databundle 1 + retrieve_eez 1 retrieve_electricity_demand 1 retrieve_eurostat_data 1 retrieve_eurostat_household_data 1 retrieve_gas_infrastructure_data 1 + retrieve_gem_europe_gas_tracker 1 + retrieve_gem_steel_plant_tracker 1 + retrieve_jrc_idees 1 + retrieve_naturalearth_countries 1 + retrieve_osm_prebuilt 1 retrieve_ship_raster 1 retrieve_synthetic_electricity_demand 1 + retrieve_worldbank_urban_population 1 simplify_network 1 solve_sector_network 1 time_aggregation 1 - total 69 + total 74 This covers the retrieval of additional raw data from online resources and preprocessing data about the transport, industry, and heating sectors as well as @@ -146,264 +155,266 @@ successfully. graph[bgcolor=white, margin=0]; node[shape=box, style=rounded, fontname=sans, fontsize=10, penwidth=2]; edge[penwidth=2, color=grey]; - 0[label = "all", color = "0.28 0.6 0.85", style="rounded"]; - 1[label = "plot_summary", color = "0.60 0.6 0.85", style="rounded"]; + 0[label = "all", color = "0.22 0.6 0.85", style="rounded"]; + 1[label = "plot_summary", color = "0.11 0.6 0.85", style="rounded"]; 2[label = "make_summary", color = "0.30 0.6 0.85", style="rounded"]; - 3[label = "solve_sector_network", color = "0.36 0.6 0.85", style="rounded"]; - 4[label = "prepare_sector_network\nsector_opts: ", color = "0.22 0.6 0.85", style="rounded"]; - 5[label = "build_renewable_profiles\ntechnology: offwind-ac", color = "0.20 0.6 0.85", style="rounded"]; - 6[label = "base_network", color = "0.00 0.6 0.85", style="rounded"]; - 7[label = "build_shapes", color = "0.25 0.6 0.85", style="rounded"]; - 8[label = "retrieve_databundle", color = "0.06 0.6 0.85", style="rounded"]; - 9[label = "build_ship_raster", color = "0.06 0.6 0.85", style="rounded"]; - 10[label = "retrieve_ship_raster", color = "0.27 0.6 0.85", style="rounded"]; - 11[label = "retrieve_cutout\ncutout: be-03-2013-era5", color = "0.26 0.6 0.85", style="rounded"]; - 12[label = "build_renewable_profiles\ntechnology: offwind-dc", color = "0.20 0.6 0.85", style="rounded"]; - 13[label = "build_renewable_profiles\ntechnology: offwind-float", color = "0.20 0.6 0.85", style="rounded"]; - 14[label = "cluster_gas_network", color = "0.37 0.6 0.85", style="rounded"]; - 15[label = "build_gas_network", color = "0.44 0.6 0.85", style="rounded"]; - 16[label = "retrieve_gas_infrastructure_data", color = "0.43 0.6 0.85", style="rounded"]; - 17[label = "cluster_network\nclusters: 5", color = "0.08 0.6 0.85", style="rounded"]; - 18[label = "simplify_network\nsimpl: ", color = "0.01 0.6 0.85", style="rounded"]; - 19[label = "add_electricity", color = "0.53 0.6 0.85", style="rounded"]; - 20[label = "build_renewable_profiles\ntechnology: solar", color = "0.20 0.6 0.85", style="rounded"]; - 21[label = "build_renewable_profiles\ntechnology: solar-hsat", color = "0.20 0.6 0.85", style="rounded"]; - 22[label = "build_renewable_profiles\ntechnology: onwind", color = "0.20 0.6 0.85", style="rounded"]; - 23[label = "retrieve_cost_data\nyear: 2030", color = "0.11 0.6 0.85", style="rounded"]; - 24[label = "build_powerplants", color = "0.62 0.6 0.85", style="rounded"]; - 25[label = "build_electricity_demand", color = "0.66 0.6 0.85", style="rounded"]; - 26[label = "retrieve_electricity_demand", color = "0.20 0.6 0.85", style="rounded"]; - 27[label = "retrieve_synthetic_electricity_demand", color = "0.52 0.6 0.85", style="rounded"]; - 28[label = "build_gas_input_locations", color = "0.21 0.6 0.85", style="rounded"]; - 29[label = "time_aggregation", color = "0.58 0.6 0.85", style="rounded"]; - 30[label = "prepare_network\nll: v1.5\nopts: ", color = "0.61 0.6 0.85", style="rounded"]; - 31[label = "add_extra_components", color = "0.59 0.6 0.85", style="rounded"]; - 32[label = "build_hourly_heat_demand", color = "0.48 0.6 0.85", style="rounded"]; - 33[label = "build_daily_heat_demand\nscope: total", color = "0.12 0.6 0.85", style="rounded"]; - 34[label = "build_population_layouts", color = "0.62 0.6 0.85", style="rounded"]; - 35[label = "build_solar_thermal_profiles\nscope: total", color = "0.23 0.6 0.85", style="rounded"]; - 36[label = "retrieve_eurostat_data", color = "0.45 0.6 0.85", style="rounded"]; - 37[label = "build_population_weighted_energy_totals\nkind: energy", color = "0.22 0.6 0.85", style="rounded"]; - 38[label = "build_energy_totals", color = "0.65 0.6 0.85", style="rounded"]; - 39[label = "retrieve_eurostat_household_data", color = "0.36 0.6 0.85", style="rounded"]; - 40[label = "build_clustered_population_layouts", color = "0.02 0.6 0.85", style="rounded"]; - 41[label = "build_population_weighted_energy_totals\nkind: heat", color = "0.22 0.6 0.85", style="rounded"]; - 42[label = "build_heat_totals", color = "0.53 0.6 0.85", style="rounded"]; - 43[label = "build_shipping_demand", color = "0.17 0.6 0.85", style="rounded"]; - 44[label = "build_transport_demand", color = "0.49 0.6 0.85", style="rounded"]; - 45[label = "build_temperature_profiles\nscope: total", color = "0.32 0.6 0.85", style="rounded"]; - 46[label = "build_biomass_potentials\nplanning_horizons: 2030", color = "0.34 0.6 0.85", style="rounded"]; - 47[label = "build_salt_cavern_potentials", color = "0.55 0.6 0.85", style="rounded"]; - 48[label = "build_simplified_population_layouts", color = "0.46 0.6 0.85", style="rounded"]; - 49[label = "build_industrial_energy_demand_per_node", color = "0.14 0.6 0.85", style="rounded"]; - 50[label = "build_industry_sector_ratios_intermediate\nplanning_horizons: 2030", color = "0.27 0.6 0.85", style="rounded"]; - 51[label = "build_industry_sector_ratios", color = "0.11 0.6 0.85", style="rounded"]; - 52[label = "build_ammonia_production", color = "0.25 0.6 0.85", style="rounded"]; - 53[label = "build_industrial_energy_demand_per_country_today", color = "0.44 0.6 0.85", style="rounded"]; - 54[label = "build_industrial_production_per_country", color = "0.18 0.6 0.85", style="rounded"]; - 55[label = "build_industrial_production_per_node", color = "0.41 0.6 0.85", style="rounded"]; - 56[label = "build_industrial_distribution_key", color = "0.04 0.6 0.85", style="rounded"]; - 57[label = "build_industrial_production_per_country_tomorrow\nplanning_horizons: 2030", color = "0.09 0.6 0.85", style="rounded"]; - 58[label = "build_industrial_energy_demand_per_node_today", color = "0.46 0.6 0.85", style="rounded"]; - 59[label = "build_district_heat_share\nplanning_horizons: 2030", color = "0.39 0.6 0.85", style="rounded"]; - 60[label = "build_temperature_profiles\nscope: rural", color = "0.32 0.6 0.85", style="rounded"]; - 61[label = "build_temperature_profiles\nscope: urban", color = "0.32 0.6 0.85", style="rounded"]; - 62[label = "build_cop_profiles", color = "0.55 0.6 0.85", style="rounded"]; - 63[label = "build_solar_thermal_profiles\nscope: urban", color = "0.23 0.6 0.85", style="rounded"]; - 64[label = "build_solar_thermal_profiles\nscope: rural", color = "0.23 0.6 0.85", style="rounded"]; - 65[label = "plot_power_network_clustered", color = "0.41 0.6 0.85", style="rounded"]; - 66[label = "plot_power_network", color = "0.40 0.6 0.85", style="rounded"]; - 67[label = "plot_hydrogen_network", color = "0.42 0.6 0.85", style="rounded"]; - 68[label = "plot_gas_network", color = "0.32 0.6 0.85", style="rounded"]; + 3[label = "solve_sector_network", color = "0.42 0.6 0.85", style="rounded"]; + 4[label = "prepare_sector_network\nsector_opts: ", color = "0.45 0.6 0.85", style="rounded"]; + 5[label = "build_renewable_profiles\ntechnology: offwind-ac", color = "0.44 0.6 0.85", style="rounded"]; + 6[label = "base_network", color = "0.26 0.6 0.85", style="rounded"]; + 7[label = "retrieve_osm_prebuilt", color = "0.01 0.6 0.85", style="rounded"]; + 8[label = "build_shapes", color = "0.50 0.6 0.85", style="rounded"]; + 9[label = "retrieve_naturalearth_countries", color = "0.09 0.6 0.85", style="rounded"]; + 10[label = "retrieve_eez", color = "0.52 0.6 0.85", style="rounded"]; + 11[label = "retrieve_databundle", color = "0.00 0.6 0.85", style="rounded"]; + 12[label = "build_ship_raster", color = "0.29 0.6 0.85", style="rounded"]; + 13[label = "retrieve_ship_raster", color = "0.13 0.6 0.85", style="rounded"]; + 14[label = "retrieve_cutout\ncutout: be-03-2013-era5", color = "0.06 0.6 0.85", style="rounded"]; + 15[label = "build_renewable_profiles\ntechnology: offwind-dc", color = "0.44 0.6 0.85", style="rounded"]; + 16[label = "build_renewable_profiles\ntechnology: offwind-float", color = "0.44 0.6 0.85", style="rounded"]; + 17[label = "cluster_gas_network", color = "0.48 0.6 0.85", style="rounded"]; + 18[label = "build_gas_network", color = "0.59 0.6 0.85", style="rounded"]; + 19[label = "retrieve_gas_infrastructure_data", color = "0.14 0.6 0.85", style="rounded"]; + 20[label = "cluster_network\nclusters: 5", color = "0.08 0.6 0.85", style="rounded"]; + 21[label = "simplify_network\nsimpl: ", color = "0.25 0.6 0.85", style="rounded"]; + 22[label = "add_electricity", color = "0.46 0.6 0.85", style="rounded"]; + 23[label = "build_renewable_profiles\ntechnology: solar", color = "0.44 0.6 0.85", style="rounded"]; + 24[label = "build_renewable_profiles\ntechnology: solar-hsat", color = "0.44 0.6 0.85", style="rounded"]; + 25[label = "build_renewable_profiles\ntechnology: onwind", color = "0.44 0.6 0.85", style="rounded"]; + 26[label = "build_transmission_projects", color = "0.63 0.6 0.85", style="rounded"]; + 27[label = "retrieve_cost_data\nyear: 2030", color = "0.05 0.6 0.85", style="rounded"]; + 28[label = "build_powerplants", color = "0.43 0.6 0.85", style="rounded"]; + 29[label = "build_electricity_demand", color = "0.39 0.6 0.85", style="rounded"]; + 30[label = "retrieve_electricity_demand", color = "0.62 0.6 0.85", style="rounded"]; + 31[label = "retrieve_synthetic_electricity_demand", color = "0.31 0.6 0.85", style="rounded"]; + 32[label = "build_gas_input_locations", color = "0.45 0.6 0.85", style="rounded"]; + 33[label = "retrieve_gem_europe_gas_tracker", color = "0.33 0.6 0.85", style="rounded"]; + 34[label = "time_aggregation", color = "0.60 0.6 0.85", style="rounded"]; + 35[label = "prepare_network\nll: v1.5\nopts: ", color = "0.23 0.6 0.85", style="rounded"]; + 36[label = "add_extra_components", color = "0.36 0.6 0.85", style="rounded"]; + 37[label = "build_hourly_heat_demand", color = "0.15 0.6 0.85", style="rounded"]; + 38[label = "build_daily_heat_demand", color = "0.57 0.6 0.85", style="rounded"]; + 39[label = "build_population_layouts", color = "0.47 0.6 0.85", style="rounded"]; + 40[label = "retrieve_worldbank_urban_population", color = "0.19 0.6 0.85", style="rounded"]; + 41[label = "build_solar_thermal_profiles", color = "0.11 0.6 0.85", style="rounded"]; + 42[label = "retrieve_eurostat_data", color = "0.04 0.6 0.85", style="rounded"]; + 43[label = "build_population_weighted_energy_totals\nkind: energy", color = "0.04 0.6 0.85", style="rounded"]; + 44[label = "build_energy_totals", color = "0.30 0.6 0.85", style="rounded"]; + 45[label = "retrieve_jrc_idees", color = "0.02 0.6 0.85", style="rounded"]; + 46[label = "retrieve_eurostat_household_data", color = "0.49 0.6 0.85", style="rounded"]; + 47[label = "build_clustered_population_layouts", color = "0.19 0.6 0.85", style="rounded"]; + 48[label = "build_population_weighted_energy_totals\nkind: heat", color = "0.04 0.6 0.85", style="rounded"]; + 49[label = "build_heat_totals", color = "0.08 0.6 0.85", style="rounded"]; + 50[label = "build_shipping_demand", color = "0.52 0.6 0.85", style="rounded"]; + 51[label = "build_transport_demand", color = "0.16 0.6 0.85", style="rounded"]; + 52[label = "build_temperature_profiles", color = "0.58 0.6 0.85", style="rounded"]; + 53[label = "build_biomass_potentials\nplanning_horizons: 2030", color = "0.55 0.6 0.85", style="rounded"]; + 54[label = "build_salt_cavern_potentials", color = "0.28 0.6 0.85", style="rounded"]; + 55[label = "build_simplified_population_layouts", color = "0.14 0.6 0.85", style="rounded"]; + 56[label = "build_industrial_energy_demand_per_node", color = "0.24 0.6 0.85", style="rounded"]; + 57[label = "build_industry_sector_ratios_intermediate\nplanning_horizons: 2030", color = "0.60 0.6 0.85", style="rounded"]; + 58[label = "build_industry_sector_ratios", color = "0.26 0.6 0.85", style="rounded"]; + 59[label = "build_ammonia_production", color = "0.16 0.6 0.85", style="rounded"]; + 60[label = "build_industrial_energy_demand_per_country_today", color = "0.18 0.6 0.85", style="rounded"]; + 61[label = "build_industrial_production_per_country", color = "0.61 0.6 0.85", style="rounded"]; + 62[label = "build_industrial_production_per_node", color = "0.65 0.6 0.85", style="rounded"]; + 63[label = "build_industrial_distribution_key", color = "0.31 0.6 0.85", style="rounded"]; + 64[label = "retrieve_gem_steel_plant_tracker", color = "0.27 0.6 0.85", style="rounded"]; + 65[label = "build_industrial_production_per_country_tomorrow\nplanning_horizons: 2030", color = "0.09 0.6 0.85", style="rounded"]; + 66[label = "build_industrial_energy_demand_per_node_today", color = "0.40 0.6 0.85", style="rounded"]; + 67[label = "build_district_heat_share\nplanning_horizons: 2030", color = "0.07 0.6 0.85", style="rounded"]; + 68[label = "build_cop_profiles", color = "0.38 0.6 0.85", style="rounded"]; + 69[label = "build_central_heating_temperature_profiles", color = "0.55 0.6 0.85", style="rounded"]; + 70[label = "plot_power_network_clustered", color = "0.20 0.6 0.85", style="rounded"]; + 71[label = "plot_power_network", color = "0.53 0.6 0.85", style="rounded"]; + 72[label = "plot_hydrogen_network", color = "0.64 0.6 0.85", style="rounded"]; + 73[label = "plot_gas_network", color = "0.28 0.6 0.85", style="rounded"]; 1 -> 0 2 -> 1 - 36 -> 1 - 8 -> 1 + 42 -> 1 + 11 -> 1 3 -> 2 - 23 -> 2 - 65 -> 2 - 66 -> 2 - 67 -> 2 - 68 -> 2 + 27 -> 2 + 70 -> 2 + 71 -> 2 + 72 -> 2 + 73 -> 2 4 -> 3 5 -> 4 - 12 -> 4 - 13 -> 4 - 14 -> 4 - 28 -> 4 - 29 -> 4 - 30 -> 4 - 36 -> 4 - 37 -> 4 - 41 -> 4 - 43 -> 4 - 44 -> 4 - 38 -> 4 - 8 -> 4 - 46 -> 4 - 23 -> 4 - 47 -> 4 - 18 -> 4 + 15 -> 4 + 16 -> 4 17 -> 4 - 40 -> 4 - 48 -> 4 - 49 -> 4 32 -> 4 - 59 -> 4 - 45 -> 4 - 60 -> 4 - 61 -> 4 - 62 -> 4 + 34 -> 4 35 -> 4 - 63 -> 4 - 64 -> 4 + 42 -> 4 + 43 -> 4 + 48 -> 4 + 50 -> 4 + 51 -> 4 + 44 -> 4 + 11 -> 4 + 53 -> 4 + 27 -> 4 + 54 -> 4 + 21 -> 4 + 20 -> 4 + 47 -> 4 + 55 -> 4 + 56 -> 4 + 37 -> 4 + 67 -> 4 + 52 -> 4 + 68 -> 4 + 41 -> 4 6 -> 5 - 8 -> 5 - 9 -> 5 - 7 -> 5 11 -> 5 + 12 -> 5 + 8 -> 5 + 14 -> 5 7 -> 6 - 8 -> 7 - 10 -> 9 - 11 -> 9 - 6 -> 12 - 8 -> 12 - 9 -> 12 - 7 -> 12 - 11 -> 12 - 6 -> 13 - 8 -> 13 - 9 -> 13 - 7 -> 13 - 11 -> 13 - 15 -> 14 - 17 -> 14 - 16 -> 15 + 8 -> 6 + 9 -> 8 + 10 -> 8 + 11 -> 8 + 13 -> 12 + 14 -> 12 + 6 -> 15 + 11 -> 15 + 12 -> 15 + 8 -> 15 + 14 -> 15 + 6 -> 16 + 11 -> 16 + 12 -> 16 + 8 -> 16 + 14 -> 16 18 -> 17 - 23 -> 17 + 20 -> 17 19 -> 18 - 23 -> 18 - 6 -> 18 - 20 -> 19 - 21 -> 19 - 22 -> 19 - 5 -> 19 - 12 -> 19 - 13 -> 19 - 6 -> 19 - 23 -> 19 - 24 -> 19 - 25 -> 19 - 7 -> 19 - 6 -> 20 - 8 -> 20 - 7 -> 20 - 11 -> 20 + 21 -> 20 + 27 -> 20 + 22 -> 21 + 27 -> 21 6 -> 21 - 8 -> 21 - 7 -> 21 - 11 -> 21 + 23 -> 22 + 24 -> 22 + 25 -> 22 + 5 -> 22 + 15 -> 22 + 16 -> 22 6 -> 22 + 26 -> 22 + 27 -> 22 + 28 -> 22 + 29 -> 22 8 -> 22 - 7 -> 22 - 11 -> 22 + 6 -> 23 + 11 -> 23 + 8 -> 23 + 14 -> 23 6 -> 24 - 26 -> 25 - 27 -> 25 - 16 -> 28 - 17 -> 28 + 11 -> 24 + 8 -> 24 + 14 -> 24 + 6 -> 25 + 11 -> 25 + 8 -> 25 + 14 -> 25 + 6 -> 26 + 8 -> 26 + 6 -> 28 30 -> 29 - 32 -> 29 - 35 -> 29 - 31 -> 30 - 23 -> 30 - 17 -> 31 - 23 -> 31 + 31 -> 29 33 -> 32 - 34 -> 33 - 17 -> 33 - 11 -> 33 - 7 -> 34 - 11 -> 34 - 34 -> 35 - 17 -> 35 - 11 -> 35 + 19 -> 32 + 20 -> 32 + 35 -> 34 + 37 -> 34 + 41 -> 34 + 36 -> 35 + 27 -> 35 + 20 -> 36 + 27 -> 36 38 -> 37 - 40 -> 37 - 7 -> 38 - 8 -> 38 - 36 -> 38 39 -> 38 - 34 -> 40 - 17 -> 40 - 11 -> 40 - 42 -> 41 - 40 -> 41 - 38 -> 42 - 7 -> 43 - 17 -> 43 - 38 -> 43 - 40 -> 44 - 37 -> 44 - 38 -> 44 + 20 -> 38 + 14 -> 38 + 8 -> 39 + 40 -> 39 + 14 -> 39 + 39 -> 41 + 20 -> 41 + 14 -> 41 + 44 -> 43 + 47 -> 43 8 -> 44 + 11 -> 44 45 -> 44 - 34 -> 45 - 17 -> 45 - 11 -> 45 - 8 -> 46 - 17 -> 46 - 7 -> 46 - 8 -> 47 - 17 -> 47 - 34 -> 48 - 18 -> 48 - 11 -> 48 - 50 -> 49 - 55 -> 49 - 58 -> 49 - 51 -> 50 - 53 -> 50 - 54 -> 50 + 42 -> 44 + 46 -> 44 + 39 -> 47 + 20 -> 47 + 14 -> 47 + 49 -> 48 + 47 -> 48 + 44 -> 49 + 8 -> 50 + 20 -> 50 + 44 -> 50 + 47 -> 51 + 43 -> 51 + 44 -> 51 + 11 -> 51 52 -> 51 - 8 -> 51 - 8 -> 52 + 39 -> 52 + 20 -> 52 + 14 -> 52 + 42 -> 53 + 11 -> 53 + 20 -> 53 8 -> 53 - 54 -> 53 - 52 -> 54 - 8 -> 54 - 36 -> 54 - 56 -> 55 - 57 -> 55 - 17 -> 56 - 40 -> 56 - 54 -> 57 - 56 -> 58 - 53 -> 58 - 38 -> 59 - 40 -> 59 - 34 -> 60 - 17 -> 60 - 11 -> 60 - 34 -> 61 - 17 -> 61 - 11 -> 61 - 45 -> 62 - 60 -> 62 - 61 -> 62 - 34 -> 63 - 17 -> 63 - 11 -> 63 - 34 -> 64 - 17 -> 64 - 11 -> 64 - 17 -> 65 - 3 -> 66 - 17 -> 66 - 3 -> 67 - 17 -> 67 - 3 -> 68 - 17 -> 68 + 11 -> 54 + 20 -> 54 + 39 -> 55 + 21 -> 55 + 14 -> 55 + 57 -> 56 + 62 -> 56 + 66 -> 56 + 58 -> 57 + 60 -> 57 + 61 -> 57 + 59 -> 58 + 45 -> 58 + 44 -> 60 + 45 -> 60 + 61 -> 60 + 59 -> 61 + 45 -> 61 + 42 -> 61 + 63 -> 62 + 65 -> 62 + 20 -> 63 + 47 -> 63 + 64 -> 63 + 61 -> 65 + 63 -> 66 + 60 -> 66 + 44 -> 67 + 47 -> 67 + 69 -> 68 + 52 -> 68 + 20 -> 68 + 52 -> 69 + 20 -> 69 + 20 -> 70 + 3 -> 71 + 20 -> 71 + 3 -> 72 + 20 -> 72 + 3 -> 73 + 20 -> 73 } | diff --git a/envs/environment.fixed.yaml b/envs/environment.fixed.yaml index 31dc7527..ac2d7eee 100644 --- a/envs/environment.fixed.yaml +++ b/envs/environment.fixed.yaml @@ -2,468 +2,9 @@ # # SPDX-License-Identifier: CC0-1.0 -name: pypsa-eur +name: pypsa-eur-20240812 channels: +- http://conda.anaconda.org/gurobi - conda-forge -- bioconda -- gurobi - defaults -dependencies: -- _libgcc_mutex=0.1 -- _openmp_mutex=4.5 -- affine=2.4.0 -- alsa-lib=1.2.11 -- ampl-mp=3.1.0 -- amply=0.1.6 -- appdirs=1.4.4 -- argparse-dataclass=2.0.0 -- asttokens=2.4.1 -- atk-1.0=2.38.0 -- atlite=0.2.12 -- attr=2.5.1 -- attrs=23.2.0 -- aws-c-auth=0.7.22 -- aws-c-cal=0.6.14 -- aws-c-common=0.9.19 -- aws-c-compression=0.2.18 -- aws-c-event-stream=0.4.2 -- aws-c-http=0.8.1 -- aws-c-io=0.14.8 -- aws-c-mqtt=0.10.4 -- aws-c-s3=0.5.9 -- aws-c-sdkutils=0.1.16 -- aws-checksums=0.1.18 -- aws-crt-cpp=0.26.9 -- aws-sdk-cpp=1.11.329 -- azure-core-cpp=1.11.1 -- azure-identity-cpp=1.6.0 -- azure-storage-blobs-cpp=12.10.0 -- azure-storage-common-cpp=12.5.0 -- beautifulsoup4=4.12.3 -- blosc=1.21.5 -- bokeh=3.4.1 -- bottleneck=1.3.8 -- branca=0.7.2 -- brotli=1.1.0 -- brotli-bin=1.1.0 -- brotli-python=1.1.0 -- bzip2=1.0.8 -- c-ares=1.28.1 -- c-blosc2=2.14.4 -- ca-certificates=2024.2.2 -- cads-api-client=1.0.3 -- cairo=1.18.0 -- cartopy=0.23.0 -- cdsapi=0.7.0 -- certifi=2024.2.2 -- cffi=1.16.0 -- cfgv=3.3.1 -- cfitsio=4.4.0 -- cftime=1.6.3 -- charset-normalizer=3.3.2 -- click=8.1.7 -- click-plugins=1.1.1 -- cligj=0.7.2 -- cloudpickle=3.0.0 -- coin-or-cbc=2.10.10 -- coin-or-cgl=0.60.7 -- coin-or-clp=1.17.8 -- coin-or-osi=0.108.10 -- coin-or-utils=2.11.11 -- coincbc=2.10.10 -- colorama=0.4.6 -- conda-inject=1.3.1 -- configargparse=1.7 -- connection_pool=0.0.3 -- contourpy=1.2.1 -- country_converter=1.2 -- cppad=20240000.4 -- cycler=0.12.1 -- cytoolz=0.12.3 -- dask=2024.5.1 -- dask-core=2024.5.1 -- dask-expr=1.1.1 -- datrie=0.8.2 -- dbus=1.13.6 -- decorator=5.1.1 -- deprecation=2.1.0 -- descartes=1.1.0 -- distlib=0.3.8 -- distributed=2024.5.1 -- distro=1.9.0 -- docutils=0.21.2 -- dpath=2.1.6 -- entsoe-py=0.6.7 -- et_xmlfile=1.1.0 -- exceptiongroup=1.2.0 -- executing=2.0.1 -- expat=2.6.2 -- filelock=3.14.0 -- fiona=1.9.6 -- fmt=10.2.1 -- folium=0.16.0 -- font-ttf-dejavu-sans-mono=2.37 -- font-ttf-inconsolata=3.000 -- font-ttf-source-code-pro=2.038 -- font-ttf-ubuntu=0.83 -- fontconfig=2.14.2 -- fonts-conda-ecosystem=1 -- fonts-conda-forge=1 -- fonttools=4.52.1 -- freetype=2.12.1 -- freexl=2.0.0 -- fribidi=1.0.10 -- fsspec=2024.5.0 -- gdal=3.8.5 -- gdk-pixbuf=2.42.12 -- geographiclib=2.0 -- geojson-rewind=1.1.0 -- geopandas=0.14.4 -- geopandas-base=0.14.4 -- geopy=2.4.1 -- geos=3.12.1 -- geotiff=1.7.3 -- gettext=0.22.5 -- gettext-tools=0.22.5 -- gflags=2.2.2 -- giflib=5.2.2 -- gitdb=4.0.11 -- gitpython=3.1.43 -- glib=2.80.2 -- glib-tools=2.80.2 -- glog=0.7.0 -- glpk=5.0 -- gmp=6.3.0 -- graphite2=1.3.13 -- graphviz=11.0.0 -- gst-plugins-base=1.24.3 -- gstreamer=1.24.3 -- gtk2=2.24.33 -- gts=0.7.6 -- gurobi=11.0.2 -- harfbuzz=8.5.0 -- hdf4=4.2.15 -- hdf5=1.14.3 -- humanfriendly=10.0 -- icu=73.2 -- identify=2.5.36 -- idna=3.7 -- immutables=0.20 -- importlib-metadata=7.1.0 -- importlib_metadata=7.1.0 -- importlib_resources=6.4.0 -- iniconfig=2.0.0 -- ipopt=3.14.16 -- ipython=8.24.0 -- jedi=0.19.1 -- jinja2=3.1.4 -- joblib=1.4.2 -- json-c=0.17 -- jsonschema=4.22.0 -- jsonschema-specifications=2023.12.1 -- jupyter_core=5.7.2 -- kealib=1.5.3 -- keyutils=1.6.1 -- kiwisolver=1.4.5 -- krb5=1.21.2 -- lame=3.100 -- lcms2=2.16 -- ld_impl_linux-64=2.40 -- lerc=4.0.0 -- libabseil=20240116.2 -- libaec=1.1.3 -- libarchive=3.7.4 -- libarrow=16.1.0 -- libarrow-acero=16.1.0 -- libarrow-dataset=16.1.0 -- libarrow-substrait=16.1.0 -- libasprintf=0.22.5 -- libasprintf-devel=0.22.5 -- libblas=3.9.0 -- libboost-headers=1.85.0 -- libbrotlicommon=1.1.0 -- libbrotlidec=1.1.0 -- libbrotlienc=1.1.0 -- libcap=2.69 -- libcblas=3.9.0 -- libclang-cpp15=15.0.7 -- libclang13=18.1.5 -- libcrc32c=1.1.2 -- libcups=2.3.3 -- libcurl=8.8.0 -- libdeflate=1.20 -- libedit=3.1.20191231 -- libev=4.33 -- libevent=2.1.12 -- libexpat=2.6.2 -- libffi=3.4.2 -- libflac=1.4.3 -- libgcc-ng=13.2.0 -- libgcrypt=1.10.3 -- libgd=2.3.3 -- libgdal=3.8.5 -- libgettextpo=0.22.5 -- libgettextpo-devel=0.22.5 -- libgfortran-ng=13.2.0 -- libgfortran5=13.2.0 -- libglib=2.80.2 -- libgomp=13.2.0 -- libgoogle-cloud=2.24.0 -- libgoogle-cloud-storage=2.24.0 -- libgpg-error=1.49 -- libgrpc=1.62.2 -- libhwloc=2.9.3 -- libiconv=1.17 -- libjpeg-turbo=3.0.0 -- libkml=1.3.0 -- liblapack=3.9.0 -- liblapacke=3.9.0 -- libllvm15=15.0.7 -- libllvm18=18.1.6 -- libnetcdf=4.9.2 -- libnghttp2=1.58.0 -- libnsl=2.0.1 -- libogg=1.3.4 -- libopenblas=0.3.27 -- libopus=1.3.1 -- libparquet=16.1.0 -- libpng=1.6.43 -- libpq=16.3 -- libprotobuf=4.25.3 -- libre2-11=2023.09.01 -- librsvg=2.58.0 -- librttopo=1.1.0 -- libscotch=7.0.4 -- libsndfile=1.2.2 -- libspatialindex=1.9.3 -- libspatialite=5.1.0 -- libspral=2024.01.18 -- libsqlite=3.45.3 -- libssh2=1.11.0 -- libstdcxx-ng=13.2.0 -- libsystemd0=255 -- libthrift=0.19.0 -- libtiff=4.6.0 -- libutf8proc=2.8.0 -- libuuid=2.38.1 -- libvorbis=1.3.7 -- libwebp=1.4.0 -- libwebp-base=1.4.0 -- libxcb=1.15 -- libxcrypt=4.4.36 -- libxkbcommon=1.7.0 -- libxml2=2.12.7 -- libxslt=1.1.39 -- libzip=1.10.1 -- libzlib=1.2.13 -- linopy=0.3.9 -- locket=1.0.0 -- lxml=5.2.2 -- lz4=4.3.3 -- lz4-c=1.9.4 -- lzo=2.10 -- mapclassify=2.6.1 -- markupsafe=2.1.5 -- matplotlib=3.8.4 -- matplotlib-base=3.8.4 -- matplotlib-inline=0.1.7 -- memory_profiler=0.61.0 -- metis=5.1.0 -- minizip=4.0.5 -- mpfr=4.2.1 -- mpg123=1.32.6 -- msgpack-python=1.0.8 -- multiurl=0.3.1 -- mumps-include=5.7.1 -- mumps-seq=5.7.1 -- munkres=1.1.4 -- mysql-common=8.3.0 -- mysql-libs=8.3.0 -- nbformat=5.10.4 -- ncurses=6.5 -- netcdf4=1.6.5 -- networkx=3.3 -- nodeenv=1.8.0 -- nomkl=1.0 -- nspr=4.35 -- nss=3.100 -- numexpr=2.9.0 -- numpy=1.26.4 -- openjdk=22.0.1 -- openjpeg=2.5.2 -- openpyxl=3.1.2 -- openssl=3.3.0 -- orc=2.0.1 -- packaging=24.0 -- pandas=2.2.2 -- pango=1.52.2 -- parso=0.8.4 -- partd=1.4.2 -- patsy=0.5.6 -- pcre2=10.43 -- pexpect=4.9.0 -- pickleshare=0.7.5 -- pillow=10.3.0 -- pip=24.0 -- pixman=0.43.2 -- pkgutil-resolve-name=1.3.10 -- plac=1.4.3 -- platformdirs=4.2.2 -- pluggy=1.5.0 -- ply=3.11 -- poppler=24.04.0 -- poppler-data=0.4.12 -- postgresql=16.3 -- powerplantmatching=0.5.15 -- pre-commit=3.7.1 -- progressbar2=4.4.2 -- proj=9.4.0 -- prompt-toolkit=3.0.42 -- psutil=5.9.8 -- pthread-stubs=0.4 -- ptyprocess=0.7.0 -- pulp=2.8.0 -- pulseaudio-client=17.0 -- pure_eval=0.2.2 -- py-cpuinfo=9.0.0 -- pyarrow=16.1.0 -- pyarrow-core=16.1.0 -- pyarrow-hotfix=0.6 -- pycountry=22.3.5 -- pycparser=2.22 -- pygments=2.18.0 -- pyomo=6.6.1 -- pyparsing=3.1.2 -- pyproj=3.6.1 -- pypsa=0.29.0 -- pyqt=5.15.9 -- pyqt5-sip=12.12.2 -- pyscipopt=5.0.1 -- pyshp=2.3.1 -- pysocks=1.7.1 -- pytables=3.9.2 -- pytest=8.2.1 -- python=3.11.9 -- python-dateutil=2.9.0 -- python-fastjsonschema=2.19.1 -- python-tzdata=2024.1 -- python-utils=3.8.2 -- python_abi=3.11 -- pytz=2024.1 -- pyxlsb=1.0.10 -- pyyaml=6.0.1 -- qt-main=5.15.8 -- rasterio=1.3.10 -- re2=2023.09.01 -- readline=8.2 -- referencing=0.35.1 -- requests=2.32.2 -- reretry=0.11.8 -- rioxarray=0.15.5 -- rpds-py=0.18.1 -- rtree=1.2.0 -- s2n=1.4.15 -- scikit-learn=1.5.0 -- scip=9.0.1 -- scipy=1.13.1 -- scotch=7.0.4 -- seaborn=0.13.2 -- seaborn-base=0.13.2 -- setuptools=70.0.0 -- setuptools-scm=8.1.0 -- setuptools_scm=8.1.0 -- shapely=2.0.4 -- sip=6.7.12 -- six=1.16.0 -- smart_open=7.0.4 -- smmap=5.0.0 -- snakemake-interface-common=1.17.2 -- snakemake-interface-executor-plugins=9.1.1 -- snakemake-interface-report-plugins=1.0.0 -- snakemake-interface-storage-plugins=3.2.2 -- snakemake-minimal=8.11.6 -- snappy=1.2.0 -- snuggs=1.4.7 -- sortedcontainers=2.4.0 -- soupsieve=2.5 -- spdlog=1.13.0 -- sqlite=3.45.3 -- stack_data=0.6.2 -- statsmodels=0.14.2 -- stopit=1.1.2 -- jpype1=1.5.0 -- tabulate=0.9.0 -- tbb=2021.11.0 -- tblib=3.0.0 -- threadpoolctl=3.5.0 -- throttler=1.2.2 -- tiledb=2.23.0 -- tk=8.6.13 -- toml=0.10.2 -- tomli=2.0.1 -- toolz=0.12.1 -- toposort=1.10 -- tornado=6.4 -- tqdm=4.66.4 -- traitlets=5.14.3 -- typing-extensions=4.11.0 -- typing_extensions=4.11.0 -- tzcode=2024a -- tzdata=2024a -- ukkonen=1.0.1 -- unidecode=1.3.8 -- unixodbc=2.3.12 -- uriparser=0.9.8 -- urllib3=2.2.1 -- validators=0.28.2 -- virtualenv=20.26.2 -- wcwidth=0.2.13 -- wheel=0.43.0 -- wrapt=1.16.0 -- xarray=2024.5.0 -- xcb-util=0.4.0 -- xcb-util-image=0.4.0 -- xcb-util-keysyms=0.4.0 -- xcb-util-renderutil=0.3.9 -- xcb-util-wm=0.4.1 -- xerces-c=3.2.5 -- xkeyboard-config=2.41 -- xlrd=2.0.1 -- xorg-fixesproto=5.0 -- xorg-inputproto=2.3.2 -- xorg-kbproto=1.0.7 -- xorg-libice=1.1.1 -- xorg-libsm=1.2.4 -- xorg-libx11=1.8.9 -- xorg-libxau=1.0.11 -- xorg-libxdmcp=1.1.3 -- xorg-libxext=1.3.4 -- xorg-libxfixes=5.0.3 -- xorg-libxi=1.7.10 -- xorg-libxrender=0.9.11 -- xorg-libxt=1.3.0 -- xorg-libxtst=1.2.3 -- xorg-recordproto=1.14.2 -- xorg-renderproto=0.11.1 -- xorg-xextproto=7.3.0 -- xorg-xf86vidmodeproto=2.3.1 -- xorg-xproto=7.0.31 -- xyzservices=2024.4.0 -- xz=5.2.6 -- yaml=0.2.5 -- yte=1.5.4 -- zict=3.0.0 -- zipp=3.17.0 -- zlib=1.2.13 -- zlib-ng=2.0.7 -- zstd=1.5.6 -- pip: - - highspy==1.5.3 - - oauthlib==3.2.2 - - requests-oauthlib==1.3.1 - - snakemake-executor-plugin-cluster-generic==1.0.9 - - snakemake-executor-plugin-slurm==0.5.1 - - snakemake-executor-plugin-slurm-jobstep==0.2.1 - - snakemake-storage-plugin-http==0.2.3 - - tsam==2.3.1 - - tabula-py=2.9.3 +prefix: /home/fneum/miniconda3/envs/pypsa-eur-20240812 diff --git a/rules/build_sector.smk b/rules/build_sector.smk old mode 100644 new mode 100755 diff --git a/rules/retrieve.smk b/rules/retrieve.smk index c0cd5b6c..67b91b99 100644 --- a/rules/retrieve.smk +++ b/rules/retrieve.smk @@ -312,10 +312,9 @@ if config["enable"]["retrieve"]: run: import requests - response = requests.get( - "https://globalenergymonitor.org/wp-content/uploads/2024/05/Europe-Gas-Tracker-2024-05.xlsx", - headers={"User-Agent": "Mozilla/5.0"}, - ) + # mirror of https://globalenergymonitor.org/wp-content/uploads/2024/05/Europe-Gas-Tracker-2024-05.xlsx + url = "https://tubcloud.tu-berlin.de/s/LMBJQCsN6Ez5cN2/download/Europe-Gas-Tracker-2024-05.xlsx" + response = requests.get(url) with open(output[0], "wb") as f: f.write(response.content) @@ -329,10 +328,9 @@ if config["enable"]["retrieve"]: run: import requests - response = requests.get( - "https://globalenergymonitor.org/wp-content/uploads/2024/04/Global-Steel-Plant-Tracker-April-2024-Standard-Copy-V1.xlsx", - headers={"User-Agent": "Mozilla/5.0"}, - ) + # mirror or https://globalenergymonitor.org/wp-content/uploads/2024/04/Global-Steel-Plant-Tracker-April-2024-Standard-Copy-V1.xlsx + url = "https://tubcloud.tu-berlin.de/s/Aqebo3rrQZWKGsG/download/Global-Steel-Plant-Tracker-April-2024-Standard-Copy-V1.xlsx" + response = requests.get(url) with open(output[0], "wb") as f: f.write(response.content) diff --git a/scripts/build_biomass_potentials.py b/scripts/build_biomass_potentials.py old mode 100644 new mode 100755 index 4c7752e4..a3c51292 --- a/scripts/build_biomass_potentials.py +++ b/scripts/build_biomass_potentials.py @@ -330,7 +330,7 @@ def add_unsustainable_potentials(df): ) share_sus = params.get("share_sustainable_potential_available").get(investment_year) - df *= share_sus + df.loc[df_wo_ch.index] *= share_sus df = df.join(df_wo_ch.filter(like="unsustainable")).fillna(0) @@ -345,8 +345,8 @@ if __name__ == "__main__": snakemake = mock_snakemake( "build_biomass_potentials", simpl="", - clusters="37", - planning_horizons=2020, + clusters="38", + planning_horizons=2050, ) configure_logging(snakemake) diff --git a/scripts/build_biomass_transport_costs.py b/scripts/build_biomass_transport_costs.py index d5650902..db369542 100644 --- a/scripts/build_biomass_transport_costs.py +++ b/scripts/build_biomass_transport_costs.py @@ -79,7 +79,7 @@ def build_biomass_transport_costs(): transport_costs.name = "EUR/km/MWh" # rename country names - to_rename = {"UK": "GB", "XK": "KO", "EL": "GR"} + to_rename = {"UK": "GB", "EL": "GR"} transport_costs.rename(to_rename, inplace=True) # add missing Norway with data from Sweden diff --git a/scripts/build_central_heating_temperature_profiles/central_heating_temperature_approximator.py b/scripts/build_central_heating_temperature_profiles/central_heating_temperature_approximator.py index 5b467824..67f2c019 100644 --- a/scripts/build_central_heating_temperature_profiles/central_heating_temperature_approximator.py +++ b/scripts/build_central_heating_temperature_profiles/central_heating_temperature_approximator.py @@ -58,6 +58,15 @@ class CentralHeatingTemperatureApproximator: rolling_window_ambient_temperature : int Rolling window size for averaging ambient temperature. """ + + if any(max_forward_temperature < min_forward_temperature): + raise ValueError( + "max_forward_temperature must be greater than min_forward_temperature" + ) + if any(min_forward_temperature < fixed_return_temperature): + raise ValueError( + "min_forward_temperature must be greater than fixed_return_temperature" + ) self._ambient_temperature = ambient_temperature self.max_forward_temperature = max_forward_temperature self.min_forward_temperature = min_forward_temperature diff --git a/scripts/build_central_heating_temperature_profiles/run.py b/scripts/build_central_heating_temperature_profiles/run.py index 115293e4..feb4ab4f 100644 --- a/scripts/build_central_heating_temperature_profiles/run.py +++ b/scripts/build_central_heating_temperature_profiles/run.py @@ -9,8 +9,8 @@ al. 2019, where for ambient temperatures below 0C, the highest possible forward temperature is assumed and vice versa for temperatures above 10C. Between these threshold levels, forward temperatures are linearly interpolated. -By default, temperature levels are increased for non-Scandinavian countries. -The default ratios between min. and max. forward temperatures is based on AGFW-Hauptbericht 2022. +By default, `max_forward_temperature` from Euroheat DHC Market Outlook 2024 is used; `min_forward_temperature` and `return_temperature` for Germany is used from AGFW-Hauptbericht 2022. +`min_forward_temperature` and `return_temperature` for other countries are extrapolated based on the ratio between `max_forward_temperature` and `min_forward_temperature` and `return_temperature` for those countries not missing (by default only Germany). Relevant Settings ----------------- @@ -47,26 +47,68 @@ from central_heating_temperature_approximator import ( ) +def extrapolate_missing_supply_temperatures_by_country( + extrapolate_from: dict, extrapolate_to: dict +) -> xr.DataArray: + """ + Extrapolates missing supply temperatures by country. + + Parameters: + extrapolate_from (dict): A dictionary containing supply temperatures to extrapolate from. Should contain all countries. + extrapolate_to (dict): A dictionary containing supply temperatures to extrapolate to. Where `country` is present, average ratio between `extrapolate_to[country]` and `extrapolate_from[country]` is applied to all countries for which `country` is not present in `extrapolate_from.keys()` to infer ratio for extrapolation. + + Returns: + xr.DataArray: A DataArray containing the extrapolated supply temperatures. + """ + + if not all([key in extrapolate_from.keys() for key in extrapolate_to.keys()]): + raise ValueError( + "Not all countries in extrapolate_to are present in extrapolate_from." + ) + # average ratio between extrapolate_from and extrapolate_to for those countries that are in both dictionaries + extrapolation_ratio = np.mean( + [extrapolate_to[key] / extrapolate_from[key] for key in extrapolate_to.keys()] + ) + + # apply extrapolation ratio to all keys missing in extrapolate_to + return { + key: ( + extrapolate_to[key] + if key in extrapolate_to.keys() + else extrapolate_from[key] * extrapolation_ratio + ) + for key in extrapolate_from.keys() + } + + def get_country_from_node_name(node_name: str) -> str: + """ + Extracts the country code from a given node name. + + Parameters: + node_name (str): The name of the node. + + Returns: + str: The country code extracted from the node name. + """ return node_name[:2] def map_temperature_dict_to_onshore_regions( supply_temperature_by_country: dict, regions_onshore: pd.Index, - snapshots: pd.DatetimeIndex, ) -> xr.DataArray: """ Map dictionary of temperatures to onshore regions. + Missing values are replaced by the mean of all values. + Parameters: ---------- supply_temperature_by_country : dictionary - Dictionary with temperatures as values and country keys as keys. One key must be named "default" + Dictionary with temperatures as values and country keys as keys. regions_onshore : pd.Index Names of onshore regions - snapshots : pd.DatetimeIndex - Time stamps Returns: ------- @@ -75,20 +117,16 @@ def map_temperature_dict_to_onshore_regions( """ return xr.DataArray( [ - [ - ( - supply_temperature_by_country[get_country_from_node_name(node_name)] - if get_country_from_node_name(node_name) - in supply_temperature_by_country.keys() - else supply_temperature_by_country["default"] - ) - for node_name in regions_onshore.values - ] - # pass both nodes and snapshots as dimensions to preserve correct data structure - for _ in snapshots + ( + supply_temperature_by_country[get_country_from_node_name(node_name)] + if get_country_from_node_name(node_name) + in supply_temperature_by_country.keys() + else np.mean(list(supply_temperature_by_country.values())) + ) + for node_name in regions_onshore.values ], - dims=["time", "name"], - coords={"time": snapshots, "name": regions_onshore}, + dims=["name"], + coords={"name": regions_onshore}, ) @@ -104,28 +142,35 @@ if __name__ == "__main__": set_scenario_config(snakemake) + max_forward_temperature = snakemake.params.max_forward_temperature_central_heating + min_forward_temperature = extrapolate_missing_supply_temperatures_by_country( + extrapolate_from=max_forward_temperature, + extrapolate_to=snakemake.params.min_forward_temperature_central_heating, + ) + return_temperature = extrapolate_missing_supply_temperatures_by_country( + extrapolate_from=max_forward_temperature, + extrapolate_to=snakemake.params.return_temperature_central_heating, + ) + # map forward and return temperatures specified on country-level to onshore regions regions_onshore = gpd.read_file(snakemake.input.regions_onshore)["name"] snapshots = pd.date_range(freq="h", **snakemake.params.snapshots) max_forward_temperature_central_heating_by_node_and_time: xr.DataArray = ( map_temperature_dict_to_onshore_regions( - supply_temperature_by_country=snakemake.params.max_forward_temperature_central_heating, + supply_temperature_by_country=max_forward_temperature, regions_onshore=regions_onshore, - snapshots=snapshots, ) ) min_forward_temperature_central_heating_by_node_and_time: xr.DataArray = ( map_temperature_dict_to_onshore_regions( - supply_temperature_by_country=snakemake.params.min_forward_temperature_central_heating, + supply_temperature_by_country=min_forward_temperature, regions_onshore=regions_onshore, - snapshots=snapshots, ) ) return_temperature_central_heating_by_node_and_time: xr.DataArray = ( map_temperature_dict_to_onshore_regions( - supply_temperature_by_country=snakemake.params.return_temperature_central_heating, + supply_temperature_by_country=return_temperature, regions_onshore=regions_onshore, - snapshots=snapshots, ) ) diff --git a/scripts/build_cutout.py b/scripts/build_cutout.py index e8d6207c..015eb66a 100644 --- a/scripts/build_cutout.py +++ b/scripts/build_cutout.py @@ -37,7 +37,7 @@ Outputs ------- - ``cutouts/{cutout}``: weather data from either the `ERA5 `_ - reanalysis weather dataset or `SARAH-2 `_ + reanalysis weather dataset or `SARAH-3 `_ satellite-based historic weather data with the following structure: **ERA5 cutout:** @@ -80,7 +80,7 @@ Outputs .. image:: img/era5.png :scale: 40 % -A **SARAH-2 cutout** can be used to amend the fields ``temperature``, ``influx_toa``, ``influx_direct``, ``albedo``, +A **SARAH-3 cutout** can be used to amend the fields ``temperature``, ``influx_toa``, ``influx_direct``, ``albedo``, ``influx_diffuse`` of ERA5 using satellite-based radiation observations. .. image:: img/sarah.png diff --git a/scripts/definitions/heat_system.py b/scripts/definitions/heat_system.py index b907b0fe..2806f6bf 100644 --- a/scripts/definitions/heat_system.py +++ b/scripts/definitions/heat_system.py @@ -5,8 +5,8 @@ from enum import Enum -from scripts.definitions.heat_sector import HeatSector -from scripts.definitions.heat_system_type import HeatSystemType +from definitions.heat_sector import HeatSector +from definitions.heat_system_type import HeatSystemType class HeatSystem(Enum): diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py old mode 100644 new mode 100755 index e1c6fd7c..28a85dbd --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -63,7 +63,8 @@ def define_spatial(nodes, options): if options.get("biomass_spatial", options["biomass_transport"]): spatial.biomass.nodes = nodes + " solid biomass" - spatial.biomass.bioliquids = nodes + " bioliquids" + spatial.biomass.nodes_unsustainable = nodes + " unsustainable solid biomass" + spatial.biomass.bioliquids = nodes + " unsustainable bioliquids" spatial.biomass.locations = nodes spatial.biomass.industry = nodes + " solid biomass for industry" spatial.biomass.industry_cc = nodes + " solid biomass for industry CC" @@ -71,6 +72,7 @@ def define_spatial(nodes, options): spatial.msw.locations = nodes else: spatial.biomass.nodes = ["EU solid biomass"] + spatial.biomass.nodes_unsustainable = ["EU unsustainable solid biomass"] spatial.biomass.bioliquids = ["EU unsustainable bioliquids"] spatial.biomass.locations = ["EU"] spatial.biomass.industry = ["solid biomass for industry"] @@ -573,12 +575,43 @@ def add_carrier_buses(n, carrier, nodes=None): fossils = ["coal", "gas", "oil", "lignite"] if options.get("fossil_fuels", True) and carrier in fossils: + suffix = "" + + if carrier == "oil" and cf_industry["oil_refining_emissions"] > 0: + + n.madd( + "Bus", + nodes + " primary", + location=location, + carrier=carrier + " primary", + unit=unit, + ) + + n.madd( + "Link", + nodes + " refining", + bus0=nodes + " primary", + bus1=nodes, + bus2="co2 atmosphere", + location=location, + carrier=carrier + " refining", + p_nom=1e6, + efficiency=1 + - ( + cf_industry["oil_refining_emissions"] + / costs.at[carrier, "CO2 intensity"] + ), + efficiency2=cf_industry["oil_refining_emissions"], + ) + + suffix = " primary" + n.madd( "Generator", - nodes, - bus=nodes, + nodes + suffix, + bus=nodes + suffix, p_nom_extendable=True, - carrier=carrier, + carrier=carrier + suffix, marginal_cost=costs.at[carrier, "fuel"], ) @@ -2148,8 +2181,6 @@ def add_heat(n: pypsa.Network, costs: pd.DataFrame, cop: xr.DataArray): heat_demand = build_heat_demand(n) - overdim_factor = options["overdimension_individual_heating"] - district_heat_info = pd.read_csv(snakemake.input.district_heat_share, index_col=0) dist_fraction = district_heat_info["district fraction of node"] urban_fraction = district_heat_info["urban fraction"] @@ -2178,6 +2209,9 @@ def add_heat(n: pypsa.Network, costs: pd.DataFrame, cop: xr.DataArray): HeatSystem ): # this loops through all heat systems defined in _entities.HeatSystem + overdim_factor = options["overdimension_heat_generators"][ + heat_system.central_or_decentral + ] if heat_system == HeatSystem.URBAN_CENTRAL: nodes = dist_fraction.index[dist_fraction > 0] else: @@ -2654,7 +2688,7 @@ def add_biomass(n, costs): if ( options["municipal_solid_waste"] and not options["industry"] - and (cf_industry["waste_to_energy"] or cf_industry["waste_to_energy_cc"]) + and not (cf_industry["waste_to_energy"] or cf_industry["waste_to_energy_cc"]) ): logger.warning( "Flag municipal_solid_waste can be only used with industry " @@ -2674,12 +2708,9 @@ def add_biomass(n, costs): carrier="municipal solid waste", ) - e_max_pu = np.array( - len(spatial.msw.nodes) * [[1] * (len(n.snapshots) - 1) + [0]] - ).T - e_max_pu = pd.DataFrame( - e_max_pu, index=n.snapshots, columns=spatial.msw.nodes - ).astype(float) + e_max_pu = pd.DataFrame(1, index=n.snapshots, columns=spatial.msw.nodes) + e_max_pu.iloc[-1] = 0 + n.madd( "Store", spatial.msw.nodes, @@ -2794,14 +2825,23 @@ def add_biomass(n, costs): e_max_pu=e_max_pu, ) - e_max_pu = pd.DataFrame(1, index=n.snapshots, columns=spatial.biomass.nodes) + n.madd( + "Bus", + spatial.biomass.nodes_unsustainable, + location=spatial.biomass.locations, + carrier="unsustainable solid biomass", + unit="MWh_LHV", + ) + + e_max_pu = pd.DataFrame( + 1, index=n.snapshots, columns=spatial.biomass.nodes_unsustainable + ) e_max_pu.iloc[-1] = 0 n.madd( "Store", - spatial.biomass.nodes, - suffix=" unsustainable", - bus=spatial.biomass.nodes, + spatial.biomass.nodes_unsustainable, + bus=spatial.biomass.nodes_unsustainable, carrier="unsustainable solid biomass", e_nom=unsustainable_solid_biomass_potentials_spatial, marginal_cost=costs.at["fuelwood", "fuel"], @@ -2810,6 +2850,16 @@ def add_biomass(n, costs): e_max_pu=e_max_pu, ) + n.madd( + "Link", + spatial.biomass.nodes_unsustainable, + bus0=spatial.biomass.nodes_unsustainable, + bus1=spatial.biomass.nodes, + carrier="unsustainable solid biomass", + efficiency=1, + p_nom=unsustainable_solid_biomass_potentials_spatial, + ) + n.madd( "Bus", spatial.biomass.bioliquids, @@ -2826,7 +2876,6 @@ def add_biomass(n, costs): n.madd( "Store", spatial.biomass.bioliquids, - suffix=" unsustainable", bus=spatial.biomass.bioliquids, carrier="unsustainable bioliquids", e_nom=unsustainable_liquid_biofuel_potentials_spatial, @@ -2836,6 +2885,8 @@ def add_biomass(n, costs): e_max_pu=e_max_pu, ) + add_carrier_buses(n, "oil") + n.madd( "Link", spatial.biomass.bioliquids, @@ -2964,6 +3015,32 @@ def add_biomass(n, costs): constant=biomass_potentials["solid biomass"].sum(), type="operational_limit", ) + if biomass_potentials["unsustainable solid biomass"].sum() > 0: + n.madd( + "Generator", + spatial.biomass.nodes_unsustainable, + bus=spatial.biomass.nodes_unsustainable, + carrier="unsustainable solid biomass", + p_nom=10000, + marginal_cost=costs.at["fuelwood", "fuel"] + + bus_transport_costs * average_distance, + ) + # Set last snapshot of e_max_pu for unsustainable solid biomass to 1 to make operational limit work + unsus_stores_idx = n.stores.query( + "carrier == 'unsustainable solid biomass'" + ).index + unsus_stores_idx = unsus_stores_idx.intersection( + n.stores_t.e_max_pu.columns + ) + n.stores_t.e_max_pu.loc[n.snapshots[-1], unsus_stores_idx] = 1 + n.add( + "GlobalConstraint", + "unsustainable biomass limit", + carrier_attribute="unsustainable solid biomass", + sense="==", + constant=biomass_potentials["unsustainable solid biomass"].sum(), + type="operational_limit", + ) if options["municipal_solid_waste"]: # Add municipal solid waste @@ -3055,7 +3132,9 @@ def add_biomass(n, costs): efficiency=costs.at["biomass boiler", "efficiency"], capital_cost=costs.at["biomass boiler", "efficiency"] * costs.at["biomass boiler", "fixed"] - * options["overdimension_individual_heating"], + * options["overdimension_heat_generators"][ + HeatSystem(name).central_or_decentral + ], marginal_cost=costs.at["biomass boiler", "pelletizing cost"], lifetime=costs.at["biomass boiler", "lifetime"], ) @@ -3577,7 +3656,9 @@ def add_industry(n, costs): efficiency2=costs.at["oil", "CO2 intensity"], capital_cost=costs.at["decentral oil boiler", "efficiency"] * costs.at["decentral oil boiler", "fixed"] - * options["overdimension_individual_heating"], + * options["overdimension_heat_generators"][ + heat_system.central_or_decentral + ], lifetime=costs.at["decentral oil boiler", "lifetime"], ) @@ -3680,9 +3761,13 @@ def add_industry(n, costs): spatial.msw.locations, bus0=spatial.msw.nodes, bus1=non_sequestered_hvc_locations, + bus2="co2 atmosphere", carrier="municipal solid waste", p_nom_extendable=True, efficiency=1.0, + efficiency2=-costs.at[ + "oil", "CO2 intensity" + ], # because msw is co2 neutral and will be burned in waste CHP or decomposed as oil ) n.madd( @@ -4584,11 +4669,10 @@ if __name__ == "__main__": "prepare_sector_network", simpl="", opts="", - clusters="37", + clusters="38", ll="vopt", sector_opts="", - planning_horizons="2050", - run="enable_all", + planning_horizons="2030", ) configure_logging(snakemake) diff --git a/scripts/solve_network.py b/scripts/solve_network.py index c70d4d3c..bdc10dd1 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -330,8 +330,8 @@ def add_carbon_constraint(n, snapshots): continue # stores - n.stores["carrier"] = n.stores.bus.map(n.buses.carrier) - stores = n.stores.query("carrier in @emissions.index and not e_cyclic") + bus_carrier = n.stores.bus.map(n.buses.carrier) + stores = n.stores[bus_carrier.isin(emissions.index) & ~n.stores.e_cyclic] if not stores.empty: last = n.snapshot_weightings.reset_index().groupby("period").last() last_i = last.set_index([last.index, last.timestep]).index @@ -356,8 +356,8 @@ def add_carbon_budget_constraint(n, snapshots): continue # stores - n.stores["carrier"] = n.stores.bus.map(n.buses.carrier) - stores = n.stores.query("carrier in @emissions.index and not e_cyclic") + bus_carrier = n.stores.bus.map(n.buses.carrier) + stores = n.stores[bus_carrier.isin(emissions.index) & ~n.stores.e_cyclic] if not stores.empty: last = n.snapshot_weightings.reset_index().groupby("period").last() last_i = last.set_index([last.index, last.timestep]).index @@ -1000,8 +1000,8 @@ def add_co2_atmosphere_constraint(n, snapshots): continue # stores - n.stores["carrier"] = n.stores.bus.map(n.buses.carrier) - stores = n.stores.query("carrier in @emissions.index and not e_cyclic") + bus_carrier = n.stores.bus.map(n.buses.carrier) + stores = n.stores[bus_carrier.isin(emissions.index) & ~n.stores.e_cyclic] if not stores.empty: last_i = snapshots[-1] lhs = n.model["Store-e"].loc[last_i, stores.index]