Skip to content

feat:improve PtX excess heat handling#1944

Open
amos-schledorn wants to merge 98 commits intorefactor-ptes-boostingfrom
feat-improve-ptx-excess-heat
Open

feat:improve PtX excess heat handling#1944
amos-schledorn wants to merge 98 commits intorefactor-ptes-boostingfrom
feat-improve-ptx-excess-heat

Conversation

@amos-schledorn
Copy link
Copy Markdown
Contributor

@amos-schledorn amos-schledorn commented Dec 11, 2025

Integrates utilisation of excess heat from Power-to-X processes (electrolysis, Fischer-Tropsch, Sabatier, Haber-Bosch, methanolisation, fuel cells) into the new heat-source structure.

Changes

definitions/heat_source.py

  • 6 new PTX heat sources in HeatSource enum
  • HeatSourceType categorization (INEXHAUSTIBLE, SUPPLY_LIMITED, STORAGE, PROCESS_WASTE)
  • Renamed has_constant_temperaturetemperature_from_config
  • Moved some of the logic from prepare_sector_network.add_waste_heat() to HeatSource enum
  • Removed unnecessary __init__ from HeatSource enum

prepare_sector_network.py

  • add_waste_heat(): Reduced from ~80 lines to ~30 using loop over PtX HeatSources

Small refactoring changes

  • Updated build_cop_profiles/run.py to use temperature_from_config
  • Updated build_heat_source_utilisation_profiles.py to use temperature_from_config
  • Updated rules/build_sector.smk to use temperature_from_config

Config Changes

sector:
  heat_source_temperatures:
    geothermal: 65
    electrolysis_excess: 200
    fuel_cell_excess: 200
    fischer_tropsch_excess: 200
    haber_bosch_excess: 200
    sabatier_excess: 200
    methanolisation_excess: 200
  ptx_heat_losses: 0.05
  heat_sources:
    urban central:
    - air
    - electrolysis_excess
    - fuel_cell_excess
    - fischer_tropsch_excess
    - haber_bosch_excess
    - sabatier_excess
    - methanolisation_excess
plotting:
    tech_colors:
    # necessary additions for waste heat carriers

Waste Heat Efficiency Changes

The old implementation used hardcoded approximations. The new implementation uses efficiency-heat values from technology-data where available:

Process Old Formula New Source Value (2050)
Fischer-Tropsch 0.95 - efficiency (~0.15) technology-data efficiency-heat 0.15
Electrolysis 0.84 - efficiency (~0.14) technology-data efficiency-heat 0.129
Haber-Bosch calc based on industry ratios (0.15 * total_energy_input / electricity_input ~3.75) technology-data efficiency-heat/electricity-input 0.146
Methanolisation technology-data heat-output / hydrogen-input (~0.088) same calculation* ~0.088
Sabatier 0.95 - efficiency (=0.15) same calculation* 0.15
Fuel Cell 0.95 - efficiency (=0.45) same calculation* 0.45

Checklist

  • I tested my contribution locally and it works as intended.
  • Code and workflow changes are sufficiently documented.
  • Changed dependencies are added to pixi.toml (using pixi add <dependency-name>).
  • Changes in configuration options are added in config/config.default.yaml.
  • Changes in configuration options are documented in doc/configtables/*.csv.
  • For new data sources or versions, these instructions <https://pypsa-eur.readthedocs.io/en/latest/data_sources.html>_ have been followed.
  • A release note doc/release_notes.rst is added.

Testing

Configs

Base branch


scenario:
  clusters:
  - 8
  planning_horizons:
  - 2040

clustering:
  temporal:
    resolution_sector: 25h

countries: ['DE', 'DK']

plotting:
  energy_threshold: 0
  enable_heat_source_maps: true
  interactive_bus_balance: 
    bus_name_pattern: "*urban central*"

sector:
  district_heating:
    supply_temperature_approximation:
      max_forward_temperature_baseyear:
        DE: 110
        DK: 80
      min_forward_temperature_baseyear:
        DE: 75
        DK: 55
      return_temperature_baseyear:
        DE: 60
        DK: 50
      relative_annual_temperature_reduction: 0.0
  ttes: true

solving:
  options:
    noisy_costs: false

Feature branch, same config but with same temperatures as implicitly assumed before

(only changes are waste heat efficiencies)

sector:
  district_heating:
    heat_source_temperatures:
      geothermal: 65
      electrolysis_excess: 200
      fuel_cell_excess: 200 
      fischer_tropsch_excess: 200
      haber_bosch_excess: 2
      sabatier_excess: 200 
      methanolisation_excess: 200

Feature branch, default config

Results

objective values

Scenario Objective (€) Δ vs Base
Base (no PTX waste heat) 117.25 bn -
Feature, 200°C PtX temps 117.31 bn +0.056%
Feature, default PtX temps 117.32 bn +0.61%
Feature, 200°C PtX temps, hard-coded base branch heat-efficiencies (-> equivalent to base) 117.25 bn +0.0002%

Excess heat utilisation

Process Base Feature, 200°C PtX temps Feature, default PtX temps
Fischer-Tropsch 0.05 0.04 0.03
Sabatier 0.01 0.01 0.01
Haber-Bosch 3510.00 510.47 506.12
Methanolisation 0.04 0.03 0.03
Electrolysis 1765.32 1575.85 1556.97
Fuel Cell 0.12 0.18 0.14

Urban central heat balance

Base
image
Feature, 200°C PtX temps
image
Feature, default PtX temps
image

@amos-schledorn amos-schledorn changed the base branch from master to refactor-ptes-boosting December 11, 2025 15:35
@amos-schledorn amos-schledorn marked this pull request as draft December 11, 2025 15:35
@amos-schledorn amos-schledorn changed the title fea:improve PtX excess heat handling feat:improve PtX excess heat handling Dec 12, 2025
@amos-schledorn amos-schledorn marked this pull request as ready for review December 17, 2025 16:08
@amos-schledorn amos-schledorn requested review from cpschau and fneum and removed request for fneum December 17, 2025 16:08
@amos-schledorn
Copy link
Copy Markdown
Contributor Author

Note: 36110d5 fixed a bug that caused the return flow temperature to be used in the COP approximation of all heat sources, including those pre-heating the return flow.
-> The above results assume incorrect COPs for heat sources above the return temperature boosted via heat pumps.

Copy link
Copy Markdown
Contributor

@cpschau cpschau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work @amos-schledorn! I think I am finally getting a sense for the convenience of enums 😄

I only have one question about the processing of the HB heat efficiency. Other than that, this looks good to me!

Comment on lines +371 to +372
costs.at[self.technology_data_name, "efficiency-heat"]
/ costs.at[self.technology_data_name, "electricity-input"]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the heat efficiency value of the technology data not used directly?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because the Haber-Bosch link's bus1 is electricity -> scaling of "efficiency-heat" [MWh_th/MWh_NH3] to [MWh_th/MWh_el] is necessary .

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood (because electricity is on bus0).

amos-schledorn and others added 30 commits February 16, 2026 11:44
* fix powerplant to region mapping; use ppm for wind and solar

* re-add everywhere_powerplants param

* do not apply ppm phase-out heuristic

* adjust test configuration files

* add 2030 to power grouping years

* ensure renewable carriers are not added as conventional power plants

* improve handling of grouping years in add_existing_baseyear

* pre-commit fixes
* Use .static and .components

* Use .dynamic and .components

* Replace lin{k,e}_widths

* More iterate_components replaced

* More dynamic and static attributes

* Rename plotting args (do not touch configs)

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* resolve more deprecations

* saver iterate

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: lkstrp <lkstrp@pm.me>
* Add config schema updater & docs

* Updates following review; fix example

* Add instructions on how to check for prior changes to config item

* Lower case `name`; Actually use `name`

* Not allowed to use `Field` with `_name` attr; mass schema file rename

* Simplify schema name setting
* fix missing or outdated configuration options

* pixi run generate-config
* allow custom efficiency_classes for conventional generators

* pixi run generate-config
* chore: pin grpcio<1.78 to silence warnings

* doc: add release note

* Update envs/environment.yaml

---------

Co-authored-by: Lukas Trippe <lkstrp@pm.me>
* Update pixi `run-post-link-scripts` config

* Remove `dot -c` from pixi tasks

---------

Co-authored-by: Lukas Trippe <lkstrp@pm.me>
* distribute electricity demand by JRC energy atlas

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* reset_index when redistribute_attribute is called

* add dependency and adapt to new data inventory

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* add to data.csv

* codespell fixes and update pixi.lock

* update schema

* fixes for new data layer

* add rule messages

* solve slow DAG evaluation

The rule was using storage() in the input block, which caused Snakemake
to make HTTP HEAD requests during DAG construction to verify the file
exists. The UK government server is slow to respond to HEAD requests,
causing a 30x slowdown (2 sec → 60 sec) in DAG evaluation.

This fix removes the input block and handles the download directly in
the run block using requests.get(), matching the pattern used by
retrieve_ons_lad. This eliminates the existence check and restores
DAG evaluation speed.

* fix retrieval issues with storage()

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* add raise_for_status

* restore master pixi.lock

* update pixi.lock

* add to archive

* more archive

* handle archive

* fix swiss

* generate config

* fix: url format

* add retrieval for for archive and fix upload

* another url fix

* update pixi.lock

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: lkstrp <lkstrp@pm.me>
* Reverting to .pdf file ending.

* Added release notes.

---------

Co-authored-by: Fabian Neumann <fabian.neumann@outlook.de>
Co-authored-by: lkstrp <62255395+lkstrp@users.noreply.github.com>
Co-authored-by: Fabian Neumann <fabian.neumann@outlook.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.