Fix fixu gri charge
All checks were successful
CI and deploy / migration-check (push) Successful in 3s
CI and deploy / deploy (push) Successful in 26s

This commit is contained in:
Dusan Vojacek
2026-04-19 14:30:31 +02:00
parent 0814b1d8e8
commit dc0e37e580
2 changed files with 39 additions and 15 deletions

View File

@@ -163,12 +163,14 @@ def _select_charge_slots(
Logika:
1) Sloty s PV-surplus (pv_a + pv_b > load_baseline) jsou vždy zahrnuty
jde o „zdarma“ nabíjení z FVE, nemá smysl ho zakazovat.
2) Zbývající energetický rozpočet (cíl = charge_buf × (soc_max current_soc),
snížený o očekávaný přínos z PV-surplus slotů) se doplní nejlevnějšími sloty
podle buy_price (nákupní cena ze sítě).
3) Per-slot kapacita přírůstku SoC = max_charge_power × η × 15 min (plný výkon,
ne limitovaný aktuálním PV-surplus výkonem).
nabíjení z FVE je „zdarma“, solver ho musí mít povolené. Tyto sloty se
NEzapočítávají do grid rozpočtu (v dlouhém horizontu by přetekly target).
2) Nezávisle na bodu 1 se vybere top-N **grid** slotů seřazených podle
`buy_price` ASC tak, aby pokryly `charge_buf × (soc_max current_soc)`.
Tím dostane solver k dispozici přístup k nejlevnějšímu nákupu ze sítě,
i když PV v daném slotu spotřebu nepokrývá.
3) Per-slot kapacita přírůstku SoC = max_charge_power × η × 15 min (plný
výkon, ne limitovaný aktuálním PV-surplus výkonem).
Vrací množinu indexů povolených pro `bc[t] > 0` v MILP. Prázdná množina = žádné
restrikce. `charge_slot_buffer <= 0` v DB ⇒ všechny sloty povoleny.
@@ -186,17 +188,13 @@ def _select_charge_slots(
per_slot_full_wh = max_p_w * eta * INTERVAL_H
selected: set[int] = set()
pv_budget_wh = 0.0
for t, s in enumerate(slots):
pv_surplus_w = max(0, s.pv_a_forecast_w + s.pv_b_forecast_w - s.load_baseline_w)
if pv_surplus_w <= 0:
continue
selected.add(t)
pv_budget_wh += min(float(pv_surplus_w), max_p_w) * eta * INTERVAL_H
if pv_surplus_w > 0:
selected.add(t)
target_wh = energy_to_fill * charge_buf
remaining_wh = max(0.0, target_wh - pv_budget_wh)
if remaining_wh <= 0 or per_slot_full_wh <= 0:
grid_target_wh = energy_to_fill * charge_buf
if grid_target_wh <= 0 or per_slot_full_wh <= 0:
return selected
grid_candidates = [
@@ -206,7 +204,7 @@ def _select_charge_slots(
cumulative = 0.0
for t, _price in grid_candidates:
if cumulative >= remaining_wh:
if cumulative >= grid_target_wh:
break
selected.add(t)
cumulative += per_slot_full_wh