Skip to content

[BUG] OPF time_elapsed computed with .seconds and int() — sub-hourly runs silently decouple storage power from energy #693

Description

@joda9

Where

edisgo/io/powermodels_io.py (in to_powermodels):

pm["time_elapsed"] = int(
    (psa_net.snapshots[1] - psa_net.snapshots[0]).seconds / 3600
)  # length of timesteps in hours

This single global value drives all inter-timestep couplings in the Julia OPF (battery,
heat storage, DSM energy balances, EV charging energy).

Three independent defects

  1. .seconds instead of .total_seconds().seconds is the seconds component of the
    Timedelta (0–86399), not its total duration. A gap of exactly 1 day yields 0; a gap of
    25 h yields 1 h. Silently wrong.
  2. int(...) truncation — 15-min resolution: int(900/3600) = int(0.25) = 0. With
    time_elapsed = 0 the storage coupling se₂ − se₁ == −0·ps₂ degenerates to 0 == 0 for
    any ps: power and energy are completely decoupled. The battery becomes an
    inexhaustible storage with no energy accounting (results look plausible — power bounds are
    respected — but are physically meaningless). With flexible charging points the model becomes
    infeasible instead (cpe₂ == cpe₁ is forced while the flexibility-band midpoint moves).
    Real 15-min runs have been executed and were affected by this.
  3. Only the first snapshot gap is used, globally — non-equidistant time indices are
    silently mis-scaled for every step after the first.

Suggested fix

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: opfOptimal power flow / Julia side (eDisGo_OPF.jl, powermodels_io)bugcorrectnessSilently produces wrong numeric results (no crash) — high-value to fixpriority: high

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions