Skip to content

Heat dsm 2025#1857

Merged
fneum merged 43 commits intoPyPSA:masterfrom
open-energy-transition:heat_dsm_2025
Dec 2, 2025
Merged

Heat dsm 2025#1857
fneum merged 43 commits intoPyPSA:masterfrom
open-energy-transition:heat_dsm_2025

Conversation

@lprieto1409
Copy link
Copy Markdown
Contributor

@lprieto1409 lprieto1409 commented Oct 14, 2025

Closes # (if applicable).

Changes proposed in this Pull Request

This PR introduces residential heat demand-side management (DSM) for electric heat pumps based on the smartEn / DNV methodology.

It enables flexible heat demand that shifts within configurable intraday periods, improving renewable integration and reducing system costs.

The new formulation models building thermal mass as an energy-storage resource, allowing load shifting within user-defined windows (default = 12 h) via the restriction_time parameter, while maintaining thermal comfort.

Implementation

  • Adds residential_heat section in config/config.default.yaml with dsm, restriction_value, and restriction_time parameters (restriction_value reflects projected EC heat-pump rollout, ≈ 27% by 2030)
  • Applies DSM to rural, urban decentral, and urban central (district-heating) systems
  • Introduces heat_dsm_profile() in scripts/build_hourly_heat_demand.py and DSM stores in scripts/prepare_sector_network.py
  • Updates rules/build_sector.smk, documentation (doc/configtables/sector.csv, doc/supply_demand.rst),
    and release notes

Validation & Impact Analysis

The following analysis demonstrates the flexibility feature is working correctly using a test scenario (EU27, TY: 2030, 38 clusters). Comparison: Baseline (No DSM) vs. With DSM.

1. DSM Dispatch & Renewable Response

The plot validates dynamic optimization: DSM shifts from wind-following in winter to solar-driven midday charging in summer, confirming responsiveness to renewable availability.

02_dsm_stores_dispatch

2. Heat Pump Efficiency Improvement

DSM improves heat pump efficiency by shifting operation to higher COP periods. The time series shows consistently higher COP for DSM, particularly in summer, with the distribution revealing more frequent operation at higher efficiency levels.

04_cop_improvement

3. Generation Mix Changes

06_generation_by_technology

The flexibility provided by DSM dynamically shifts the optimal generation mix, leading to the largest proportional increases in solar thermal and biogas dispatch:

4. Generation Dispatch Patterns

07_generation_dispatch_patterns

The bottom panel shows DSM's net impact on generation. During summer, DSM reduces generation through better COP utilization and solar alignment. In winter, it increases generation due to thermal storage losses and pre-heating during high-wind periods.

5. Renewable Curtailment

08_curtailment_by_technology

DSM reduces offshore wind curtailment by absorbing surplus generation, but increases onshore wind curtailment due to higher capacity deployment driven by storage losses.

6. System Cost Impact

10_system_cost_comparison

Heat DSM reduces total system cost by 1.3 billion EUR (0.22%). Generator capacity investment remains unchanged at 156 B€, while storage and link investments decrease slightly due to improved system flexibility.

Definition of done

  • Update the code to current master and resolve the merge conflict
  • Check the code is still working as intended
  • Check the feature implementation, if the implementation is reasonable and confirmed by literature/assumptions supported by the referenced document
  • Check if the code matches the style and requirements of the remaining PyPSA-Eur code
  • Add some documentation (PyPSA-Eur style, i.e. the configuration options, but also to the body of the PyPSA-Eur docs where the logic of implemented features is explained)
  • Update the assessment of the impact this PR has on the model figure/qualitatively

Checklist

  • I tested my contribution locally and it works as intended.
  • Code and workflow changes are sufficiently documented.
  • Changed dependencies are added to envs/environment.yaml.
  • Changes in configuration options are added in config/config.default.yaml.
  • Changes in configuration options are documented in doc/configtables/*.csv.
  • Sources of newly added data are documented in doc/data_sources.rst.
  • A release note doc/release_notes.rst is added.

@lprieto1409 lprieto1409 marked this pull request as ready for review October 14, 2025 03:38
@euronion
Copy link
Copy Markdown
Contributor

Supersedes #1856 and #1371

Copy link
Copy Markdown
Contributor

@euronion euronion left a comment

Choose a reason for hiding this comment

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

Thanks @lprieto1409 . I have a few questions and a few improvement suggestions, see the comments below.

@euronion
Copy link
Copy Markdown
Contributor

@lprieto1409 The oet/master got merged into this branch instead of the pypsa-eur/master.
Can you please fix it? It makes it difficult to review and we don't want the OET changes in here.

@fneum
Copy link
Copy Markdown
Member

fneum commented Nov 1, 2025

Thanks for the PR. For getting it reviewed here, could you prepare:

  1. An overview of what new functionality was added and how it can be used (configuration settings, new data dependencies, etc.). Please, not just an auto-generated AI summary.

  2. Could you add a before (master) and after (this PR) comparison of system costs and energy balances, as well as any other aspects relevant to the feature? This allows us to assess whether the proposed changes are plausible quickly.

Thank you!

@lprieto1409
Copy link
Copy Markdown
Contributor Author

@lprieto1409 The oet/master got merged into this branch instead of the pypsa-eur/master. Can you please fix it? It makes it difficult to review and we don't want the OET changes in here.

Thanks @euronion, I fixed it and also address the conflicts, let me know if you have any additional comments

@euronion
Copy link
Copy Markdown
Contributor

Thanks a lot for the updated figures @lprieto1409 , this helps discussion the PR impacts!

I'm not fully happy with the PR results.

  1. Looking at the figures, it seems that most of the DSF serves the integration of solar thermal outside of winter/the main heating season
  2. The impact of DSF during winter/heating season on the electricity generation profile seems small.
  3. The DSF only works in pulling demand forward in time, not by delaying demand, i.e. it allows to heat earlier, but not to defer the heating decision. This is a modelling decision, by assuming e_min_pu = 0 for the DSM store.

Related to 1. and 2.:
This could either be an artifact of the model results you show only being for 6h resolution, or they could be and unexpected interaction with other aspects. If I look at the earlier results from @martacki 's implementation at #1371 , I would have exepcted a more pronounced impact during winter/heating season.
Can you please check with 1h results again. If then it doesn't change have a look and see if there is indeed not the behaviour that @martacki saw and what could be causing it. If it does change with different time resolution, then best to add a note to the documentation and hint at this PR with different results for different time resolutions.

Related to 3. I would argue that we should have e_min_pu = (-1) * e_max_pu, representing the thermal inertia of buildings (e_max_pu > 0 -> building get's heated above regular temperature and cools down slowly, e_min_pu < 0 -> building is allowed to cool down below regular temperature and then is heated up again). I suggest to make this configurable with a a dedicated config key, e.g. shift: {back-and-forth,back,forth}.

@lprieto1409
Copy link
Copy Markdown
Contributor Author

Thanks a lot for the updated figures @lprieto1409 , this helps discussion the PR impacts!

I'm not fully happy with the PR results.

1. Looking at the figures, it seems that most of the DSF serves the integration of `solar thermal` outside of winter/the main heating season

2. The impact of DSF during winter/heating season on the electricity generation profile seems small.

3. The DSF only works in pulling demand forward in time, not by delaying demand, i.e. it allows to heat earlier, but not to defer the heating decision. This is a modelling decision, by assuming `e_min_pu = 0` for the DSM store.

Related to 1. and 2.: This could either be an artifact of the model results you show only being for 6h resolution, or they could be and unexpected interaction with other aspects. If I look at the earlier results from @martacki 's implementation at #1371 , I would have exepcted a more pronounced impact during winter/heating season. Can you please check with 1h results again. If then it doesn't change have a look and see if there is indeed not the behaviour that @martacki saw and what could be causing it. If it does change with different time resolution, then best to add a note to the documentation and hint at this PR with different results for different time resolutions.

Related to 3. I would argue that we should have e_min_pu = (-1) * e_max_pu, representing the thermal inertia of buildings (e_max_pu > 0 -> building get's heated above regular temperature and cools down slowly, e_min_pu < 0 -> building is allowed to cool down below regular temperature and then is heated up again). I suggest to make this configurable with a a dedicated config key, e.g. shift: {back-and-forth,back,forth}.

Thanks for your comments @euronion, to look even further at points 1 and 2, I run the same test on hourly resolution from January to March (3 months) here are some of the results comparing both:

1 hour resolution
04_cop_improvement

6 hour resolution
04_cop_improvement

1 hour resolution
06_generation_by_technology

6 hour resolution
06_generation_by_technology

1 hour resolution
07_generation_dispatch_patterns

6 hour resolution
07_generation_dispatch_patterns

1 hour resolution
08_curtailment_by_technology

6 hour resolution
08_curtailment_by_technology

1 hour resolution
11_dsm_soc_selected_stores

6 hour resolution
11_dsm_soc_selected_stores

Rename config and restructure config. Add directionality option.
@euronion
Copy link
Copy Markdown
Contributor

Thanks for the updated plots.
I was still puzzled by the little effects, but the 6h does smooth over some of the benefits of the 1h.
I had a look myself and made a few adjustments:

  • Implemented directionality: Structures can be cooled or heated below/above requirements (overheat and undercool or overheat-undercool). The previous implementation was only overheat.
  • Reduced the test scope to 5 countries, 2 months, hourly resolution for faster solving

Here are the results I'm getting:

The effect on the heat pump dispatch pattern is very noticeable:
image

Although the annual COP is not much affected:
image

The electricity generation / dispatch pattern is also affected, in peak by up to 27%:
image

Interestingly enough, the undercool-ing seems to be more prominent than the overheating. I think that change makes most of the difference. You can see this in the SoC of the heat dsm / virtual stores, as they are more often negative than positive. This corresponds to letting the housing structure cool below target temperature during the morning/midday and to re-heat it to target temperature in the early afternoon/evening.
image

@euronion
Copy link
Copy Markdown
Contributor

I'm happy with the results now.

@martacki and @lprieto1409 feel free to have another look. I'd consider it RTM then

@lprieto1409
Copy link
Copy Markdown
Contributor Author

I'm happy with the results now.

@martacki and @lprieto1409 feel free to have another look. I'd consider it RTM then

Thanks @euronion it does look good to me, I only saw a minor typo in sector.csv but other than that looks great :)

Copy link
Copy Markdown
Member

@martacki martacki left a comment

Choose a reason for hiding this comment

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

thanks @euronion; the under-cool addition seems like a great addition! I like the upgrade 👍

@fneum I guess the latest analysis also covers your request(s) ?

Copy link
Copy Markdown
Member

@fneum fneum left a comment

Choose a reason for hiding this comment

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

Approved in principle! Nice feature, just a few editorial things to clean up. Takes 10 minutes. Then, RTM!


*Thermal characteristics*

Thermal losses in the building thermal mass are modeled using the same standing loss rates as decentralized water tank storage, which provides a reasonable proxy for the thermal inertia of building envelopes. The storage is cyclic, meaning the state of charge at the end of the optimization period must equal that at the beginning.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think the standing losses in a hot water storage are likely much higher than in a building.

@fneum fneum enabled auto-merge (squash) December 2, 2025 07:26
@euronion
Copy link
Copy Markdown
Contributor

euronion commented Dec 2, 2025

Tests are failing because Zenodo retrieval for seawater_temperature is not consistent with the data retrieval from #1675 . will be fixed in open-energy-transition#67

@fneum
Copy link
Copy Markdown
Member

fneum commented Dec 2, 2025

Tests are failing because Zenodo retrieval for seawater_temperature is not consistent with the data retrieval from #1675 . will be fixed in open-energy-transition#67

Good but then it's unrelated to this PR.

@fneum fneum disabled auto-merge December 2, 2025 11:12
@fneum fneum merged commit 2739717 into PyPSA:master Dec 2, 2025
5 of 6 checks passed
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.

5 participants