Skip to content

Battery discharge cannot be paced for home support (LOAD_SUPPORT dumps greedily on deep evening peaks) #147

Description

@johanzander

Summary

On high-consumption days with a deep/long evening peak, the optimizer plans to pace the battery — discharge little early and reserve charge for the most expensive hours — but the control can't execute it. LOAD_SUPPORT → load_first + discharge_rate 100% makes the inverter greedily cover the full home deficit every period, draining the battery early and leaving nothing for the priciest hours, which are then bought from the grid.

This is the same class as the solar over-crediting bug (#145), on the discharge side: the optimizer plans a partial/paced action the inverter mode cannot deliver (the mode is all-or-nothing home coverage). Surfaced by the new R==P plan-faithfulness check (the realized inverter execution diverges from the plan).

Evidence — synthetic_consumption_high_no_solar (max_discharge 6 kW)

 p  intent        home |  PLAN disch/import/SoE |  REAL disch/import/SoE
p15 LOAD_SUPPORT   5.0  |  0.40 / 4.60 / 28.7    |  5.00 / 0.00 / 18.4   plan paces; hardware dumps
p16 LOAD_SUPPORT   7.0  |  5.40 / 1.60 / 23.1    |  6.00 / 1.00 / 12.1
p18 LOAD_SUPPORT  10.0  |  6.00 / 4.00 / 10.4    |  2.65 / 7.35 /  3.0   hardware hits floor early
p19 LOAD_SUPPORT   9.0  |  6.00 / 3.00 /  4.1    |  0.00 / 9.00 /  3.0   empty → imports 9 kWh at peak

The plan keeps SoE high into the deep peak (p18–20); the hardware empties by p18 and imports the most expensive hours.

Effect

Real money (not just reporting): on these day-shapes the user pays ~3–4% more than the plan claims (e.g. this scenario R−P = +4.88 SEK on P≈129), and the dashboard over-states savings by the same amount. Solar days and normal-load days are unaffected (R ≈ P). Pre-existing — old code had it too; only now measurable via the simulator (PR #144/#146).

Affected test scenarios (R−P > 0.5 SEK), currently xfail in test_scenarios.py pending this:
synthetic_consumption_high_no_solar (+4.88), synthetic_seasonal_winter (+2.03), synthetic_consumption_ev_charging (+2.03), historical_2025_01_12_evening_peak_no_solar (+0.96).

Fix direction (needs design)

To pace, the optimizer needs a way to limit discharge below the full home deficit — e.g. scale discharge_rate for LOAD_SUPPORT from the planned power (mirroring EXPORT_ARBITRAGE), or a per-period discharge cap / reserve-SoC.

Tension to resolve: unlike solar storage, home consumption is also a forecast, and full-deficit coverage (100%) is the forecast-robust choice — throttling discharge to a planned amount under-covers home if actual consumption exceeds the forecast. So a naive discharge-rate scale would trade pacing for robustness. A reserve-SoC / "don't discharge below X this period" formulation may pace without sacrificing coverage robustness. Needs design before implementing.

Refs: PR #146 (binary surplus fix), #145 (the analogous solar bug), PR #144 (simulator).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bot-analyzedTriage bot has processed this issuebugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions