[BUG] eDisGo_OPF.jl: SOC and NC models treat the virtual storage branch differently

Aperta
#802 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
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
julia, python
Ambito
databases

Direzione di ricerca

Start with edisgo/opf/eDisGo_OPF.jl/src/form/bf.jl and the constraint_model_current tests in edisgo/opf/eDisGo_OPF.jl/test/form/test_bf.jl. Compare how SOC and NC constrain storage branches, then review the linked context in #753 before choosing a loss model. Done means both formulations model storage losses consistently and the regression test reflects the chosen constraint behavior.

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

Descrizione

area: opf bug correctness priority: medium
Describe the bug

What happens

Each flexible battery is connected to its grid bus through a virtual branch with
a small resistance (r = 0.017 Ω, powermodels_io.py:947-990). The losses
ccm·r on that branch are the battery's loss model, and Python reads the
battery's power from that branch's flow pf "to account for losses"
(powermodels_io.py:374-387).

The branch-current coupling p² + q² (≤ or =) w·ccm is applied differently to this
branch in the two formulations:

  • SOC (method="soc"): the inequality is written for every branch, including the
    virtual storage branch. The storage losses are at least the I²R value.
  • NC (method="nc", and the Ipopt step of the warm start): the equality is
    skipped for storage branches. On the virtual branch, ccm is only limited by
    its bounds, so the storage losses ccm·r are an unconstrained variable between
    0 and ub·r that has nothing to do with the flow. With a loss-minimising
    objective, NC usually makes the battery lossless.

As a result, the SOC model is not a relaxation of the NC model. FUNCTION_COVERAGE.md
reports that the SOC optimum is measurably above the NC optimum. Also,
check_SOC_equality skips storage branches (src/core/solution.jl:27), so a
non-tight cone on the virtual branch goes unnoticed either way.

Where

  • edisgo/opf/eDisGo_OPF.jl/src/form/bf.jl:101-107: SOC, all branches.
  • edisgo/opf/eDisGo_OPF.jl/src/form/bf.jl:128: NC,
    if !(branch["storage"]).
  • edisgo/opf/eDisGo_OPF.jl/src/form/bf.jl:45-57: in the unbounded case
    (versions 1 and 3), only storage branches get an upper bound on ccm.
  • edisgo/opf/eDisGo_OPF.jl/src/core/constraint_template.jl:59: the voltage drop
    equation is skipped for storage branches in both formulations, so neither
    formulation has a voltage variable at the storage bus (src/core/variables.jl:87).
To Reproduce

Test: edisgo/opf/eDisGo_OPF.jl/test/form/test_bf.jl, @testset "constraint_model_current"
→ @testset "SOC and NC cover the same branches". It pins that the sets differ by
the storage branch and marks @test_broken soc_branches == nc_branches.

Expected behavior

Both formulations model the storage losses in the same way, so SOC is a true
relaxation of NC.

Additional context

Impact today

This affects every OPF with flexible storage units (for example home_batteries
in the presets) solved with method="nc". Once the warm start works, it also
affects the Ipopt warm-start step. The default method="soc" keeps the
constraint, so SOC runs model storage losses as intended.

Suggested fix: needs a domain decision first

How should the virtual branch model battery losses? Possible options:

  • (a) Exact I²R losses in NC too. Drop the storage check in the NC method,
    so the virtual branch gets the equality. w[f_bus] exists, because f_bus is
    the grid bus. This adds one non-convex equality per battery and time step.
  • (b) Use the cone inequality for the virtual branch in both models. In NC,
    write the convex inequality p² + q² ≤ w·ccm for storage branches instead of
    skipping them. This keeps the NC model's non-convexity limited to real lines,
    and the storage losses stay at least I²R in both models.
  • (c) Drop the virtual branch as loss model. Skip storage branches in SOC as
    well, and model the losses some other way, for example through the
    charge/discharge efficiencies. These are read but ignored today: see
    constraint_store_state_initial / constraint_store_state and
    test/core/test_constraint.jl, @testset "storage ignores energy, efficiencies and p_loss".

This should be decided together with #753, which tracks the mismatch between
eDisGo's and eTraGo's battery loss models and the HV requirement using ps
instead of the virtual branch flow. The @test_broken only requires the same
branch set in both models, so it fits (a) and (c). For (b), the test has to be
changed to compare the constraint type instead.

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.