[FEATURE] Aggregating heat pump and resistive heater discards their individual characteristics

Aperta
#751 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
35/100
Tipo di issue
Funzionalità
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
python
Ambito
backend, databases

Direzione di ricerca

Start with aggregate_district_heating_components in edisgo/tools/tools.py and cop_oedb in edisgo/io/timeseries_import.py, then trace constraint_hp_operation and the heatpumps and heat_storage dictionaries in powermodels_io.py. Read how the existing heat balance handles PtH units before changing it. Done means the two units retain their own power, COP, bus and dispatch through the handover and contribute jointly to district heating demand.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

enhancement

Summary

edisgo/tools/tools.py::aggregate_district_heating_components merges the central heat
pump and the central resistive heater of a district heating area into a single load
component. Rated powers are added, a harmonic-mean COP is synthesised, and the resistive
heater is deleted from loads_df, cop_df and heat_demand_df.

The two components have fundamentally different characteristics — a heat pump with a
time-varying COP of ~2-4, and a resistive heater with a COP of ~1. Merging them discards
that distinction and, with it, the possibility of dispatching them optimally. The split
between the two is no longer an outcome of the optimisation; it is fixed by a rule before
the optimiser sees the problem.

What is lost

1. The dispatch decision. The merge hard-codes a merit order: the heat pump runs up to
its rated power, the resistive heater covers the remainder.

el_demand = (heat_demand_df[district_hp] / cop_df[district_hp]).clip(lower=0)
hp_p_set   = loads_df.at[district_hp, "p_set"]
df = pd.concat([
    (el_demand.clip(upper=hp_p_set) / el_demand).fillna(1).to_frame(district_hp),
    ((el_demand - el_demand.clip(upper=hp_p_set)) / el_demand).fillna(0).to_frame(district_rh),
], axis=1)

This is a reasonable heuristic for a cost-minimising dispatch, but it is only a heuristic.
It cannot represent a resistive heater running while the heat pump has headroom — which is
exactly what a system-level optimisation does when electricity is abundant, and what
eTraGo actually produces (see below).

2. The two COP time series. They are collapsed into one synthetic series:

new_cop = 1 / (df / cop_df[district_hps.index]).sum(axis=1)

The harmonic mean is the correct way to preserve total electricity demand for the assumed
split
— but it is only correct for that split. Once the aggregated component exists, no
other split can be evaluated, because the individual COPs are gone.

3. The grid location of each unit. new_p_set is the sum of both rated powers and is
assigned to the heat pump's bus; the resistive heater's load is dropped. Where the two
units sit at different busbars, the electrical load appears entirely at one of them.

4. Both units currently receive a heat-pump COP. timeseries_import.py::cop_oedb
fetches COP per weather cell for every PtH unit, so the resistive heater's cop_df column
holds a heat-pump COP of ~2-4 rather than ~1. The harmonic mean is therefore computed from
a wrong input for one of its two terms. This is a defect in its own right, but it only
becomes visible once the components are treated individually.

eTraGo dispatches them separately

The aggregation assumption is contradicted by the upstream data it is meant to represent.
Grid 30885, area 2544, scenario eGon2035 (results_dg_1606_fullflex_nodg):

carrier p_nom (MW) annual electrical (MWh) hours dispatched
central_heat_pump 0.329 842.4 2750
central_resistive_heater 0.420 441.1 1248

Two distinct dispatch patterns. eGo currently sums them to a single 1283.5 MWh series
(see openego/eGo — companion issue on the interface side), and eDisGo then merges the two
components as well, so the distinction is destroyed twice over.

Where it happens

  • edisgo/tools/tools.py::aggregate_district_heating_components (~line 1124 onwards) —
    the merge, the synthetic COP, and the deletion of the resistive heater.
  • edisgo/io/timeseries_import.py::cop_oedb — assigns a heat-pump COP to resistive
    heaters.

Proposed direction

Keep the heat pump and the resistive heater as separate components throughout, each with
its own p_set, its own COP series (~1 for the resistive heater) and its own bus, and let
the heat balance be satisfied by the two of them jointly rather than by a pre-merged
surrogate. In the Julia OPF this means several PtH units contributing to one district
heating area's heat balance instead of exactly one, which is a change to
constraint_hp_operation and the heatpumps/heat_storage dictionaries built in
powermodels_io.py.

Where eTraGo dispatch is handed down, the per-component electrical time series should be
adopted directly rather than re-derived from an aggregate.

Related

  • Companion issue in openego/eGo: interface.py::central_heat sums central_heat_pump
    and central_resistive_heater into one heat_pump_central_active_power series and one
    heat_pump_central_p_nom scalar. Both sides have to change for the per-component
    information to survive the handover.
  • ISSUE_edisgo_dh_demand_scaling.md — same function, separate defect.
Lingua principale
Python
Stelle
48
Fork
22
Merge medio
1g 8h
PR unite (30g)
37

Preparare l'ambiente

  • Nessun Dockerfile né file Docker Compose
  • Ha un modello di pull request
  • Nessuna guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di openego/eDisGo

Tutte le issue di openego/eDisGo

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.