Summary
When running eDisGo standalone (without eTraGo), district heating demand is fully assigned to heat pumps located inside the ding0 grid district — even when the underlying district heating network extends well beyond the grid boundary. As a result, heat pumps inside the grid are required to cover the entire district heating demand, including the parts physically located outside the modeled grid. In real-world dispatch, eTraGo would distribute this demand across multiple supply units (other heat pumps, CHPs, peak boilers) along the broader heating network. Without that coupling, eDisGo produces unrealistic heat pump capacities and load profiles.
Reproduction
- Grid:
ding0_grid_id = 30891 (north of Hamburg)
- Scenario:
eGon2035
- Workflow:
EDisGo(ding0_grid=...)
edisgo.import_heat_pumps(scenario="eGon2035", import_types=["central_heat_pumps"], engine=...)
- Inspect
edisgo.heat_pump.heat_demand_df and the resulting loads_active_power of the central heat pump.
- Observation: a single central heat pump in grid 30891 ends up with a peak active power demand of ~800 MW, far above the installed unit capacity and any plausible local heat sink. The reason is that the entire
egon_district_heating_areas / demand.egon_demandregio_zensus_electricity-derived district heat demand for the heating area linked to that heat pump is fully attributed to the grid, ignoring the geometric overlap between the heating area and the MV grid district.
Expected behavior
Heat demand assigned to heat pumps that supply district heating areas should reflect only the share of the heat demand whose physical heat sinks (buildings, residential/CTS heat consumers) lie inside the ding0 MV grid district — or, more generally, the local share of the heat pump's nominal contribution to that district heating area.
Proposed fix
Add a weighting step when populating heat_pump.heat_demand_df for central_heat_pumps:
- For each district heating area linked to a central heat pump in the grid:
- Determine the geometric intersection of the heating area polygon with the MV grid district polygon (
edisgo.topology.grid_district["geom"]).
- Weight the demand by either:
- the share of heat-demanding buildings/zensus cells of that heating area that fall inside the grid district (preferred, demand-weighted), or
- the share of the heating area's area inside the grid district (geometric fallback).
- Apply the weight to the imported heat demand time series before it is written into
heat_pump.heat_demand_df.
- Optionally also scale the heat pump's nominal capacity (
p_set) by the same factor, so that pre-reinforcement worst-case calculations stay consistent.
This keeps the standalone eDisGo workflow self-contained while removing the most severe over-counting. The "true" allocation across multiple supply units along a district heating network would still require eTraGo, but a geometric/demand-based weighting brings results into a realistic order of magnitude.
Why this matters
Without the fix, downstream steps are systematically biased:
pm_optimize solves an OPF with a load that physically cannot be served locally, leading to non-convergence or absurd dispatch.
reinforce / enhanced_reinforce_grid over-dimensions the grid, sometimes by orders of magnitude, and reports inflated grid expansion costs.
- Comparative studies between grids are not robust, because the bias depends on how much of the linked district heating area extends outside the grid district — which is grid-specific.
Suggested API
A new parameter for import_heat_pumps, e.g.:
edisgo.import_heat_pumps(
scenario="eGon2035",
import_types=["central_heat_pumps"],
engine=db_engine,
weight_district_heating_demand="building_share", # or "area_share" / None
)
with None preserving the current (unweighted) behavior for backwards compatibility.
Summary
When running
eDisGostandalone (withouteTraGo), district heating demand is fully assigned to heat pumps located inside the ding0 grid district — even when the underlying district heating network extends well beyond the grid boundary. As a result, heat pumps inside the grid are required to cover the entire district heating demand, including the parts physically located outside the modeled grid. In real-world dispatch, eTraGo would distribute this demand across multiple supply units (other heat pumps, CHPs, peak boilers) along the broader heating network. Without that coupling, eDisGo produces unrealistic heat pump capacities and load profiles.Reproduction
ding0_grid_id = 30891(north of Hamburg)eGon2035EDisGo(ding0_grid=...)edisgo.import_heat_pumps(scenario="eGon2035", import_types=["central_heat_pumps"], engine=...)edisgo.heat_pump.heat_demand_dfand the resultingloads_active_powerof the central heat pump.egon_district_heating_areas/demand.egon_demandregio_zensus_electricity-derived district heat demand for the heating area linked to that heat pump is fully attributed to the grid, ignoring the geometric overlap between the heating area and the MV grid district.Expected behavior
Heat demand assigned to heat pumps that supply district heating areas should reflect only the share of the heat demand whose physical heat sinks (buildings, residential/CTS heat consumers) lie inside the ding0 MV grid district — or, more generally, the local share of the heat pump's nominal contribution to that district heating area.
Proposed fix
Add a weighting step when populating
heat_pump.heat_demand_dfforcentral_heat_pumps:edisgo.topology.grid_district["geom"]).heat_pump.heat_demand_df.p_set) by the same factor, so that pre-reinforcement worst-case calculations stay consistent.This keeps the standalone eDisGo workflow self-contained while removing the most severe over-counting. The "true" allocation across multiple supply units along a district heating network would still require eTraGo, but a geometric/demand-based weighting brings results into a realistic order of magnitude.
Why this matters
Without the fix, downstream steps are systematically biased:
pm_optimizesolves an OPF with a load that physically cannot be served locally, leading to non-convergence or absurd dispatch.reinforce/enhanced_reinforce_gridover-dimensions the grid, sometimes by orders of magnitude, and reports inflated grid expansion costs.Suggested API
A new parameter for
import_heat_pumps, e.g.:with
Nonepreserving the current (unweighted) behavior for backwards compatibility.