diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml index a5c19e594..ceafd7f3f 100644 --- a/.github/workflows/validate.yaml +++ b/.github/workflows/validate.yaml @@ -54,9 +54,9 @@ jobs: # /.png plots: > " - KN2045_Bal_v4/ariadne/primary_energy.png - KN2045_Bal_v4/ariadne/secondary_energy.png - KN2045_Bal_v4/ariadne/final_energy.png + KN2045_Mix/ariadne/primary_energy.png + KN2045_Mix/ariadne/secondary_energy.png + KN2045_Mix/ariadne/final_energy.png ariadne_comparison/Trade-Secondary-Energy-Hydrogen-Volume.png ariadne_comparison/Trade-Secondary-Energy-Liquids-Hydrogen-Volume.png ariadne_comparison/Capacity-Electricity-Solar.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 96a758362..4ef0ca653 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ # Changelog +- 0.3: workflow is all public now, no longer requires credentials to internal data - Allowing myopic optimization until 2050 - CHP plants located in onshore regions without district heating are represented as EOP plants - updating technology cost data to v0.11.0 diff --git a/CITATION.cff b/CITATION.cff index 7c3aa3f64..6ebc9e8f4 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -2,7 +2,7 @@ cff-version: 1.2.0 message: "pypsa-de" title: "PyPSA-DE - Hochaufgelöstes, sektorengekoppeltes Modell des deutschen Energiesystems" repository: https://github.com/PyPSA/pypsa-de -version: 0.2.0 +version: 0.3.0 doi: "10.5281/zenodo.15096969" date-released: "Mar 27, 2025" license: MIT diff --git a/README.md b/README.md index 3378e834e..9e56f2c95 100644 --- a/README.md +++ b/README.md @@ -24,42 +24,11 @@ Where `{os}` should be replaced with your operating system, e.g. for linux the c conda env create -f envs/linux-pinned.yaml ``` -## Connecting to the Ariadne-Database - -### For external users: Use config.public.yaml - -The default workflow configured for this repository assumes access to the internal Ariadne2 database. The database will soon be publicly available. Until then, users that do not have the required login details can run the analysis based on the data published during the [first phase of the Ariadne project](https://data.ece.iiasa.ac.at/ariadne/). - -This is possible by providing an additional config to the snakemake workflow. For every `snakemake COMMAND` specified in the instructions below, public users should use: - -``` -snakemake COMMAND --configfile=config/config.public.yaml -``` - -The additional config file specifies the required database, model, and scenario names for Ariadne1. If public users wish to edit the default scenario specifications, they can do so by changing `scenarios.public.yaml` to `scenarios.manual.yaml`. More details on using scenarios are given below. - -### For internal users: Provide login details - -The snakemake rule `retrieve_ariadne_database` logs into the interal Ariadne IIASA Database via the [`pyam`](https://pyam-iamc.readthedocs.io/en/stable/tutorials/iiasa.html) package. The credentials for logging into this database have to be stored locally on your machine with `ixmp4`. To do this activate the project environment and run - -``` -ixmp4 login -``` - -You will be prompted to enter your ``. - -Caveat: These credentials are stored on your machine in plain text. - -To switch between internal and public use, the command `ixmp4 logout` may be necessary. - ## Run the analysis Before running any analysis with scenarios, the rule `build_scenarios` must be executed. This will create the file `config/scenarios.automated.yaml` which includes input data and CO2 targets from the IIASA Ariadne database as well as the specifications from the manual scenario file. [This file is specified in the config.de.yaml via they key `run:scenarios:manual_file` and located at `config/scenarios.manual.yaml` by default]. snakemake build_scenarios -f -or in case of using the public database - - snakemake build_scenarios --configfile=config/config.public.yaml -f Note that the hierarchy of scenario files is the following: `scenarios.automated.yaml` > (any `explicitly specified --configfiles`) > `config.de.yaml `> `config.default.yaml `Changes in the file `scenarios.manual.yaml `are only taken into account if the rule `build_scenarios` is executed. @@ -88,7 +57,6 @@ PyPSA-DE is a softfork of PyPSA-EUR. As such, large parts of the functionality a - Default resolution of 16 regions in Germany and 13 region for neighboring countries - 10 pre-defined scenarios (1 Current Policies, 3 Net-Zero Scenarios (Balanced, Focus H2, Focus Electricity), 2 Demand Variations based on the Balanced Scenario, 4 Demand Variations Based on the Current Policies Scenario) - Specific cost assumption for Germany: - - Gas, Oil, Coal prices - electrolysis and heat-pump costs - Infrastructure costs [according to the Netzentwicklungsplan](https://github.com/PyPSA/pypsa-ariadne/pull/193) 2021 and 2023 diff --git a/Snakefile b/Snakefile index 85c4f1f89..521929c55 100644 --- a/Snakefile +++ b/Snakefile @@ -453,9 +453,6 @@ rule modify_existing_heating: params: iiasa_reference_scenario=config_provider("iiasa_database", "reference_scenario"), leitmodelle=config_provider("iiasa_database", "leitmodelle"), - fallback_reference_scenario=config_provider( - "iiasa_database", "fallback_reference_scenario" - ), input: ariadne=resources("ariadne_database.csv"), existing_heating="data/existing_infrastructure/existing_heating_raw.csv", @@ -641,9 +638,7 @@ rule export_ariadne_variables: rule plot_ariadne_variables: params: iiasa_scenario=config_provider("iiasa_database", "reference_scenario"), - fallback_reference_scenario=config_provider( - "iiasa_database", "fallback_reference_scenario" - ), + reference_scenario=config_provider("iiasa_database", "reference_scenario"), input: exported_variables_full=RESULTS + "ariadne/exported_variables_full.xlsx", ariadne_database=resources("ariadne_database.csv"), diff --git a/config/config.de.yaml b/config/config.de.yaml index 547e35a0a..5f9436b37 100644 --- a/config/config.de.yaml +++ b/config/config.de.yaml @@ -4,18 +4,14 @@ # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#run run: - prefix: 20250414_merge_master_april + prefix: 20250425_public_db name: - # - CurrentPolicies - - KN2045_Bal_v4 - # - KN2045_Elec_v4 - # - KN2045_H2_v4 - # - KN2045plus_EasyRide - # - KN2045plus_LowDemand - # - KN2045minus_WorstCase - # - KN2045minus_SupplyFocus - # - KN2045_Bal_LowDemand - # - KN2045_Bal_HighDemand + # - ExPol + - KN2045_Mix + # - KN2045_Elek + # - KN2045_H2 + # - KN2045_NFniedrig + # - KN2045_NFhoch scenarios: enable: true manual_file: config/scenarios.manual.yaml @@ -32,22 +28,20 @@ run: disable_progressbar: true iiasa_database: - db_name: ariadne2_intern + db_name: ariadne2 leitmodelle: general: REMIND-EU v1.1 buildings: REMod v1.0 transport: Aladin v1 industry: FORECAST v1.0 scenarios: - - CurrentPolicies - - KN2045_Elec_v4 - - KN2045_H2_v4 - - KN2045_Bal_v4 - - KN2045plus_EasyRide - - KN2045plus_LowDemand - - KN2045minus_WorstCase - - KN2045minus_SupplyFocus - reference_scenario: KN2045_Bal_v4 + - ExPol + - KN2045_Elek + - KN2045_H2 + - KN2045_Mix + - KN2045_NFniedrig + - KN2045_NFhoch + reference_scenario: KN2045_Mix region: Deutschland # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#foresight @@ -298,7 +292,6 @@ sector: rural: true co2_spatial: true biomass_spatial: true - #TBD what to include in config #relax so no infeasibility in 2050 with no land transport demand min_part_load_fischer_tropsch: 0. regional_methanol_demand: true #set to true if regional CO2 constraints needed diff --git a/config/config.public.yaml b/config/config.public.yaml deleted file mode 100644 index 3980ffcf3..000000000 --- a/config/config.public.yaml +++ /dev/null @@ -1,38 +0,0 @@ -# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: CC0-1.0 - -run: - prefix: 20240627public_db - name: - - 8Gt_Bal_v3 - # - 8Gt_Elec_v3 - # - 8Gt_H2_v3 - scenarios: - enable: true - manual_file: config/scenarios.public.yaml - file: config/scenarios.automated.yaml - shared_resources: - policy: base #stops recalculating - exclude: - - existing_heating.csv # specify files which should not be shared between scenarios - - costs - - retrieve_cost # This is necessary to save retrieve_cost_data_{year}.log in the correct folder - - industry_sector_ratios - - build_industry_sector_ratios # This is necessary to save build_industry_sector_ratios_data.log in the correct folder - - modify_existing_heating - -iiasa_database: - db_name: ariadne - leitmodelle: - general: REMIND-EU v1.1 - buildings: REMod v1.0 - transport: REMIND-EU v1.1 - transport_stock: DLR-VECTOR21 - industry: FORECAST v1.0 - scenarios: - - 8Gt_Bal_v3 - - 8Gt_Elec_v3 - - 8Gt_H2_v3 - reference_scenario: 8Gt_Bal_v3 - region: Deutschland diff --git a/config/scenarios.manual.yaml b/config/scenarios.manual.yaml index 0291a1561..121f4c7cb 100644 --- a/config/scenarios.manual.yaml +++ b/config/scenarios.manual.yaml @@ -2,15 +2,14 @@ # SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors # # SPDX-License-Identifier: MIT -CurrentPolicies: +ExPol: # UBA CO2 pathway instead of KSG targets # Europen CO2 pathway fixed at 2030 for 2035-2050 # Kernnetz is not assumed to be built # Not forcing renewables after 2030 iiasa_database: - reference_scenario: CurrentPolicies - fallback_reference_scenario: CurrentPolicies # if the reference scenario is not available (due to late uploads) + reference_scenario: ExPol co2_budget_DE_source: UBA @@ -72,7 +71,7 @@ CurrentPolicies: delay_years: 1 -KN2045_Bal_v4: +KN2045_Mix: # Ausgewogener Mix an Technologien zur Dekarbonisierung der Sektoren # Breites Energieträgerportfolio in der Endenergie (Strom, Wasserstoff, synthetische Kraftstoffe) # Ausbau der erneuerbare Stromerzeugung erreicht politisch gesetzte Ziele @@ -80,8 +79,7 @@ KN2045_Bal_v4: # dient als Referenzszenario in der Familie der Ariadne-Szenarien iiasa_database: - reference_scenario: KN2045_Bal_v4 - fallback_reference_scenario: KN2045_Bal_v4 + reference_scenario: KN2045_Mix co2_budget_DE_source: KSG costs: @@ -101,15 +99,14 @@ KN2045_Bal_v4: steam_hydrogen_fraction: 0.3 steam_electricity_fraction: 0.3 -KN2045_Elec_v4: +KN2045_Elek: # Fokus auf dem Hochlauf von Technologien zur direkten Elektrifizierung der Sektoren # Strom als präferierter Energieträger in der Endenergie, andere Energieträger ergänzend, wo nötig (Wasserstoff, synthetische Kraftstoffe) # Ausbau der erneuerbaren Stromerzeugung erreicht politisch gesetzte Ziele # Importe erneuerbar erzeugter Energien auf mittlerem Niveau iiasa_database: - reference_scenario: KN2045_Elec_v4 - fallback_reference_scenario: KN2045_Elec_v4 + reference_scenario: KN2045_Elek co2_budget_DE_source: KSG costs: @@ -167,15 +164,14 @@ KN2045_Elec_v4: steam_hydrogen_fraction: 0.1 steam_electricity_fraction: 0.5 -KN2045_H2_v4: +KN2045_H2: # Fokus stärker auf dem Hochlauf von Technologien zur indirekten Elektrifizierung der Sektoren # Verstärkter Einsatz von Wasserstoff und synthetischen Kraftstoffen - erneuerbar erzeugt und auch importiert # Direkte Elektrifizierung spielt dennoch wesentliche Rolle bei der Dekarbonisierung der Endenergie # Ausbau der erneuerbaren Stromerzeugung erreicht politisch gesetzte Ziele iiasa_database: - reference_scenario: KN2045_H2_v4 - fallback_reference_scenario: KN2045_H2_v4 + reference_scenario: KN2045_H2 co2_budget_DE_source: KSG costs: @@ -246,312 +242,7 @@ KN2045_H2_v4: steam_hydrogen_fraction: 0.5 steam_electricity_fraction: 0.1 -KN2045plus_EasyRide: -# Endenergienachfrage ist geringer im Vergleich zu Szenarien 1-3 -# Hochlauf klimafreundlicher/effizienter Technologien schneller und günstiger -# evtl. früheres Verbrennerverbot, schärferes Heizungsgesetz -# EE weiterhin auskömmlich nur werden die Ausbauziele evtl. nicht voll ausgeschöpft -# Verlagerung der energieintensiven Grundstoffindustrie - iiasa_database: - reference_scenario: KN2045plus_EasyRide # TODO: wait for database - fallback_reference_scenario: KN2045_Bal_v4 - co2_budget_DE_source: KSG - - costs: - horizon: "optimist" - NEP: 2023 - transmission: "overhead" # either overhead line ("overhead") or underground cable ("underground") - solving: - constraints: - # boundary condition of maximum volumes - limits_volume_max: # following the Bal scenario - h2_import: - DE: - 2020: 0 - 2025: 5 - 2030: 15 - 2035: 115 - 2040: 220 - 2045: 325 - 2050: 325 - limits_capacity_min: - Link: - H2 Electrolysis: - DE: - 2030: 5 - - industry: - steam_biomass_fraction: 0.4 - steam_hydrogen_fraction: 0.3 - steam_electricity_fraction: 0.3 - sector: - reduce_space_heat_exogenously_factor: - 2020: 0.0 - 2025: 0.08 - 2030: 0.16 - 2035: 0.25 - 2040: 0.34 - 2045: 0.43 - 2050: 0.50 - -KN2045plus_LowDemand: -# Im Vergleich zu Easy Ride eher knappe EE Erzeugung -# innerhalb Deutschlands und knappe Importe EE möglich - iiasa_database: - reference_scenario: KN2045plus_LowDemand # TODO: wait for database - fallback_reference_scenario: KN2045_Bal_v4 - co2_budget_DE_source: KSG - - costs: - horizon: "optimist" - NEP: 2023 - transmission: "overhead" # either overhead line ("overhead") or underground cable ("underground") - solving: - constraints: - # boundary condition of maximum volumes - limits_volume_max: # Half of the Bal scenario - # constrain electricity import in TWh - electricity_import: - DE: - 2020: -20 - 2025: 0 - 2030: 0 - 2035: 20 - 2040: 40 - 2045: 62.5 - 2050: 62.5 - electrolysis: - DE: - 2020: 0 - 2025: 2.5 - 2030: 22.5 - 2035: 65 - 2040: 107.5 - 2045: 150 - 2050: 150 - h2_derivate_import: - DE: - 2020: 0 - 2025: 0 - 2030: 5 - 2035: 52.5 - 2040: 100 - 2045: 150 - 2050: 150 - h2_import: - DE: - 2020: 0 - 2025: 2.5 - 2030: 7.5 - 2035: 57.5 - 2040: 110 - 2045: 162.5 - 2050: 162.5 - limits_capacity_min: - Link: - H2 Electrolysis: - DE: - 2030: 5 - - industry: - steam_biomass_fraction: 0.4 - steam_hydrogen_fraction: 0.3 - steam_electricity_fraction: 0.3 - sector: - reduce_space_heat_exogenously_factor: - 2020: 0.0 - 2025: 0.08 - 2030: 0.16 - 2035: 0.25 - 2040: 0.34 - 2045: 0.43 - 2050: 0.50 - -KN2045minus_WorstCase: -# Nachfrage nach Endenergie ist höher als in den Szenarien 1-3 -# schlechtere Akzeptanz in der Bevölkerung, Verzögerungen im Infrastrukturausbau, -# geringere Preissenkung für Technologien -# Verfehlen der Reduktionsziele in 2030 und 2045 -# eher knapper Ausbau EE und EE Importe - iiasa_database: - reference_scenario: KN2045minus_WorstCase - fallback_reference_scenario: CurrentPolicies - - co2_budget_DE_source: UBA - - co2_budget: - 2020: 0.720 # average emissions of 2019 to 2021 relative to 1990, excl LULUCF, EEA data, European Environment Agency. (2023a). Annual European Union greenhouse gas inventory 1990–2021 and inventory report 2023 - CRF Table. https://unfccc.int/documents/627830 - 2025: 0.675 # With existing measures (WEM) projection, CO2 excl LULUCF, European Environment Agency. (2023e). Member States’ greenhouse gas (GHG) emission projections 2023. https://www.eea.europa.eu/en/datahub/datahubitem-view/4b8d94a4-aed7-4e67-a54c-0623a50f48e8 - 2030: 0.569 - 2035: 0.502 - 2040: 0.452 - 2045: 0.431 - 2050: 0.419 - - costs: - horizon: "pessimist" - NEP: 2023 - transmission: "underground" # either overhead line ("overhead") or underground cable ("underground") - solving: - constraints: - # boundary condition of maximum volumes - limits_volume_max: # Half of the Bal scenario - # constrain electricity import in TWh - electricity_import: - DE: - 2020: -20 - 2025: 0 - 2030: 0 - 2035: 20 - 2040: 40 - 2045: 62.5 - 2050: 62.5 - electrolysis: - DE: - 2020: 0 - 2025: 2.5 - 2030: 22.5 - 2035: 65 - 2040: 107.5 - 2045: 150 - 2050: 150 - h2_derivate_import: - DE: - 2020: 0 - 2025: 0 - 2030: 5 - 2035: 52.5 - 2040: 100 - 2045: 150 - 2050: 150 - h2_import: - DE: - 2020: 0 - 2025: 2.5 - 2030: 7.5 - 2035: 57.5 - 2040: 110 - 2045: 162.5 - 2050: 162.5 - limits_capacity_min: - Generator: - onwind: - DE: - 2030: 86.5 # 75 % Wind-an-Land Law - offwind: - DE: - 2030: 17.3 # 75 % Wind-auf-See Law - 2035: 29.3 - solar: - DE: - 2030: 161.25 # 75 % PV strategy - Link: - H2 Electrolysis: - DE: - 2030: 5 - limits_capacity_max: - Generator: - offwind: - DE: - 2020: 7.8 - 2025: 11.3 - 2030: 17.3 # 12 less than NEP, because of 1 year delay - 2035: 40 # 29.3 + half of extra projects - onwind: - DE: - 2030: 94.5 # uba Projektionsbericht - solar: - DE: - 2030: 215 # uba Projektionsbericht - industry: - steam_biomass_fraction: 0.4 - steam_hydrogen_fraction: 0.3 - steam_electricity_fraction: 0.3 - - sector: - district_heating: - potential: 0.1 - reduce_space_heat_exogenously_factor: - 2020: 0.0 - 2025: 0.06 - 2030: 0.12 - 2035: 0.18 - 2040: 0.24 - 2045: 0.29 - 2050: 0.33 - offshore_nep_force: - cutin_year: 2025 - cutout_year: 2035 # Hackily reduced to 2030 if delay_years: 1 - delay_years: 1 - - -KN2045minus_SupplyFocus: -# Nachfrage genau so hoch wie in Szenario WorstCase -# Ausbau EE und EE Importe jetzt aber auskömmlich - iiasa_database: - reference_scenario: KN2045minus_SupplyFocus - fallback_reference_scenario: CurrentPolicies - - costs: - horizon: "pessimist" - NEP: 2023 - transmission: "underground" # either overhead line ("overhead") or underground cable ("underground") - co2_budget_DE_source: UBA - - co2_budget: - 2020: 0.720 # average emissions of 2019 to 2021 relative to 1990, excl LULUCF, EEA data, European Environment Agency. (2023a). Annual European Union greenhouse gas inventory 1990–2021 and inventory report 2023 - CRF Table. https://unfccc.int/documents/627830 - 2025: 0.675 # With existing measures (WEM) projection, CO2 excl LULUCF, European Environment Agency. (2023e). Member States’ greenhouse gas (GHG) emission projections 2023. https://www.eea.europa.eu/en/datahub/datahubitem-view/4b8d94a4-aed7-4e67-a54c-0623a50f48e8 - 2030: 0.569 - 2035: 0.502 - 2040: 0.452 - 2045: 0.431 - 2050: 0.419 - solving: - constraints: - # boundary condition of maximum volumes - limits_volume_max: # following the Bal scenario - h2_import: - DE: - 2020: 0 - 2025: 5 - 2030: 15 - 2035: 115 - 2040: 220 - 2045: 325 - 2050: 325 - limits_capacity_min: - Generator: - onwind: - DE: - 2030: 115 # Wind-an-Land Law - solar: - DE: - 2025: 101 - 2030: 215 # PV strategy - Link: - H2 Electrolysis: - DE: - 2030: 5 - limits_capacity_max: - Generator: - solar: - DE: - 2030: 215 # uba Projektionsbericht - industry: - steam_biomass_fraction: 0.4 - steam_hydrogen_fraction: 0.3 - steam_electricity_fraction: 0.3 - sector: - reduce_space_heat_exogenously_factor: - 2020: 0.0 - 2025: 0.06 - 2030: 0.12 - 2035: 0.18 - 2040: 0.24 - 2045: 0.29 - 2050: 0.33 - -KN2045_Bal_LowDemand: +KN2045_NFniedrig: # Ausgewogener Mix an Technologien zur Dekarbonisierung der Sektoren # Breites Energieträgerportfolio in der Endenergie (Strom, Wasserstoff, synthetische Kraftstoffe) # Ausbau der erneuerbare Stromerzeugung erreicht politisch gesetzte Ziele @@ -560,7 +251,6 @@ KN2045_Bal_LowDemand: iiasa_database: reference_scenario: KN2045plus_LowDemand - fallback_reference_scenario: KN2045_Bal_v4 co2_budget_DE_source: KSG costs: @@ -600,7 +290,7 @@ KN2045_Bal_LowDemand: 2045: 0.43 2050: 0.50 -KN2045_Bal_HighDemand: +KN2045_NFhoch: # Ausgewogener Mix an Technologien zur Dekarbonisierung der Sektoren # Breites Energieträgerportfolio in der Endenergie (Strom, Wasserstoff, synthetische Kraftstoffe) # Ausbau der erneuerbare Stromerzeugung erreicht politisch gesetzte Ziele @@ -609,7 +299,6 @@ KN2045_Bal_HighDemand: iiasa_database: reference_scenario: KN2045minus_SupplyFocus - fallback_reference_scenario: KN2045_Bal_v4 co2_budget_DE_source: KSG costs: diff --git a/config/scenarios.public.yaml b/config/scenarios.public.yaml deleted file mode 100644 index beca6d98c..000000000 --- a/config/scenarios.public.yaml +++ /dev/null @@ -1,207 +0,0 @@ -# -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: : 2017-2023 The PyPSA-Eur Authors -# -# SPDX-License-Identifier: MIT - - -8Gt_Bal_v3: - iiasa_database: - reference_scenario: 8Gt_Bal_v3 - fallback_reference_scenario: 8Gt_Bal_v3 - co2_budget_DE_source: KSG - - costs: - horizon: "mean" - NEP: 2023 - transmission: "overhead" # either overhead line ("overhead") or underground cable ("underground") - solving: - constraints: - # boundary condition of maximum volumes - limits_volume_max: - # constrain electricity import in TWh - electricity_import: - DE: - 2020: -20 - 2025: 0 - 2030: 0 - 2035: 40 - 2040: 80 - 2045: 125 - electrolysis: - DE: - 2020: 0 - 2025: 5 - 2030: 45 - 2035: 130 - 2040: 215 - 2045: 300 - h2_derivate_import: - DE: - 2020: 0 - 2025: 0 - 2030: 10 - 2035: 105 - 2040: 200 - 2045: 300 - h2_import: - DE: - 2020: 0 - 2025: 5 - 2030: 15 - 2035: 115 - 2040: 220 - 2045: 325 - limits_volume_min: - electrolysis: - DE: - 2020: 0 - 2025: 0 - 2030: 0 - 2035: 0 - 2040: 0 - 2045: 0 - limits_capacity_min: - Link: - H2 Electrolysis: - DE: - 2030: 5 - - industry: - steam_biomass_fraction: 0.4 - steam_hydrogen_fraction: 0.3 - steam_electricity_fraction: 0.3 - -8Gt_Elec_v3: - iiasa_database: - reference_scenario: 8Gt_Elec_v3 - fallback_reference_scenario: 8Gt_Elec_v3 - co2_budget_DE_source: KSG - - costs: - horizon: "mean" - NEP: 2023 - transmission: "overhead" # either overhead line ("overhead") or underground cable ("underground") - solving: - constraints: - limits_volume_max: - # constrain electricity import in TWh - electricity_import: - DE: - 2020: -20 - 2025: 0 - 2030: 0 - 2035: 50 - 2040: 100 - 2045: 150 - electrolysis: - DE: - 2020: 0 - 2025: 5 - 2030: 45 - 2035: 95 - 2040: 145 - 2045: 200 - h2_derivate_import: - DE: - 2020: 0 - 2025: 0 - 2030: 10 - 2035: 70 - 2040: 130 - 2045: 200 - h2_import: - DE: - 2020: 0 - 2025: 5 - 2030: 10 - 2035: 90 - 2040: 170 - 2045: 250 - limits_volume_min: - electrolysis: - DE: - 2020: 0 - 2025: 0 - 2030: 0 - 2035: 0 - 2040: 0 - 2045: 0 - limits_capacity_min: - Link: - H2 Electrolysis: - DE: - 2030: 5 - - industry: - steam_biomass_fraction: 0.4 - steam_hydrogen_fraction: 0.1 - steam_electricity_fraction: 0.5 - -8Gt_H2_v3: - iiasa_database: - reference_scenario: 8Gt_H2_v3 - fallback_reference_scenario: 8Gt_H2_v3 - co2_budget_DE_source: KSG - - costs: - horizon: "mean" - NEP: 2023 - transmission: "overhead" # either overhead line ("overhead") or underground cable ("underground") - solving: - constraints: - limits_volume_max: - # constrain electricity import in TWh - electricity_import: - DE: - 2020: -20 - 2025: 0 - 2030: 0 - 2035: 30 - 2040: 70 - 2045: 100 # scenario guidelines - - # constrain hydrogen import in TWh - h2_import: - DE: - 2020: 0 - 2025: 5 - 2030: 45 # scenario guidelines - 2035: 155 - 2040: 265 - 2045: 400 # scenario guidelines - # import of h2 derivatives in TWh - h2_derivate_import: - DE: - 2020: 0 - 2025: 0 - 2030: 10 # scenario guidelines - 2035: 140 - 2040: 270 - 2045: 400 # scenario guidelines - electrolysis: - DE: - 2020: 0 - 2025: 5 - 2030: 45 # scenario guidelines - 2035: 160 - 2040: 275 - 2045: 400 # scenario guidelines - - limits_volume_min: - electrolysis: - DE: - 2025: 0 - 2030: 0 - 2035: 0 - 2040: 0 - 2045: 200 - limits_capacity_min: - Link: - H2 Electrolysis: - DE: - 2030: 5 - - industry: - steam_biomass_fraction: 0.4 - steam_hydrogen_fraction: 0.5 - steam_electricity_fraction: 0.1 diff --git a/config/scenarios.template.yaml b/config/scenarios.template.yaml deleted file mode 100644 index 823f9408f..000000000 --- a/config/scenarios.template.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# -*- coding: utf-8 -*- -# SPDX-FileCopyrightText: Contributors to PyPSA-Eur -# -# SPDX-License-Identifier: MIT - -# This file is used to define the scenarios that are run by snakemake. Each entry on the first level is a scenario. Each scenario can contain configuration overrides with respect to the config/config.yaml settings. -# -# Example -# -# custom-scenario: # name of the scenario -# electricity: -# renewable_carriers: [wind, solar] # override the list of renewable carriers - -normal: - electricity: - renewable_carriers: - - solar - - onwind - - offwind-ac - - offwind-dc - - hydro - -no-offwind: - electricity: - renewable_carriers: - - solar - - onwind - - hydro diff --git a/config/test/config.dach.yaml b/config/test/config.dach.yaml index ea312e8b3..9a8b860bb 100644 --- a/config/test/config.dach.yaml +++ b/config/test/config.dach.yaml @@ -5,11 +5,11 @@ run: prefix: "test-sector-myopic-dach" name: - - KN2045_Bal_v4 + - KN2045_Mix scenario: clusters: - - 5 #current options: 27, 49 + - 5 countries: ['DE', 'AT', 'CH'] snapshots: diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 38ce8971f..b621f1ced 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -1076,7 +1076,7 @@ def add_heating_capacities_installed_before_baseyear( opts="", sector_opts="none", planning_horizons="2020", - run="KN2045_Bal_v4", + run="KN2045_Mix", ) configure_logging(snakemake) # pylint: disable=E0606 diff --git a/scripts/plot_statistics_comparison.py b/scripts/plot_statistics_comparison.py index a11d2e4ae..a88ff822d 100644 --- a/scripts/plot_statistics_comparison.py +++ b/scripts/plot_statistics_comparison.py @@ -90,7 +90,7 @@ def read_csv(input, output): snakemake = mock_snakemake( "plot_statistics_comparison", - run="CurrentPolicies", + run="ExPol", country="DE", carrier="H2", ) diff --git a/scripts/plot_statistics_single.py b/scripts/plot_statistics_single.py index 748b23f81..85ecdbb00 100644 --- a/scripts/plot_statistics_single.py +++ b/scripts/plot_statistics_single.py @@ -55,7 +55,7 @@ def read_csv(input): snakemake = mock_snakemake( "plot_statistics_single", - run="CurrentPolicies", + run="ExPol", simpl="", ll="vopt", clusters="22", diff --git a/scripts/plot_summary.py b/scripts/plot_summary.py index 568e51972..08e084fb5 100644 --- a/scripts/plot_summary.py +++ b/scripts/plot_summary.py @@ -92,12 +92,15 @@ def plot_costs(): fig, ax = plt.subplots(figsize=(12, 8)) - df.loc[new_index].T.plot( - kind="bar", - ax=ax, - stacked=True, - color=[snakemake.params.plotting["tech_colors"][i] for i in new_index], - ) + if df.empty: + ax.bar([], []) + else: + df.loc[new_index].T.plot( + kind="bar", + ax=ax, + stacked=True, + color=[snakemake.params.plotting["tech_colors"][i] for i in new_index], + ) handles, labels = ax.get_legend_handles_labels() diff --git a/scripts/pypsa-de/build_egon_data.py b/scripts/pypsa-de/build_egon_data.py index 7bf559617..5fc4ace1e 100644 --- a/scripts/pypsa-de/build_egon_data.py +++ b/scripts/pypsa-de/build_egon_data.py @@ -30,7 +30,7 @@ if "snakemake" not in globals(): snakemake = mock_snakemake( "build_egon_data", - run="KN2045_Bal_v4", + run="KN2045_Mix", ) configure_logging(snakemake) diff --git a/scripts/pypsa-de/build_existing_chp_de.py b/scripts/pypsa-de/build_existing_chp_de.py index e727f7a5b..9d965f81a 100644 --- a/scripts/pypsa-de/build_existing_chp_de.py +++ b/scripts/pypsa-de/build_existing_chp_de.py @@ -211,7 +211,7 @@ def BP(cap, year): snakemake = mock_snakemake( "build_existing_chp_de", clusters=27, - run="KN2045_Bal_v4", + run="KN2045_Mix", ) configure_logging(snakemake) diff --git a/scripts/pypsa-de/build_mobility_demand.py b/scripts/pypsa-de/build_mobility_demand.py index 6ede31073..c7eacdd88 100644 --- a/scripts/pypsa-de/build_mobility_demand.py +++ b/scripts/pypsa-de/build_mobility_demand.py @@ -7,38 +7,43 @@ logger = logging.getLogger(__name__) -def get_transport_data(db): +def get_transport_data(db, year): """ Retrieve the German mobility demand from the transport_data model. Sum over the subsectors Bus, LDV, Rail, and Truck for the fuels electricity, hydrogen, and synthetic fuels. """ - # get transport_data data - - df = db.loc[snakemake.params.leitmodelle["transport"]] - subsectors = ["Bus", "LDV", "Rail", "Truck"] fuels = ["Electricity", "Hydrogen", "Liquids"] transport_demand = pd.Series(0.0, index=fuels) - for fuel in fuels: - for subsector in subsectors: - key = f"Final Energy|Transportation|{subsector}|{fuel}" - if snakemake.params.db_name == "ariadne": - transport_demand.loc[fuel] += df.get((key, "TWh/yr"), 0.0) * 3.6 - else: - transport_demand.loc[fuel] += df.loc[key]["PJ/yr"] + if snakemake.wildcards.planning_horizons == "2020": + logger.info( + "For 2020, using hard-coded transport data from the Ariadne2-internal database." + ) - transport_demand = transport_demand.div(3.6e-6) # convert PJ to MWh + transport_demand = pd.Series() + # if 2020 + transport_demand["Electricity"] = 0.0 + 17.0 + 35.82 + 0.0 + transport_demand["Hydrogen"] = 0.0 + 0.0 + 0.0 + 0.0 + transport_demand["Liquids"] = 41.81 + 1369.34 + 11.18 + 637.23 + transport_demand = transport_demand.div(3.6e-6) # convert PJ to MWh + transport_demand["number_of_cars"] = 0.658407 - if "transport_stock" in snakemake.params.leitmodelle: - df = db.loc[snakemake.params.leitmodelle["transport_stock"]] + else: + df = db[year].loc[snakemake.params.leitmodelle["transport"]] - transport_demand["number_of_cars"] = df.loc[ - "Stock|Transportation|LDV|BEV", "million" - ] + for fuel in fuels: + for subsector in subsectors: + key = f"Final Energy|Transportation|{subsector}|{fuel}" + transport_demand.loc[fuel] += df.get((key, "TWh/yr"), 0.0) + + transport_demand = transport_demand.mul(1e6) # convert TWh to MWh + transport_demand["number_of_cars"] = df.loc[ + "Stock|Transportation|LDV|BEV", "million" + ] return transport_demand @@ -53,7 +58,7 @@ def get_transport_data(db): ll="vopt", sector_opts="none", planning_horizons="2020", - run="KN2045_Bal_v4", + run="KN2045_Mix", ) configure_logging(snakemake) @@ -66,13 +71,13 @@ def get_transport_data(db): "Deutschland", :, :, - ][snakemake.wildcards.planning_horizons] + ] logger.info( f"Retrieving German mobility demand from {snakemake.params.leitmodelle['transport']} transport model." ) # get transport_data data - transport_data = get_transport_data(db) + transport_data = get_transport_data(db, snakemake.wildcards.planning_horizons) # get German mobility weighting pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, index_col=0) diff --git a/scripts/pypsa-de/build_scenarios.py b/scripts/pypsa-de/build_scenarios.py index d0cf94615..eeaa614c7 100644 --- a/scripts/pypsa-de/build_scenarios.py +++ b/scripts/pypsa-de/build_scenarios.py @@ -15,11 +15,9 @@ def get_transport_growth(df, planning_horizons): - try: - aviation = df.loc["Final Energy|Bunkers|Aviation", "PJ/yr"] - except KeyError: - aviation = df.loc["Final Energy|Bunkers|Aviation", "TWh/yr"] * 3.6 # TWh to PJ + aviation = df.loc["Final Energy|Bunkers|Aviation", "TWh/yr"] + aviation[2020] = 111.25 # Ariadne2-internal DB, Aladin model aviation_growth_factor = aviation / aviation[2020] return aviation_growth_factor[planning_horizons] @@ -31,19 +29,12 @@ def get_primary_steel_share(df, planning_horizons): total_steel = df.loc[model, "Production|Steel"] primary_steel = df.loc[model, "Production|Steel|Primary"] + total_steel[2020] = 40.621 # Ariadne2-internal DB, FORECAST, 2021 + primary_steel[2020] = 28.53 # Ariadne2-internal DB, FORECAST, 2021 + primary_steel_share = primary_steel / total_steel primary_steel_share = primary_steel_share[planning_horizons] - if ( - model == "FORECAST v1.0" - and (planning_horizons[0] == 2020) - and snakemake.params.db_name == "ariadne2_intern" - ): - logger.warning( - "FORECAST v1.0 does not have data for 2020. Using 2021 data for Production|Steel instead." - ) - primary_steel_share[2020] = primary_steel[2021] / total_steel[2021] - return primary_steel_share.set_index(pd.Index(["Primary_Steel_Share"])) @@ -54,14 +45,10 @@ def get_DRI_share(df, planning_horizons): # Assuming that only hydrogen DRI steel is sustainable and DRI using natural gas is phased out DRI_steel = df.loc[model, "Production|Steel|Primary|Direct Reduction Hydrogen"] - DRI_steel_share = DRI_steel / total_steel - - if model == "FORECAST v1.0" and planning_horizons[0] == 2020: - logger.warning( - "FORECAST v1.0 does not have data for 2020. Using 2021 data for DRI fraction instead." - ) - DRI_steel_share[2020] = DRI_steel_share[2021] / total_steel[2021] + total_steel[2020] = 40.621 # Ariadne2-internal DB, FORECAST, 2021 + DRI_steel[2020] = 0 # Ariadne2-internal DB, FORECAST, 2021 + DRI_steel_share = DRI_steel / total_steel DRI_steel_share = DRI_steel_share[planning_horizons] return DRI_steel_share.set_index(pd.Index(["DRI_Steel_Share"])) @@ -135,6 +122,9 @@ def get_co2_budget(df, source): targets_pypsa = targets_co2 - nonco2 target_fractions_pypsa = targets_pypsa.loc[targets_co2.index] / baseline_pypsa + target_fractions_pypsa[2020] = ( + 0.671 # Hard-coded based on REMIND data from ariadne2-internal DB + ) return target_fractions_pypsa.round(3) @@ -146,9 +136,6 @@ def write_to_scenario_yaml(input, output, scenarios, df): config = yaml.load(file_path) for scenario in scenarios: reference_scenario = config[scenario]["iiasa_database"]["reference_scenario"] - # fallback_reference_scenario = config[scenario]["iiasa_database"][ - # "fallback_reference_scenario" - # ] planning_horizons = [ 2020, @@ -159,23 +146,17 @@ def write_to_scenario_yaml(input, output, scenarios, df): 2045, 2050, ] + logger.info( + "Using hard-coded values for the year 2020 for aviation demand, steel shares and non-co2 emissions. Source: Model results in the Ariadne2-internal database" + ) aviation_demand_factor = get_transport_growth( df.loc[snakemake.params.leitmodelle["transport"], reference_scenario, :], planning_horizons, ) - # if reference_scenario.startswith( - # "KN2045plus" - # ): # Still waiting for REMIND uploads - # fallback_reference_scenario = reference_scenario - co2_budget_source = config[scenario]["co2_budget_DE_source"] - # if fallback_reference_scenario != reference_scenario: - # logger.warning( - # f"For CO2 budget: Using {fallback_reference_scenario} as fallback reference scenario for {scenario}." - # ) co2_budget_fractions = get_co2_budget( df.loc[snakemake.params.leitmodelle["general"], reference_scenario], co2_budget_source, diff --git a/scripts/pypsa-de/cluster_wasserstoff_kernnetz.py b/scripts/pypsa-de/cluster_wasserstoff_kernnetz.py index 3cac0bb4d..be7b1b9af 100644 --- a/scripts/pypsa-de/cluster_wasserstoff_kernnetz.py +++ b/scripts/pypsa-de/cluster_wasserstoff_kernnetz.py @@ -189,7 +189,7 @@ def aggregate_parallel_pipes(df, aggregate_build_years="mean"): "cluster_wasserstoff_kernnetz", simpl="", clusters=27, - run="KN2045_Bal_v4", + run="KN2045_Mix", opts="", ll="vopt", sector_opts="none", diff --git a/scripts/pypsa-de/export_ariadne_variables.py b/scripts/pypsa-de/export_ariadne_variables.py index 2b73ebb40..9f0dd39e9 100644 --- a/scripts/pypsa-de/export_ariadne_variables.py +++ b/scripts/pypsa-de/export_ariadne_variables.py @@ -21,15 +21,11 @@ # Defining global variables -TWh2PJ = 3.6 -MWh2TJ = 3.6e-3 +TWh2MWh = 1e6 +MWh2TWh = 1e-6 MW2GW = 1e-3 MW2TW = 1e-6 t2Mt = 1e-6 - -MWh2GJ = 3.6 -TWh2PJ = 3.6 -MWh2PJ = 3.6e-6 toe_to_MWh = 11.630 # GWh/ktoe OR MWh/toe @@ -231,7 +227,7 @@ def _get_fuel_fractions(n, region, fuel): else: raise ValueError(f"Fuel {fuel} not supported") - fuel_fractions = fuel_fractions.divide(domestic_fuel_supply.sum()) + fuel_fractions = fuel_fractions.divide(domestic_fuel_supply.sum()).round(9) assert isclose(fuel_fractions.sum(), 1) @@ -279,7 +275,7 @@ def _get_t_sum(df, df_t, carrier, region, snapshot_weightings, port): def sum_load(n, carrier, region): - return MWh2PJ * _get_t_sum( + return _get_t_sum( n.loads, n.loads_t, carrier, @@ -1126,7 +1122,6 @@ def get_CHP_E_and_H_usage(n, bus_carrier, region, fossil_fraction=1): ) .filter(like=region) .filter(like="CHP") - .multiply(MWh2PJ) .multiply(fossil_fraction) ) @@ -1162,7 +1157,6 @@ def get_primary_energy(n, region): .groupby("carrier") .sum() .multiply(oil_fossil_fraction) - .multiply(MWh2PJ) ) oil_CHP_E_usage, oil_CHP_H_usage = get_CHP_E_and_H_usage( @@ -1192,7 +1186,6 @@ def get_primary_energy(n, region): var["Primary Energy|Oil"], n.statistics.withdrawal(bus_carrier="oil primary", **kwargs) .get(("Link", "DE oil refining"), pd.Series(0)) - .multiply(MWh2PJ) .item(), ) @@ -1211,7 +1204,6 @@ def get_primary_energy(n, region): .groupby("carrier") .sum() .multiply(gas_fractions["Natural Gas"]) - .multiply(MWh2PJ) ) primary_gas_factor = ( n.links.query("carrier=='gas compressing'").efficiency.unique().item() @@ -1241,12 +1233,20 @@ def get_primary_energy(n, region): var["Primary Energy|Gas"] = gas_usage.sum() / primary_gas_factor + _gas_primary = ( + n.statistics.withdrawal( + bus_carrier="gas primary", + **kwargs, + ) + .get(("Link", "DE gas compressing"), pd.Series(0)) + .round() + .item() + ) + assert isclose( var["Primary Energy|Gas"], - n.statistics.withdrawal(bus_carrier="gas primary", **kwargs) - .get(("Link", "DE gas compressing"), pd.Series(0)) - .multiply(MWh2PJ) - .item(), + _gas_primary, + atol=1e-1, ) var["Primary Energy|Gas|Gases"] = ( @@ -1274,7 +1274,6 @@ def get_primary_energy(n, region): .filter(like=region) .groupby("carrier") .sum() - .multiply(MWh2PJ) ) coal_CHP_E_usage, coal_CHP_H_usage = get_CHP_E_and_H_usage(n, "coal", region) @@ -1322,7 +1321,6 @@ def get_primary_energy(n, region): .drop("Store", errors="ignore") .groupby("carrier") .sum() - .multiply(MWh2PJ) ) biomass_CHP_E_usage, biomass_CHP_H_usage = get_CHP_E_and_H_usage( @@ -1345,7 +1343,6 @@ def get_primary_energy(n, region): .filter(like=region) .groupby("carrier") .sum() - .multiply(MWh2PJ) .get("unsustainable bioliquids", 0) ) @@ -1396,7 +1393,6 @@ def get_primary_energy(n, region): .filter(like=region) .groupby("carrier") .sum() - .multiply(MWh2PJ) .get("nuclear", 0) ) @@ -1417,7 +1413,6 @@ def get_primary_energy(n, region): .filter(like=region) .groupby("carrier") .sum() - .multiply(MWh2PJ) ) solar_thermal_heat = ( @@ -1433,7 +1428,6 @@ def get_primary_energy(n, region): .groupby("carrier") .sum() .filter(like="solar thermal") - .multiply(MWh2PJ) .sum() ) @@ -1472,7 +1466,7 @@ def get_primary_energy(n, region): + var["Primary Energy|Waste"] ) - return var + return var * MWh2TWh def get_secondary_energy(n, region, _industry_demand): @@ -1487,7 +1481,6 @@ def get_secondary_energy(n, region, _industry_demand): .filter(like=region) .groupby(["carrier"]) .sum() - .multiply(MWh2PJ) .drop( ["AC", "DC", "electricity distribution grid"], errors="ignore", @@ -1591,7 +1584,6 @@ def get_secondary_energy(n, region, _industry_demand): var["Secondary Energy|Electricity|Curtailment"] = ( n.statistics.curtailment(bus_carrier=["AC", "low voltage"], **kwargs) .filter(like=region) - .multiply(MWh2PJ) .values.sum() ) @@ -1616,9 +1608,7 @@ def get_secondary_energy(n, region, _industry_demand): "home battery discharger", "PHS", ] - ) - .multiply(MWh2PJ) - .sum() + ).sum() ) # TODO Compute transmission losses via links_t @@ -1633,7 +1623,7 @@ def get_secondary_energy(n, region, _industry_demand): # ).filter(like=region).groupby(["carrier"]).sum().get( # ["AC", "DC", "electricity distribution grid"] # ) - # ).multiply(MWh2PJ).sum() + # ).sum() # supply - withdrawal # var["Secondary Energy|Electricity|Storage"] = \ @@ -1668,7 +1658,6 @@ def get_secondary_energy(n, region, _industry_demand): .filter(like=region) .groupby(["carrier"]) .sum() - .multiply(MWh2PJ) ) var["Secondary Energy|Heat|Gas"] = heat_supply.filter(like="gas").sum() @@ -1736,7 +1725,6 @@ def get_secondary_energy(n, region, _industry_demand): .drop("Store", errors="ignore") .groupby(["carrier"]) .sum() - .multiply(MWh2PJ) ) var["Secondary Energy|Hydrogen|Electricity"] = hydrogen_production.get( @@ -1770,7 +1758,6 @@ def get_secondary_energy(n, region, _industry_demand): liquids_production = ( n.statistics.supply(bus_carrier=["oil", "renewable oil", "methanol"], **kwargs) .filter(like=region) - .multiply(MWh2PJ) .drop( [("Store", "DE oil Store"), ("Store", "DE methanol Store")], errors="ignore" ) @@ -1809,7 +1796,6 @@ def get_secondary_energy(n, region, _industry_demand): .groupby(["carrier"]) .sum() .drop(["renewable gas"], errors="ignore") - .multiply(MWh2PJ) ) # Fraction supplied by Hydrogen conversion @@ -1842,7 +1828,6 @@ def get_secondary_energy(n, region, _industry_demand): .filter(like=region) .groupby(["carrier"]) .sum() - .multiply(MWh2PJ) ) var["Secondary Energy|Solids|Biomass"] = ( @@ -1856,7 +1841,6 @@ def get_secondary_energy(n, region, _industry_demand): .filter(like=region) .groupby(["carrier"]) .sum() - .multiply(MWh2PJ) ) var["Secondary Energy Input|Electricity|Hydrogen"] = electricity_withdrawal.get( @@ -1876,7 +1860,6 @@ def get_secondary_energy(n, region, _industry_demand): .filter(like=region) .groupby(["carrier"]) .sum() - .multiply(MWh2PJ) ) H2_CHP_E_usage, H2_CHP_H_usage = get_CHP_E_and_H_usage(n, "H2", region) @@ -1913,7 +1896,7 @@ def get_secondary_energy(n, region, _industry_demand): + var["Secondary Energy|Solids"] ) - return var + return var * MWh2TWh def get_final_energy( @@ -1941,13 +1924,11 @@ def get_final_energy( * h2_fossil_fraction * config_industry["MWh_CH4_per_tNH3_SMR"] / config_industry["MWh_NH3_per_tNH3"] - * MWh2PJ ) H2_for_NH3 = ( Haber_Bosch_NH3 * (1 - h2_fossil_fraction) / config_industry["MWh_H2_per_tNH3_electrolysis"] - * MWh2PJ ) subcategories = ["HVC", "Methanol", "Chlorine"] @@ -1960,7 +1941,7 @@ def get_final_energy( ip = _industry_production.loc[region, subcategories] # kt/a sr = _sector_ratios["DE"].loc[carrier, subcategories] # MWh/tMaterial - non_energy = sr.multiply(ip).sum(axis=1) * 1e3 * MWh2PJ + non_energy = sr.multiply(ip).sum(axis=1) * 1e3 # write var var["Final Energy|Non-Energy Use|Gases"] = non_energy.methane + CH4_for_NH3 @@ -2167,7 +2148,6 @@ def get_final_energy( ) .groupby("carrier") .sum() - .multiply(MWh2PJ) ) rescom_electricity = low_voltage_electricity[ @@ -2202,7 +2182,6 @@ def get_final_energy( ], errors="ignore", ) - .multiply(MWh2PJ) ) decentral_heat_residential_and_commercial_fraction = ( @@ -2220,7 +2199,6 @@ def get_final_energy( ) .groupby("carrier") .sum() - .multiply(MWh2PJ) .multiply(decentral_heat_residential_and_commercial_fraction) ) # Dischargers probably should not be considered, to avoid double counting @@ -2237,7 +2215,6 @@ def get_final_energy( .filter(like=region) .groupby(["carrier"]) .sum() - .multiply(MWh2PJ) ) # !!! Here the final is delivered as gas, not as heat @@ -2258,7 +2235,6 @@ def get_final_energy( .filter(like=region) .groupby(["carrier"]) .sum() - .multiply(MWh2PJ) ) var["Final Energy|Residential and Commercial|Liquids"] = oil_usage.get( @@ -2285,7 +2261,6 @@ def get_final_energy( .filter(like=region) .groupby(["carrier"]) .sum() - .multiply(MWh2PJ) ) var["Final Energy|Residential and Commercial|Solids"] = var[ @@ -2468,7 +2443,6 @@ def get_final_energy( ) .groupby("carrier") .sum() - .multiply(MWh2PJ) ) var["Final Energy|Carbon Dioxide Removal|Heat"] = decentral_heat_withdrawal.get( @@ -2485,7 +2459,6 @@ def get_final_energy( ) .groupby("carrier") .sum() - .multiply(MWh2PJ) ) var["Final Energy|Carbon Dioxide Removal|Electricity"] = electricity.get("DAC", 0) @@ -2571,7 +2544,6 @@ def get_final_energy( ) .groupby("carrier") .sum() - .multiply(MWh2PJ) ) var["Final Energy|Waste"] = waste_withdrawal.get("HVC to air", 0) @@ -2595,7 +2567,7 @@ def get_final_energy( + var["Final Energy|Carbon Dioxide Removal"] ) - return var + return var * MWh2TWh def get_emissions(n, region, _energy_totals, industry_demand): @@ -2907,10 +2879,8 @@ def get_emissions(n, region, _energy_totals, industry_demand): ) # considered 0 anyways mwh_coal_per_mwh_coke = 1.366 # from eurostat energy balance - # 0.3361 t/MWh, industry_DE is in PJ, 1e-6 to convert to Mt - coking_emissions = ( - industry_DE.coke / MWh2PJ * (mwh_coal_per_mwh_coke - 1) * 0.3361 * t2Mt - ) + # 0.3361 t/MWh, 1e-6 to convert to Mt + coking_emissions = industry_DE.coke * (mwh_coal_per_mwh_coke - 1) * 0.3361 * t2Mt var["Emissions|Gross Fossil CO2|Energy|Demand|Industry"] = ( co2_emissions.reindex( [ @@ -3387,9 +3357,7 @@ def get_prices(n, region): # Price|Primary Energy|Biomass var["Price|Primary Energy|Biomass"] = ( - nodal_flows_bm.mul(nodal_prices_bm).values.sum() - / nodal_flows_bm.values.sum() - / MWh2GJ + nodal_flows_bm.mul(nodal_prices_bm).values.sum() / nodal_flows_bm.values.sum() ) # Price|Primary Energy|Coal @@ -3425,7 +3393,7 @@ def get_prices(n, region): [coal_price, lignite_price], [nf_coal.values.sum(), nf_lignite.values.sum()] ) + co2_add_coal - ) / MWh2GJ + ) # Price|Primary Energy|Gas nodal_flows_gas = get_nodal_flows(n, "gas", region) @@ -3438,7 +3406,7 @@ def get_prices(n, region): nodal_flows_gas.mul(nodal_prices_gas).values.sum() / nodal_flows_gas.values.sum() + co2_cost_gas - ) / MWh2GJ + ) # Price|Primary Energy|Oil nodal_flows_oil = get_nodal_flows(n, "oil primary", region) @@ -3451,7 +3419,7 @@ def get_prices(n, region): nodal_flows_oil.mul(nodal_prices_oil).values.sum() / nodal_flows_oil.values.sum() + co2_cost_oil - ) / MWh2GJ + ) # Price|Secondary Energy # reported: 8/14 @@ -3463,25 +3431,22 @@ def get_prices(n, region): nodal_prices_ac = n.buses_t.marginal_price[nodal_flows_ac.columns] var["Price|Secondary Energy|Electricity"] = ( - nodal_flows_ac.mul(nodal_prices_ac).values.sum() - / nodal_flows_ac.values.sum() - / MWh2GJ + nodal_flows_ac.mul(nodal_prices_ac).values.sum() / nodal_flows_ac.values.sum() ) # Price|Secondary Energy|Gases|Natural Gas var["Price|Secondary Energy|Gases|Natural Gas"] = ( costs_gen_generators(n, region, "gas")[0] + co2_cost_gas - ) / MWh2GJ + ) # Price|Secondary Energy|Gases|Hydrogen - var["Price|Secondary Energy|Gases|Hydrogen"] = ( - costs_gen_links(n, region, "Sabatier")[0] / MWh2GJ - ) + var["Price|Secondary Energy|Gases|Hydrogen"] = costs_gen_links( + n, region, "Sabatier" + )[0] # Price|Secondary Energy|Gases|Biomass - var["Price|Secondary Energy|Gases|Biomass"] = ( - get_weighted_costs_links(["biogas to gas", "biogas to gas CC"], n, region) - / MWh2GJ + var["Price|Secondary Energy|Gases|Biomass"] = get_weighted_costs_links( + ["biogas to gas", "biogas to gas CC"], n, region ) # Price|Secondary Energy|Gases|Efuel @@ -3504,7 +3469,6 @@ def get_prices(n, region): var["Price|Secondary Energy|Gases"] = ( nodal_flows_gas.mul(nodal_prices_gas).values.sum() / nodal_flows_gas.values.sum() - / MWh2GJ ) # Price|Secondary Energy|Hydrogen @@ -3514,18 +3478,18 @@ def get_prices(n, region): # var["Price|Secondary Energy|Hydrogen"] = ( # nodal_flows_h2.mul(nodal_prices_h2).values.sum() / nodal_flows_h2.values.sum() - # ) / MWh2GJ + # ) carriers = ["SMR", "SMR CC", "H2 Electrolysis"] - var["Price|Secondary Energy|Hydrogen"] = ( - get_weighted_costs_links(carriers, n, region) / MWh2GJ + var["Price|Secondary Energy|Hydrogen"] = get_weighted_costs_links( + carriers, n, region ) # Price|Secondary Energy|Hydrogen|Green # incorporate CAPEX and electricity price as electrolysis is forced in in some years - var["Price|Secondary Energy|Hydrogen|Green"] = ( - costs_gen_links(n, region, "H2 Electrolysis")[0] / MWh2GJ - ) + var["Price|Secondary Energy|Hydrogen|Green"] = costs_gen_links( + n, region, "H2 Electrolysis" + )[0] # Price|Secondary Energy|Liquids nodal_flows_oil = get_nodal_flows( @@ -3543,15 +3507,14 @@ def get_prices(n, region): var["Price|Secondary Energy|Liquids"] = ( nodal_flows_oil.mul(nodal_prices_oil).values.sum() / nodal_flows_oil.values.sum() - / MWh2GJ ) # Price|Secondary Energy|Liquids|Biomass # Price|Secondary Energy|Liquids|Oil # Price|Secondary Energy|Liquids|Hydrogen carriers = ["Fischer-Tropsch", "methanol"] - var["Price|Secondary Energy|Liquids|Hydrogen"] = ( - get_weighted_costs_links(carriers, n, region) / MWh2GJ + var["Price|Secondary Energy|Liquids|Hydrogen"] = get_weighted_costs_links( + carriers, n, region ) # Price|Secondary Energy|Liquids|Efuel @@ -3567,9 +3530,9 @@ def get_prices(n, region): # Price|Final Energy|Transportation|Freight|Electricity x # Price|Final Energy|Transportation|Freight|Gases # Price|Final Energy|Transportation|Freight|Hydrogen - var["Price|Final Energy|Transportation|Freight|Hydrogen"] = ( - price_load(n, "land transport fuel cell", region)[0] / MWh2GJ - ) + var["Price|Final Energy|Transportation|Freight|Hydrogen"] = price_load( + n, "land transport fuel cell", region + )[0] # Price|Final Energy|Transportation|Freight|Liquids carriers = [ "kerosene for aviation", @@ -3579,25 +3542,25 @@ def get_prices(n, region): ] df = pd.DataFrame({c: price_load(n, c, region) for c in carriers}) var["Price|Final Energy|Transportation|Freight|Liquids"] = ( - (df.iloc[0] * df.iloc[1]).sum() / df.iloc[1].sum() / MWh2GJ - ) + df.iloc[0] * df.iloc[1] + ).sum() / df.iloc[1].sum() # Price|Final Energy|Transportation|Freight|Solids x # Price|Final Energy|Transportation|Passenger|Electricity - var["Price|Final Energy|Transportation|Passenger|Electricity"] = ( - price_load(n, "land transport EV", region)[0] / MWh2GJ - ) + var["Price|Final Energy|Transportation|Passenger|Electricity"] = price_load( + n, "land transport EV", region + )[0] # Price|Final Energy|Transportation|Passenger|Gases # Price|Final Energy|Transportation|Passenger|Hydrogen - var["Price|Final Energy|Transportation|Passenger|Hydrogen"] = ( - price_load(n, "land transport fuel cell", region)[0] / MWh2GJ - ) + var["Price|Final Energy|Transportation|Passenger|Hydrogen"] = price_load( + n, "land transport fuel cell", region + )[0] # Price|Final Energy|Transportation|Passenger|Liquids carriers = ["kerosene for aviation", "land transport oil"] df = pd.DataFrame({c: price_load(n, c, region) for c in carriers}) var["Price|Final Energy|Transportation|Passenger|Liquids"] = ( - (df.iloc[0] * df.iloc[1]).sum() / df.iloc[1].sum() / MWh2GJ - ) + df.iloc[0] * df.iloc[1] + ).sum() / df.iloc[1].sum() # Price|Final Energy|Transportation|Passenger|Solids x # Price|Final Energy|Transportation|Liquids|Petroleum @@ -3645,17 +3608,17 @@ def get_prices(n, region): # Price|Final Energy|Transportation|Hydrogen|Other Taxes # Price|Final Energy|Transportation|Electricity - var["Price|Final Energy|Transportation|Electricity"] = ( - price_load(n, "land transport EV", region)[0] / MWh2GJ - ) + var["Price|Final Energy|Transportation|Electricity"] = price_load( + n, "land transport EV", region + )[0] # Price|Final Energy|Transportation|Electricity|Sales Margin # Price|Final Energy|Transportation|Electricity|Transport and Distribution # Price|Final Energy|Transportation|Electricity|Other Taxes # Price|Final Energy|Transportation|Liquids|Kerosene - var["Price|Final Energy|Transportation|Electricity"] = ( - price_load(n, "kerosene for aviation", region)[0] / MWh2GJ - ) + var["Price|Final Energy|Transportation|Electricity"] = price_load( + n, "kerosene for aviation", region + )[0] # Price|Final Energy|Transportation|Liquids|Kerosene|Sales Margin # Price|Final Energy|Transportation|Liquids|Kerosene|Transport and Distribution # Price|Final Energy|Transportation|Liquids|Kerosene|Carbon Price Component @@ -3684,7 +3647,7 @@ def get_prices(n, region): # Price|Final Energy|Residential and Commercial|Liquids|Oil carriers = ["rural oil boiler", "urban decentral oil boiler"] var["Price|Final Energy|Residential and Commercial|Liquids|Oil"] = ( - get_weighted_costs_links(carriers, n, region) / MWh2GJ + get_weighted_costs_links(carriers, n, region) ) # Price|Final Energy|Residential and Commercial|Liquids|Oil|Sales Margin # Price|Final Energy|Residential and Commercial|Liquids|Oil|Transport and Distribution @@ -3703,7 +3666,7 @@ def get_prices(n, region): "rural gas boiler", ] var["Price|Final Energy|Residential and Commercial|Gases"] = ( - get_weighted_costs_links(carriers, n, region) / MWh2GJ + get_weighted_costs_links(carriers, n, region) ) # Price|Final Energy|Residential and Commercial|Gases|Natural Gas # Price|Final Energy|Residential and Commercial|Gases|Natural Gas|Sales Margin @@ -3722,7 +3685,7 @@ def get_prices(n, region): ) np_rc_heat = n.buses_t.marginal_price[nf_rc_heat.columns] var["Price|Final Energy|Residential and Commercial|Heat"] = ( - nf_rc_heat.mul(np_rc_heat).values.sum() / nf_rc_heat.values.sum() / MWh2GJ + nf_rc_heat.mul(np_rc_heat).values.sum() / nf_rc_heat.values.sum() ) # Price|Final Energy|Residential and Commercial|Heat|Sales Margin # Price|Final Energy|Residential and Commercial|Heat|Transport and Distribution @@ -3736,7 +3699,7 @@ def get_prices(n, region): # Price|Final Energy|Residential and Commercial|Solids carriers = "rural biomass boiler", "urban decentral biomass boiler" var["Price|Final Energy|Residential and Commercial|Solids|Biomass"] = ( - get_weighted_costs_links(carriers, n, region) / MWh2GJ + get_weighted_costs_links(carriers, n, region) ) var["Price|Final Energy|Residential and Commercial|Solids"] = var[ "Price|Final Energy|Residential and Commercial|Solids|Biomass" @@ -3776,9 +3739,7 @@ def get_prices(n, region): ) nodal_prices_lv = n.buses_t.marginal_price[nodal_flows_lv.columns] var["Price|Final Energy|Residential and Commercial|Electricity"] = ( - nodal_flows_lv.mul(nodal_prices_lv).values.sum() - / nodal_flows_lv.values.sum() - / MWh2GJ + nodal_flows_lv.mul(nodal_prices_lv).values.sum() / nodal_flows_lv.values.sum() ) # Price|Final Energy|Residential and Commercial|Electricity|Sales Margin x # Price|Final Energy|Residential and Commercial|Electricity|Transport and Distribution @@ -3798,17 +3759,17 @@ def get_prices(n, region): ### Price|Final Energy|Industry| # Price|Final Energy|Industry|Liquids|Oil - var["Price|Final Energy|Industry|Liquids|Oil"] = ( - get_weighted_costs_links(["naphtha for industry"], n, region) / MWh2GJ + var["Price|Final Energy|Industry|Liquids|Oil"] = get_weighted_costs_links( + ["naphtha for industry"], n, region ) # Price|Final Energy|Industry|Liquids|Oil|Sales Margin # Price|Final Energy|Industry|Liquids|Oil|Transport and Distribution # Price|Final Energy|Industry|Liquids|Oil|Carbon Price Component # Price|Final Energy|Industry|Liquids|Oil|Other Taxes - var["Price|Final Energy|Industry|Solids|Coal"] = ( - price_load(n, "coal for industry", region)[0] / MWh2GJ - ) + var["Price|Final Energy|Industry|Solids|Coal"] = price_load( + n, "coal for industry", region + )[0] # Price|Final Energy|Industry|Solids|Coal|Sales Margin x # Price|Final Energy|Industry|Solids|Coal|Transport and Distribution # Price|Final Energy|Industry|Solids|Coal|Carbon Price Component @@ -3837,7 +3798,7 @@ def get_prices(n, region): var["Price|Final Energy|Industry|Solids|Biomass"] = price_load( n, "solid biomass for industry", region - )[0] / (MWh2GJ) + )[0] # Price|Final Energy|Industry|Solids|Biomass|Sales Margin x # Price|Final Energy|Industry|Solids|Biomass|Transport and Distribution # Price|Final Energy|Industry|Solids|Biomass|Other Taxes @@ -3847,9 +3808,9 @@ def get_prices(n, region): # Price|Final Energy|Industry|Gases|Biomass|Transport and Distribution # Price|Final Energy|Industry|Gases|Biomass|Other Taxes - var["Price|Final Energy|Industry|Liquids|Efuel"] = ( - price_load(n, "naphtha for industry", region)[0] / MWh2GJ - ) + var["Price|Final Energy|Industry|Liquids|Efuel"] = price_load( + n, "naphtha for industry", region + )[0] # Price|Final Energy|Industry|Liquids|Efuel|Sales Margin x # Price|Final Energy|Industry|Liquids|Efuel|Transport and Distribution @@ -3876,38 +3837,37 @@ def get_prices(n, region): # Price|Final Energy|Industry|Electricity var["Price|Final Energy|Industry|Electricity"] = price_load( n, "industry electricity", region - )[0] / (MWh2GJ) + )[0] # Price|Final Energy|Industry|Electricity|Sales Margin # Price|Final Energy|Industry|Electricity|Transport and Distribution # Price|Final Energy|Industry|Electricity|Other Taxes # Price|Final Energy|Industry|Gases - var["Price|Final Energy|Industry|Gases"] = ( - get_weighted_costs_links(["gas for industry", "gas for industry CC"], n, region) - / MWh2GJ + var["Price|Final Energy|Industry|Gases"] = get_weighted_costs_links( + ["gas for industry", "gas for industry CC"], n, region ) # Price|Final Energy|Industry|Heat - var["Price|Final Energy|Industry|Heat"] = ( - price_load(n, "low-temperature heat for industry", region)[0] / MWh2GJ - ) + var["Price|Final Energy|Industry|Heat"] = price_load( + n, "low-temperature heat for industry", region + )[0] # Price|Final Energy|Industry|Liquids carriers = ["naphtha for industry", "industry methanol"] df = pd.DataFrame({c: price_load(n, c, region) for c in carriers}) var["Price|Final Energy|Industry|Liquids"] = ( - (df.iloc[0] * df.iloc[1]).sum() / df.iloc[1].sum() / MWh2GJ - ) + df.iloc[0] * df.iloc[1] + ).sum() / df.iloc[1].sum() # Price|Final Energy|Industry|Hydrogen - var["Price|Final Energy|Industry|Hydrogen"] = ( - price_load(n, "H2 for industry", region)[0] / MWh2GJ - ) + var["Price|Final Energy|Industry|Hydrogen"] = price_load( + n, "H2 for industry", region + )[0] # Price|Final Energy|Industry|Solids carriers = [ "solid biomass for industry", "solid biomass for industry CC", "coal for industry", ] - var["Price|Final Energy|Industry|Solids"] = ( - get_weighted_costs_links(carriers, n, region) / MWh2GJ + var["Price|Final Energy|Industry|Solids"] = get_weighted_costs_links( + carriers, n, region ) return var @@ -3949,7 +3909,7 @@ def get_grid_investments( .p_nom ) common_index = offwind.index.intersection(offwind2020.index) - offwind_capacity[common_index] -= offwind2020[common_index] + offwind_capacity.loc[common_index] -= offwind2020.loc[common_index] offwind_connection_overnight_cost = ( offwind_capacity * offwind.connection_overnight_cost ) * 1e-9 @@ -4441,21 +4401,21 @@ def get_export_import_links(n, region, carriers): exports_dc, imports_dc = get_export_import_links(n, region, ["DC"]) var["Trade|Secondary Energy|Electricity|Volume"] = ( - (exporting_p_ac - importing_p_ac) + (exports_dc - imports_dc) - ) * MWh2PJ + exporting_p_ac - importing_p_ac + ) + (exports_dc - imports_dc) var["Trade|Secondary Energy|Electricity|Gross Import|Volume"] = ( importing_p_ac + imports_dc - ) * MWh2PJ + ) # var["Trade|Secondary Energy|Electricity|Volume|Exports"] = \ - # (exporting_p_ac + exports_dc) * MWh2PJ + # (exporting_p_ac + exports_dc) # Trade|Secondary Energy|Hydrogen|Volume h2_carriers = ["H2 pipeline", "H2 pipeline (Kernnetz)", "H2 pipeline retrofitted"] exports_h2, imports_h2 = get_export_import_links(n, region, h2_carriers) - var["Trade|Secondary Energy|Hydrogen|Volume"] = (exports_h2 - imports_h2) * MWh2PJ - var["Trade|Secondary Energy|Hydrogen|Gross Import|Volume"] = imports_h2 * MWh2PJ + var["Trade|Secondary Energy|Hydrogen|Volume"] = exports_h2 - imports_h2 + var["Trade|Secondary Energy|Hydrogen|Gross Import|Volume"] = imports_h2 # var["Trade|Secondary Energy|Hydrogen|Volume|Exports"] = \ - # exports_h2 * MWh2PJ + # exports_h2 # Trade|Secondary Energy|Liquids|Hydrogen|Volume @@ -4490,10 +4450,10 @@ def get_export_import_links(n, region, carriers): var["Trade|Secondary Energy|Liquids|Biomass|Volume"] = ( exports_oil_renew * DE_bio_fraction - imports_oil_renew * EU_bio_fraction - ) * MWh2PJ + ) var["Trade|Secondary Energy|Liquids|Biomass|Gross Import|Volume"] = ( - imports_oil_renew * EU_bio_fraction * MWh2PJ + imports_oil_renew * EU_bio_fraction ) exports_meoh, imports_meoh = get_export_import_links(n, region, ["methanol"]) @@ -4503,17 +4463,15 @@ def get_export_import_links(n, region, carriers): - imports_oil_renew * (1 - EU_bio_fraction) + exports_meoh - imports_meoh - ) * MWh2PJ + ) var["Trade|Secondary Energy|Liquids|Hydrogen|Gross Import|Volume"] = ( imports_oil_renew * (1 - EU_bio_fraction) + imports_meoh - ) * MWh2PJ + ) - var["Trade|Secondary Energy|Methanol|Volume"] = ( - exports_meoh - imports_meoh - ) * MWh2PJ + var["Trade|Secondary Energy|Methanol|Volume"] = exports_meoh - imports_meoh - var["Trade|Secondary Energy|Methanol|Gross Import|Volume"] = imports_meoh * MWh2PJ + var["Trade|Secondary Energy|Methanol|Gross Import|Volume"] = imports_meoh # Trade|Secondary Energy|Gases|Hydrogen|Volume @@ -4545,19 +4503,18 @@ def get_export_import_links(n, region, carriers): exports_gas_renew, imports_gas_renew = get_export_import_links( n, region, ["renewable gas"] ) - var["Trade|Secondary Energy|Gases|Hydrogen|Volume"] = ( - exports_gas_renew * (1 - DE_bio_fraction) - - imports_gas_renew * (1 - EU_bio_fraction) - ) * MWh2PJ + var["Trade|Secondary Energy|Gases|Hydrogen|Volume"] = exports_gas_renew * ( + 1 - DE_bio_fraction + ) - imports_gas_renew * (1 - EU_bio_fraction) var["Trade|Secondary Energy|Gases|Hydrogen|Gross Import|Volume"] = ( - imports_gas_renew * (1 - EU_bio_fraction) * MWh2PJ + imports_gas_renew * (1 - EU_bio_fraction) ) var["Trade|Secondary Energy|Gases|Biomass|Volume"] = ( exports_gas_renew * DE_bio_fraction - imports_gas_renew * EU_bio_fraction - ) * MWh2PJ + ) var["Trade|Secondary Energy|Gases|Biomass|Gross Import|Volume"] = ( - imports_gas_renew * EU_bio_fraction * MWh2PJ + imports_gas_renew * EU_bio_fraction ) # Trade|Primary Energy|Coal|Volume @@ -4570,13 +4527,13 @@ def get_export_import_links(n, region, carriers): n, region, ["gas pipeline", "gas pipeline new"] ) var["Trade|Primary Energy|Gas|Volume"] = ( - (exports_gas - imports_gas) * MWh2PJ + exports_gas - imports_gas ) * gas_fractions["Natural Gas"] var["Trade|Primary Energy|Gas|Volume|Imports"] = ( - imports_gas * MWh2PJ * gas_fractions["Natural Gas"] + imports_gas * gas_fractions["Natural Gas"] ) var["Trade|Primary Energy|Gas|Volume|Exports"] = ( - exports_gas * MWh2PJ * gas_fractions["Natural Gas"] + exports_gas * gas_fractions["Natural Gas"] ) # Trade|Primary Energy|Oil|Volume @@ -4613,7 +4570,7 @@ def get_export_import_links(n, region, carriers): biomass_net_exports = ( biomass_potential_DE - biomass_usage_local - biomass_usage_transported - ) * MWh2PJ + ) var["Trade|Primary Energy|Biomass|Volume"] = biomass_net_exports logger.info( @@ -4624,7 +4581,7 @@ def get_export_import_links(n, region, carriers): }""" ) - return var + return var * MWh2TWh def get_production(region, year): @@ -4660,219 +4617,6 @@ def get_production(region, year): return var -def get_operational_and_capital_costs(year): - """ - ' This function reads in the cost data from the costs.csv file and brings - it into the database format. - """ - var = pd.Series() - ind = planning_horizons.index(year) - costs = load_costs( - snakemake.input.costs[ind], - snakemake.params.costs, - snakemake.params.max_hours, - nyears=1, - ) - - costs_dict = { - # capacities electricity - "BEV charger": None, - "CCGT": "CCGT", - "DAC": "direct air capture", - "H2 Electrolysis": "electrolysis", - "H2 Fuel Cell": "fuel cell", - "OCGT": "OCGT", - "PHS": "PHS", - "V2G": None, - "battery charger": "battery inverter", - "battery discharger": "battery inverter", - "coal": "coal", - "gas pipeline": "CH4 (g) pipeline", - "home battery charger": "home battery inverter", - "home battery discharger": "home battery inverter", - "hydro": "hydro", - "lignite": "lignite", - "methanolisation": "methanolisation", - "offwind-ac": "offwind", # TODO add grid connection cost - "offwind-dc": "offwind", # TODO add grid connection cost - "offwind-float": "offwind-float", # TODO add grid connection cost - "oil": "oil", - "onwind": "onwind", - "ror": "ror", - "rural air heat pump": "decentral air-sourced heat pump", - "rural ground heat pump": "decentral ground-sourced heat pump", - "rural resistive heater": "decentral resistive heater", - "rural solar thermal": "decentral solar thermal", - "solar": "solar-utility", - "solar rooftop": "solar-rooftop", - "solar-hsat": "solar-utility single-axis tracking", - "solid biomass": "central solid biomass CHP", - "urban central air heat pump": "central air-sourced heat pump", - "urban central coal CHP": "central coal CHP", - "urban central gas CHP": "central gas CHP", - "urban central gas CHP CC": "central gas CHP", - "urban central lignite CHP": "central coal CHP", - "urban central oil CHP": "central gas CHP", - "urban central resistive heater": "central resistive heater", - "urban central solar thermal": "central solar thermal", - "urban central solid biomass CHP": "central solid biomass CHP", - "urban central solid biomass CHP CC": "central solid biomass CHP CC", - "urban decentral air heat pump": "decentral air-sourced heat pump", - "urban decentral resistive heater": "decentral resistive heater", - "urban decentral solar thermal": "decentral solar thermal", - "waste CHP": "waste CHP", - "waste CHP CC": "waste CHP CC", - # Heat capacities - # TODO Check the units of the investments - "Fischer-Tropsch": None, #'Fischer-Tropsch' * "efficiency" , - "Sabatier": "methanation", - # 'urban central air heat pump': 'central air-sourced heat pump', - # 'urban central coal CHP': 'central coal CHP', - # 'urban central gas CHP': 'central gas CHP', - # 'urban central gas CHP CC': 'central gas CHP', - # 'urban central lignite CHP': 'central coal CHP', - # 'urban central oil CHP': 'central gas CHP', - # 'urban central resistive heater': 'central resistive heater', - # 'urban central solid biomass CHP': 'central solid biomass CHP', - # 'urban central solid biomass CHP CC': 'central solid biomass CHP CC', - "urban central water tanks charger": "water tank charger", - "urban central water tanks discharger": "water tank discharger", - # 'waste CHP': 'waste CHP', - # 'waste CHP CC': 'waste CHP CC', - # Decentral Heat capacities - # TODO consider overdim_factor - #'rural air heat pump': None, - "rural biomass boiler": "biomass boiler", - "rural gas boiler": "decentral gas boiler", - #'rural ground heat pump': None, - "rural oil boiler": "decentral oil boiler", - "rural water tanks charger": "water tank charger", - "rural water tanks discharger": "water tank discharger", - #'urban decentral air heat pump': None, - "urban decentral biomass boiler": "biomass boiler", - "urban decentral gas boiler": "decentral gas boiler", - "urban decentral oil boiler": "decentral oil boiler", - "urban decentral water tanks charger": "water tank charger", - "urban decentral water tanks discharger": "water tank discharger", - # Other capacities - # 'Sabatier': 'methanation',costs.at["methanation", "capital_cost"] - # * costs.at["methanation", "efficiency"] - "biogas to gas": None, # TODO biogas + biogas upgrading - "biogas to gas CC": None, # TODO costs.at["biogas CC", "capital_cost"] - # + costs.at["biogas upgrading", "capital_cost"] - # + costs.at["biomass CHP capture", "capital_cost"] - # * costs.at["biogas CC", "CO2 stored"], - } - - # storage_costs_dict = { - # "H2": "hydrogen storage underground", - # "EV battery": None, # 0 i think - # "PHS": None, #'PHS', accounted already as generator?? - # "battery": "battery storage", - # "biogas": None, # not a typical store, 0 i think - # "co2 sequestered": snakemake.params.co2_sequestration_cost, - # "co2 stored": "CO2 storage tank", - # "gas": "gas storage", - # "home battery": "home battery storage", - # "hydro": None, # `hydro`, , accounted already as generator?? - # "oil": 0.02, - # "rural water tanks": "decentral water tank storage", - # "solid biomass": None, # not a store, but a potential, 0 i think - # "urban central water tanks": "central water tank storage", - # "urban decentral water tanks": "decentral water tank storage", - # } - - sector_dict = { - "BEV charger": "Electricity", - "CCGT": "Electricity", - "DAC": "Gases", - "H2 Electrolysis": "Hydrogen", - "H2 Fuel Cell": "Electricity", - "OCGT": "Electricity", - "PHS": "Electricity", - "V2G": "Electricity", - "battery charger": "Electricity", - "battery discharger": "Electricity", - "coal": "Electricity", - "Fischer-Tropsch": "Liquids", - "gas pipeline": "Gases", - "home battery charger": "Electricity", - "home battery discharger": "Electricity", - "hydro": "Electricity", - "lignite": "Electricity", - "methanolisation": "Liquids", - "offwind-ac": "Electricity", - "offwind-dc": "Electricity", - "offwind-float": "Electricity", - "oil": "Electricity", - "onwind": "Electricity", - "ror": "Electricity", - "rural air heat pump": "Heat", - "rural biomass boiler": "Heat", - "rural gas boiler": "Heat", - "rural oil boiler": "Heat", - "rural ground heat pump": "Heat", - "rural resistive heater": "Heat", - "rural solar thermal": "Heat", - "rural water tanks charger": "Heat", - "rural water tanks discharger": "Heat", - "Sabatier": "Gases", - "solar": "Electricity", - "solar rooftop": "Electricity", - "solar-hsat": "Electricity", - "solid biomass": "Heat", - "urban central air heat pump": "Heat", - "urban central coal CHP": "Heat", - "urban central gas CHP": "Heat", - "urban central gas CHP CC": "Heat", - "urban central lignite CHP": "Heat", - "urban central oil CHP": "Heat", - "urban central water tanks charger": "Heat", - "urban central water tanks discharger": "Heat", - "urban central resistive heater": "Heat", - "urban central solar thermal": "Heat", - "urban central solid biomass CHP": "Heat", - "urban central solid biomass CHP CC": "Heat", - "urban decentral air heat pump": "Heat", - "urban decentral resistive heater": "Heat", - "urban decentral solar thermal": "Heat", - "urban decentral biomass boiler": "Heat", - "urban decentral gas boiler": "Heat", - "urban decentral oil boiler": "Heat", - "urban decentral water tanks charger": "Heat", - "urban decentral water tanks discharger": "Heat", - "waste CHP": "Heat", - "waste CHP CC": "Heat", - } - - grid_connection = [ - "offwind-ac", - "offwind-dc", - "offwind-float", - "solar", - "solar-hsat", - ] - - for key, tech in costs_dict.items(): - if tech is None: - continue - sector = sector_dict[key] - - FOM = "OM Cost|Fixed" + "|" + sector + "|" + tech - VOM = "OM Cost|Variable" + "|" + sector + "|" + tech - capital = "Capital Cost" + "|" + sector + "|" + tech - - var[FOM] = costs.at[tech, "capital_cost"] / 1e3 # EUR/MW -> EUR/kW - var[VOM] = costs.at[tech, "VOM"] / MWh2GJ # EUR/MWh -> EUR/GJ - var[capital] = costs.at[tech, "investment"] / 1e3 # EUR/MW -> EUR/kW - - if key in grid_connection: - var[FOM] += costs.at["electricity grid connection", "capital_cost"] / 1e3 - var[capital] += costs.at["electricity grid connection", "investment"] / 1e3 - - return var - - def get_grid_capacity(n, region, year): var = pd.Series() ### Total Capacity @@ -5299,7 +5043,6 @@ def get_ariadne_var( get_emissions(n, region, energy_totals, industry_demand), get_policy(n, year), get_trade(n, region), - # get_operational_and_capital_costs(year), get_economy(n, region), get_system_cost(n, region), ] @@ -5366,22 +5109,19 @@ def get_data( "Investment|Energy Supply|Hydrogen|Gas" ] # For internal use only and translated directly to TWh - var["Demand|Electricity"] = ( - var.reindex( - [ - "Secondary Energy|Electricity|Storage Losses", - "Secondary Energy Input|Electricity|Heat", - "Secondary Energy Input|Electricity|Hydrogen", - "Secondary Energy Input|Electricity|Liquids", - "Final Energy|Industry|Electricity", - "Final Energy|Agriculture|Electricity", - "Final Energy|Residential and Commercial|Electricity", - "Final Energy|Transportation|Electricity", - "Final Energy|Carbon Dioxide Removal|Electricity", - ] - ).sum() - / 3.6 - ) + var["Demand|Electricity"] = var.reindex( + [ + "Secondary Energy|Electricity|Storage Losses", + "Secondary Energy Input|Electricity|Heat", + "Secondary Energy Input|Electricity|Hydrogen", + "Secondary Energy Input|Electricity|Liquids", + "Final Energy|Industry|Electricity", + "Final Energy|Agriculture|Electricity", + "Final Energy|Residential and Commercial|Electricity", + "Final Energy|Transportation|Electricity", + "Final Energy|Carbon Dioxide Removal|Electricity", + ] + ).sum() data = [] for v in var.index: @@ -5417,7 +5157,7 @@ def get_data( opts="", ll="vopt", sector_opts="None", - run="KN2045_Bal_v4", + run="KN2045_Mix", ) configure_logging(snakemake) config = snakemake.config @@ -5426,12 +5166,15 @@ def get_data( post_discretization = snakemake.params.post_discretization ariadne_template = pd.read_excel(snakemake.input.template, sheet_name=None) var2unit = ariadne_template["variable_definitions"].set_index("Variable")["Unit"] + var2unit = var2unit.str.replace("GJ", "MWh") + var2unit = var2unit.str.replace("PJ", "TWh") + industry_demands = [ pd.read_csv( in_dem, index_col="TWh/a (MtCO2/a)", ) - .multiply(TWh2PJ) + .multiply(TWh2MWh) .rename_axis("bus") for in_dem in snakemake.input.industry_demands ] @@ -5444,7 +5187,7 @@ def get_data( snakemake.params.energy_totals_year, level="year", ) - .multiply(TWh2PJ) + .multiply(TWh2MWh) ) sector_ratios = [ @@ -5489,7 +5232,7 @@ def get_data( if "debug" == "debug": # For debugging var = pd.Series() - idx = 2 + idx = 6 n = networks[idx] c = costs[idx] _industry_demand = industry_demands[idx] diff --git a/scripts/pypsa-de/modify_cost_data.py b/scripts/pypsa-de/modify_cost_data.py index 7690f1c2b..d76c76012 100644 --- a/scripts/pypsa-de/modify_cost_data.py +++ b/scripts/pypsa-de/modify_cost_data.py @@ -45,7 +45,7 @@ def carbon_component_fossils(costs, co2_price): file_path="../data/costs/", file_name="costs_2020.csv", cost_horizon="mean", - run="KN2045_Bal_v4", + run="KN2045_Mix", ) configure_logging(snakemake) diff --git a/scripts/pypsa-de/modify_district_heat_share.py b/scripts/pypsa-de/modify_district_heat_share.py index 150370308..a9fd3325f 100644 --- a/scripts/pypsa-de/modify_district_heat_share.py +++ b/scripts/pypsa-de/modify_district_heat_share.py @@ -104,7 +104,7 @@ def update_district_heat_share(heat_techs_clustered, dh_shares): ll="vopt", sector_opts="none", planning_horizons="2020", - run="KN2045_Bal_v4", + run="KN2045_Mix", ) logging.basicConfig(level=snakemake.config["logging"]["level"]) diff --git a/scripts/pypsa-de/modify_existing_heating.py b/scripts/pypsa-de/modify_existing_heating.py index d9491b229..67f54dd93 100644 --- a/scripts/pypsa-de/modify_existing_heating.py +++ b/scripts/pypsa-de/modify_existing_heating.py @@ -11,27 +11,21 @@ if "snakemake" not in globals(): snakemake = mock_snakemake( "modify_existing_heating", - run="KN2045_Bal_v4", + run="KN2045_Mix", ) configure_logging(snakemake) existing_heating = pd.read_csv(snakemake.input.existing_heating, index_col=0) - logger.info(f"Heating demand before modification:{existing_heating.loc['Germany']}") - - mapping = { - "gas boiler": "Gas Boiler", - "oil boiler": "Oil Boiler", - "air heat pump": "Heat Pump|Electrical|Air", - "ground heat pump": "Heat Pump|Electrical|Ground", - "biomass boiler": "Biomass Boiler", - } + logger.info( + f"Heating demand before modification:\n{existing_heating.loc['Germany']}" + ) new_values = pd.Series() logger.warning( - "Adjusting heating stock towards hard coded values from a previous REMod run. This is only a hotfix." + "Adjusting heating stock towards hard coded values from a\nprevious REMod run. This is only a hotfix." ) # Because REMod is not consistent and a better solution takes too long. new_values["gas boiler"] = 11.44 # million @@ -48,6 +42,8 @@ for tech, peak in new_values.items(): existing_heating.at["Germany", tech] = peak - logger.info(f"Heating demand after modification: {existing_heating.loc['Germany']}") + logger.info( + f"Heating demand after modification:\n{existing_heating.loc['Germany']}" + ) existing_heating.to_csv(snakemake.output.existing_heating) diff --git a/scripts/pypsa-de/modify_industry_demand.py b/scripts/pypsa-de/modify_industry_demand.py index 474933b44..6494ce8c2 100644 --- a/scripts/pypsa-de/modify_industry_demand.py +++ b/scripts/pypsa-de/modify_industry_demand.py @@ -10,7 +10,6 @@ - Production|Steel - Production|Chemicals|Ammonia - Production|Chemicals|Methanol -- Production|Non-Ferrous Metals - Production|Pulp and Paper """ @@ -30,39 +29,52 @@ opts="", ll="vopt", sector_opts="None", - run="KN2045_Bal_v4", + run="KN2045_Mix", planning_horizons=2020, ) configure_logging(snakemake) - # leitmodell for industry demand - leitmodell = "FORECAST v1.0" year = snakemake.input.industrial_production_per_country_tomorrow.split("_")[ -1 ].split(".")[0] - if snakemake.params.db_name == "ariadne2_intern" and year == "2020": - logger.warning(f"Assuming {leitmodell} uses 2021 as base year instead of 2020.") - year = "2021" existing_industry = pd.read_csv( snakemake.input.industrial_production_per_country_tomorrow, index_col=0 ) # read in ariadne database - ariadne = ( - pd.read_csv( - snakemake.input.ariadne, - index_col=["model", "scenario", "region", "variable", "unit"], + if year == "2020": + logger.info( + "For 2020, using hardcoded values from FORECAST from the ariadne2-internal database", + ) + ariadne = pd.DataFrame( + { + "Production|Chemicals|Ammonia": 2.891851, + "Production|Chemicals|Methanol": 1.359, + "Production|Non-Metallic Minerals": 68.635925, + "Production|Non-Metallic Minerals|Cement": 34.966, + "Production|Pulp and Paper": 40.746, + "Production|Steel": 40.621, + }, + index=[year], + ).T.multiply(1000) + else: + # leitmodell for industry demand + leitmodell = "FORECAST v1.0" + ariadne = ( + pd.read_csv( + snakemake.input.ariadne, + index_col=["model", "scenario", "region", "variable", "unit"], + ) + .loc[ + leitmodell, + snakemake.params.reference_scenario, + "Deutschland", + :, + "Mt/yr", + ] + .multiply(1000) ) - .loc[ - leitmodell, - snakemake.params.reference_scenario, - "Deutschland", - :, - "Mt/yr", - ] - .multiply(1000) - ) logger.info( "German industry demand before modification", diff --git a/scripts/pypsa-de/modify_prenetwork.py b/scripts/pypsa-de/modify_prenetwork.py index f77178a7d..9ead691e4 100644 --- a/scripts/pypsa-de/modify_prenetwork.py +++ b/scripts/pypsa-de/modify_prenetwork.py @@ -1275,7 +1275,7 @@ def scale_capacity(n, scaling): ll="vopt", sector_opts="none", planning_horizons="2025", - run="KN2045_Bal_v4", + run="KN2045_Mix", ) configure_logging(snakemake) diff --git a/scripts/pypsa-de/plot_ariadne_report.py b/scripts/pypsa-de/plot_ariadne_report.py index ab60e193d..c3b023538 100644 --- a/scripts/pypsa-de/plot_ariadne_report.py +++ b/scripts/pypsa-de/plot_ariadne_report.py @@ -1491,8 +1491,6 @@ def plot_elec_prices_spatial( region="DE", lang="ger", ): - # onshore_regions = gpd.read_file("/home/julian-geis/repos/pypsa-ariadne-1/resources/20241203-force-onwind-south-49cl-disc/KN2045_Bal_v4/regions_onshore_base_s_49.geojson") - # onshore_regions = onshore_regions.set_index('name') if lang == "ger": title1 = "Durchschnittspreis, NEP Ausbau [EUR/MWh]" cbar1_label = "Börsenstrompreis zzgl. durchschnittlichem Netzentgelt [EUR/MWh]" @@ -2768,7 +2766,7 @@ def plot_h2_trade( opts="", ll="vopt", sector_opts="None", - run="KN2045_Bal_v4", + run="KN2045_Mix", ) configure_logging(snakemake) diff --git a/scripts/pypsa-de/plot_ariadne_scenario_comparison.py b/scripts/pypsa-de/plot_ariadne_scenario_comparison.py index dd075f64f..27a29e93e 100644 --- a/scripts/pypsa-de/plot_ariadne_scenario_comparison.py +++ b/scripts/pypsa-de/plot_ariadne_scenario_comparison.py @@ -28,7 +28,7 @@ def scenario_plot(df, var): # ll="vopt", # sector_opts="None", # planning_horizons="2050", - # run="KN2045_Bal_v4" + # run="KN2045_Mix" ) dfs = [] diff --git a/scripts/pypsa-de/plot_ariadne_variables.py b/scripts/pypsa-de/plot_ariadne_variables.py index 4dfba374e..9ca388c63 100644 --- a/scripts/pypsa-de/plot_ariadne_variables.py +++ b/scripts/pypsa-de/plot_ariadne_variables.py @@ -4,8 +4,6 @@ from scripts._helpers import mock_snakemake -TWh2PJ = 3.6 - def plot_trade( df, @@ -15,31 +13,29 @@ def plot_trade( # WARNING i just asked COPILOT to reformat the two plots below # load data and convert to TWh h2_balance = ( - df.loc["Trade|Secondary Energy|Hydrogen|Volume"] / TWh2PJ * -1 + df.loc["Trade|Secondary Energy|Hydrogen|Volume"] * -1 ) # exports-imports - h2_import = df.loc["Trade|Secondary Energy|Hydrogen|Gross Import|Volume"] / TWh2PJ + h2_import = df.loc["Trade|Secondary Energy|Hydrogen|Gross Import|Volume"] h2_export = h2_balance - h2_import elec_balance = ( - df.loc["Trade|Secondary Energy|Electricity|Volume"] / TWh2PJ * -1 + df.loc["Trade|Secondary Energy|Electricity|Volume"] * -1 ) # exports-imports - elec_import = ( - df.loc["Trade|Secondary Energy|Electricity|Gross Import|Volume"] / TWh2PJ - ) + elec_import = df.loc["Trade|Secondary Energy|Electricity|Gross Import|Volume"] elec_export = elec_balance - elec_import fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4)) # Plot Electricity Trade ax1.bar( - elec_import.columns, elec_import.loc["PJ/yr"], color="#70af1d", label="Import" + elec_import.columns, elec_import.loc["TWh/yr"], color="#70af1d", label="Import" ) ax1.bar( - elec_export.columns, elec_export.loc["PJ/yr"], color="#3f630f", label="Export" + elec_export.columns, elec_export.loc["TWh/yr"], color="#3f630f", label="Export" ) ax1.scatter( elec_balance.columns, - elec_balance.loc["PJ/yr"], + elec_balance.loc["TWh/yr"], color="black", marker="x", label="Netto", @@ -52,11 +48,11 @@ def plot_trade( ax1.legend(loc="upper left") # Plot Hydrogen Trade - ax2.bar(h2_import.columns, h2_import.loc["PJ/yr"], color="#f081dc", label="Import") - ax2.bar(h2_export.columns, h2_export.loc["PJ/yr"], color="#6b3161", label="Export") + ax2.bar(h2_import.columns, h2_import.loc["TWh/yr"], color="#f081dc", label="Import") + ax2.bar(h2_export.columns, h2_export.loc["TWh/yr"], color="#6b3161", label="Export") ax2.scatter( h2_balance.columns, - h2_balance.loc["PJ/yr"], + h2_balance.loc["TWh/yr"], color="black", marker="x", label="Netto", @@ -78,17 +74,17 @@ def plot_h2_trade( ): # load data and convert to TWh h2_balance = ( - df.loc["Trade|Secondary Energy|Hydrogen|Volume"] / TWh2PJ * -1 + df.loc["Trade|Secondary Energy|Hydrogen|Volume"] * -1 ) # exports-imports - h2_import = df.loc["Trade|Secondary Energy|Hydrogen|Gross Import|Volume"] / TWh2PJ + h2_import = df.loc["Trade|Secondary Energy|Hydrogen|Gross Import|Volume"] h2_export = h2_balance - h2_import fig, ax = plt.subplots(figsize=(6, 4)) - ax.bar(h2_import.columns, h2_import.loc["PJ/yr"], color="#f081dc", label="Import") - ax.bar(h2_export.columns, h2_export.loc["PJ/yr"], color="#6b3161", label="Export") + ax.bar(h2_import.columns, h2_import.loc["TWh/yr"], color="#f081dc", label="Import") + ax.bar(h2_export.columns, h2_export.loc["TWh/yr"], color="#6b3161", label="Export") ax.scatter( h2_balance.columns, - h2_balance.loc["PJ/yr"], + h2_balance.loc["TWh/yr"], color="black", marker="x", label="Netto", @@ -111,23 +107,21 @@ def plot_elec_trade( ): # load data and convert to TWh elec_balance = ( - df.loc["Trade|Secondary Energy|Electricity|Volume"] / TWh2PJ * -1 + df.loc["Trade|Secondary Energy|Electricity|Volume"] * -1 ) # exports-imports - elec_import = ( - df.loc["Trade|Secondary Energy|Electricity|Gross Import|Volume"] / TWh2PJ - ) + elec_import = df.loc["Trade|Secondary Energy|Electricity|Gross Import|Volume"] elec_export = elec_balance - elec_import fig, ax = plt.subplots(figsize=(6, 4)) ax.bar( - elec_import.columns, elec_import.loc["PJ/yr"], color="#70af1d", label="Import" + elec_import.columns, elec_import.loc["TWh/yr"], color="#70af1d", label="Import" ) ax.bar( - elec_export.columns, elec_export.loc["PJ/yr"], color="#3f630f", label="Export" + elec_export.columns, elec_export.loc["TWh/yr"], color="#3f630f", label="Export" ) ax.scatter( elec_balance.columns, - elec_balance.loc["PJ/yr"], + elec_balance.loc["TWh/yr"], color="black", marker="x", label="Netto", @@ -589,7 +583,7 @@ def within_plot( select_regex=r"", drop_regex=r"", write_sum=False, - unit="EUR_2020/GJ", + unit="EUR_2020/MWh", **kwargs, ): df = df.T.copy() @@ -708,17 +702,17 @@ def elec_val_plot(df, savepath): elec_capacities["pypsa"] = [ 0, - df.loc[("Capacity|Electricity|Hydro", "GW"), "2020"], + df.loc[("Capacity|Electricity|Hydro", "GW"), 2020], 0, - df.loc[("Capacity|Electricity|Biomass", "GW"), "2020"], - df.loc[("Capacity|Electricity|Nuclear", "GW"), "2020"], - df.loc[("Capacity|Electricity|Coal|Lignite", "GW"), "2020"], - df.loc[("Capacity|Electricity|Coal|Hard Coal", "GW"), "2020"], - df.loc[("Capacity|Electricity|Oil", "GW"), "2020"], - df.loc[("Capacity|Electricity|Gas", "GW"), "2020"], - df.loc[("Capacity|Electricity|Wind|Onshore", "GW"), "2020"], - df.loc[("Capacity|Electricity|Wind|Offshore", "GW"), "2020"], - df.loc[("Capacity|Electricity|Solar", "GW"), "2020"], + df.loc[("Capacity|Electricity|Biomass", "GW"), 2020], + df.loc[("Capacity|Electricity|Nuclear", "GW"), 2020], + df.loc[("Capacity|Electricity|Coal|Lignite", "GW"), 2020], + df.loc[("Capacity|Electricity|Coal|Hard Coal", "GW"), 2020], + df.loc[("Capacity|Electricity|Oil", "GW"), 2020], + df.loc[("Capacity|Electricity|Gas", "GW"), 2020], + df.loc[("Capacity|Electricity|Wind|Onshore", "GW"), 2020], + df.loc[("Capacity|Electricity|Wind|Offshore", "GW"), 2020], + df.loc[("Capacity|Electricity|Solar", "GW"), 2020], ] elec_generation["real (gross)"] = [ @@ -758,18 +752,18 @@ def elec_val_plot(df, savepath): # https://energy-charts.info/charts/energy/chart.htm?l=en&c=DE&interval=year&year=2020&source=total elec_generation["pypsa (net)"] = [ - -df.loc[("Trade|Secondary Energy|Electricity|Volume", "PJ/yr"), "2020"] / 3.6, + -df.loc[("Trade|Secondary Energy|Electricity|Volume", "TWh/yr"), 2020], 0, - df.loc[("Secondary Energy|Electricity|Hydro", "PJ/yr"), "2020"] / 3.6, + df.loc[("Secondary Energy|Electricity|Hydro", "TWh/yr"), 2020], 0, - df.loc[("Secondary Energy|Electricity|Biomass", "PJ/yr"), "2020"] / 3.6, - df.loc[("Secondary Energy|Electricity|Nuclear", "PJ/yr"), "2020"] / 3.6, - df.loc[("Secondary Energy|Electricity|Coal|Lignite", "PJ/yr"), "2020"] / 3.6, - df.loc[("Secondary Energy|Electricity|Coal|Hard Coal", "PJ/yr"), "2020"] / 3.6, - df.loc[("Secondary Energy|Electricity|Oil", "PJ/yr"), "2020"] / 3.6, - df.loc[("Secondary Energy|Electricity|Gas", "PJ/yr"), "2020"] / 3.6, - df.loc[("Secondary Energy|Electricity|Wind", "PJ/yr"), "2020"] / 3.6, - df.loc[("Secondary Energy|Electricity|Solar", "PJ/yr"), "2020"] / 3.6, + df.loc[("Secondary Energy|Electricity|Biomass", "TWh/yr"), 2020], + df.loc[("Secondary Energy|Electricity|Nuclear", "TWh/yr"), 2020], + df.loc[("Secondary Energy|Electricity|Coal|Lignite", "TWh/yr"), 2020], + df.loc[("Secondary Energy|Electricity|Coal|Hard Coal", "TWh/yr"), 2020], + df.loc[("Secondary Energy|Electricity|Oil", "TWh/yr"), 2020], + df.loc[("Secondary Energy|Electricity|Gas", "TWh/yr"), 2020], + df.loc[("Secondary Energy|Electricity|Wind", "TWh/yr"), 2020], + df.loc[("Secondary Energy|Electricity|Solar", "TWh/yr"), 2020], ] # elec_generation.loc["sum/10"] = elec_generation.sum().div(10) @@ -807,7 +801,7 @@ def elec_val_plot(df, savepath): ll="v1.2", sector_opts="None", planning_horizons="2045", - run="KN2045_Bal_v4", + run="KN2045_Mix", # configfiles="config/config.public.yaml" ) @@ -821,22 +815,22 @@ def elec_val_plot(df, savepath): .groupby(["Variable", "Unit"], dropna=False) .sum() ).round(5) + elec_val_plot(df, savepath=snakemake.output.elec_val_2020) + df.drop(columns=[2020], inplace=True) df.columns = df.columns.astype(str) leitmodell = "REMIND-EU v1.1" dfremind = pd.read_csv( snakemake.input.ariadne_database, index_col=["model", "scenario", "region", "variable", "unit"], - ).loc[leitmodell, snakemake.params.fallback_reference_scenario, "Deutschland"][ - df.columns - ] + ).loc[leitmodell, snakemake.params.reference_scenario, "Deutschland"][df.columns] dfremind.index.names = df.index.names side_by_side_plot( df, dfremind, - "Primary Energy in PJ_yr", + "Primary Energy in TWh_yr", savepath=snakemake.output.primary_energy, select_regex=r"Primary Energy\|[^|]*$", drop_regex=r"^(?!.*(Fossil|Price)).+", @@ -845,7 +839,7 @@ def elec_val_plot(df, savepath): side_by_side_plot( df, dfremind, - "Detailed Primary Energy in PJ_yr", + "Detailed Primary Energy in TWh_yr", savepath=snakemake.output.primary_energy_detailed, select_regex=r"Primary Energy\|[^|]*\|[^|]*$", drop_regex=r"^(?!.*(CCS|Price|Volume)).+", @@ -854,7 +848,7 @@ def elec_val_plot(df, savepath): side_by_side_plot( df, dfremind, - "Secondary Energy in PJ_yr", + "Secondary Energy in TWh_yr", savepath=snakemake.output.secondary_energy, select_regex=r"Secondary Energy\|[^|]*$", drop_regex=r"^(?!.*(Price)).+", @@ -863,7 +857,7 @@ def elec_val_plot(df, savepath): side_by_side_plot( df, dfremind, - "Detailed Secondary Energy in PJ_yr", + "Detailed Secondary Energy in TWh_yr", savepath=snakemake.output.secondary_energy_detailed, # Secondary Energy|Something|Something (exactly two pipes) select_regex=r"Secondary Energy\|[^|]*\|[^|]*$", @@ -871,11 +865,6 @@ def elec_val_plot(df, savepath): drop_regex=r"^(?!.*(Fossil|Renewables|Losses|Price|Volume)).+", ) - if df.loc["Final Energy|Industry excl Non-Energy Use|Hydrogen", "2020"].item() < 0: - val = df.loc["Final Energy|Industry excl Non-Energy Use|Hydrogen", "2020"] - df.loc["Final Energy|Industry excl Non-Energy Use|Hydrogen", "2020"] = 0 - df.loc["Final Energy|Hydrogen", "2020"] = 0 - print("WARNING! NEGATIVE HYDROGEN DEMAND IN INDUSTRY IN 2020! ", val) if df.loc["Final Energy|Industry excl Non-Energy Use|Hydrogen", "2025"].item() < 0: val = df.loc["Final Energy|Industry excl Non-Energy Use|Hydrogen", "2025"] df.loc["Final Energy|Industry excl Non-Energy Use|Hydrogen", "2025"] = 0 @@ -884,7 +873,7 @@ def elec_val_plot(df, savepath): side_by_side_plot( df, dfremind, - "Final Energy in PJ_yr", + "Final Energy in TWh_yr", savepath=snakemake.output.final_energy, select_regex=r"Final Energy\|[^|]*$", rshift=1.45, @@ -894,7 +883,7 @@ def elec_val_plot(df, savepath): side_by_side_plot( df, dfremind, - "Detailed Final Energy in PJ_yr", + "Detailed Final Energy in TWh_yr", savepath=snakemake.output.final_energy_detailed, select_regex=r"Final Energy\|[^|]*\|[^|]*$", rshift=1.7, @@ -1039,14 +1028,12 @@ def elec_val_plot(df, savepath): write_sum=True, ) - elec_val_plot(df, savepath=snakemake.output.elec_val_2020) - within_plot( df[df.index.get_level_values("Variable").str.startswith("Trade")], dfremind, title="Trade", savepath=snakemake.output.trade, - unit="PJ/yr", + unit="TWh/yr", ) plot_NEP(df, savepath=snakemake.output.NEP_plot) diff --git a/scripts/pypsa-de/plot_hydrogen_network_incl_kernnetz.py b/scripts/pypsa-de/plot_hydrogen_network_incl_kernnetz.py index f88233c97..704704246 100644 --- a/scripts/pypsa-de/plot_hydrogen_network_incl_kernnetz.py +++ b/scripts/pypsa-de/plot_hydrogen_network_incl_kernnetz.py @@ -334,15 +334,13 @@ def plot_h2_map(n, regions): ll="vopt", sector_opts="None", planning_horizons="2045", - run="CurrentPolicies", + run="ExPol", ) configure_logging(snakemake) set_scenario_config(snakemake) n = pypsa.Network(snakemake.input.network) - # fn= "/home/julian-geis/repos/pypsa-ariadne/results/20240426plotH2Kernnetz/CurrentPolicies/postnetworks/elec_s_22_lvopt__none_2030.nc" - # n = pypsa.Network(fn) regions = gpd.read_file(snakemake.input.regions).set_index("name") diff --git a/scripts/pypsa-de/retrieve_ariadne_database.py b/scripts/pypsa-de/retrieve_ariadne_database.py index b54761a11..510424da7 100644 --- a/scripts/pypsa-de/retrieve_ariadne_database.py +++ b/scripts/pypsa-de/retrieve_ariadne_database.py @@ -17,7 +17,7 @@ db = pyam.read_iiasa( snakemake.params.db_name, - model=snakemake.params.leitmodelle.values(), + model=list(snakemake.params.leitmodelle.values()), scenario=snakemake.params.scenarios, # Download only the most recent iterations of scenarios ) diff --git a/scripts/write_statistics.py b/scripts/write_statistics.py index d7fac37ee..074937929 100644 --- a/scripts/write_statistics.py +++ b/scripts/write_statistics.py @@ -30,7 +30,7 @@ def call_with_handle(func, **kwargs): snakemake = mock_snakemake( "write_statistics", - run="CurrentPolicies", + run="ExPol", simpl="", ll="vopt", clusters="22",