Skip to content

bug: _idle_battery_flows zeroes real solar charging when SOE starts below Min SOC floor #295

Description

@johanzander

Summary

_idle_battery_flows (core/bess/dp_battery_algorithm.py) unconditionally zeroes battery_charged/battery_discharged whenever the period's starting SOE is below min_soe_kwh:

# When soe is already below the minimum floor, _state_transition clamps
# next_soe up to min_soe_kwh. That delta is a floor artefact, not solar
# production — treating it as charging would misclassify the period as
# SOLAR_STORAGE even at 2 am with no sun.
if soe < battery_settings.min_soe_kwh:
    return 0.0, 0.0

This comment's premise was true before #233's fix: _state_transition used to fabricate a jump to min_soe_kwh regardless of whether any real charging happened, so the delta genuinely was a floor artefact.

After #233 (PR #294), _state_transition no longer fabricates that jump — an IDLE period starting below the floor with a genuine solar surplus now legitimately raises next_soe by the real amount of solar energy stored. But _idle_battery_flows's guard still zeroes battery_charged unconditionally in this case, so:

  • The real stored solar energy vanishes from the reported EnergyData (battery_charged = 0 instead of the true value)
  • _build_period_data's energy balance then over-counts that surplus as grid_exported (as if it left via the grid) instead of battery_charged
  • Meanwhile, _build_period_data's separate energy_stored = next_soe - soe calculation (used for wear cost / cost basis, lines ~517/602 at the time of fix: don't fabricate SOE jump to Min SOC floor when starting below it #294) has no matching guard, so wear cost and cost basis still reflect the true nonzero delta

Net effect: an internally inconsistent period — energy that was actually stored is reported as exported for ledger purposes, while cost-basis/wear accounting proceeds as if it was stored.

Reproduction shape

Suggested fix

Recompute passive_energy_stored = next_soe - soe unconditionally (dropping the soe < min_soe_kwh guard) now that _state_transition no longer fabricates the delta in this case — the delta is always real energy post-#233, whether soe started above or below the floor.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions