dalsi oprava
This commit is contained in:
@@ -71,7 +71,7 @@ NEG_BUY_CHARGE_SHORTFALL_PENALTY_CZK_KWH = 100.0
|
||||
PRE_NEG_CHARGE_PENALTY_CZK_KWH = 400.0
|
||||
PRE_NEG_BATT_EXPORT_SHORTFALL_PENALTY_CZK_KWH = 80.0
|
||||
PRE_NEG_BATT_EXPORT_MIN_SELL_CZK_KWH = 1.0
|
||||
PLANNER_BUILD_TAG = "2026-05-28-neg-prep-window-v36f"
|
||||
PLANNER_BUILD_TAG = "2026-05-28-neg-prep-window-v36g"
|
||||
# Po t_detach v prep: necpát PV do bat (měkké; tvrdý hold přes soc_target z rampy).
|
||||
NEG_SELL_POST_DETACH_BCPV_DISCOURAGE_CZK_KWH = 250.0
|
||||
# Večer před neg dnem: výboj do sítě (měkký shortfall na ge_bat).
|
||||
@@ -1221,6 +1221,20 @@ def _pre_neg_pv_export_slot_indices(
|
||||
return out
|
||||
|
||||
|
||||
def _discharge_before_first_neg_sell_ts(
|
||||
slots: list[PlanningSlot],
|
||||
first_neg_sell_idx: int | None,
|
||||
) -> set[int]:
|
||||
"""Všechny kladné-sell sloty před 1. sell<0 (funguje i v rolling bez D−1 večera v horizontu)."""
|
||||
if first_neg_sell_idx is None or first_neg_sell_idx <= 0:
|
||||
return set()
|
||||
return {
|
||||
t
|
||||
for t in range(first_neg_sell_idx)
|
||||
if float(slots[t].sell_price) >= 0.0
|
||||
}
|
||||
|
||||
|
||||
def _evening_discharge_before_neg_day_ts(
|
||||
slots: list[PlanningSlot],
|
||||
neg_sell_day_meta: dict[str, Any],
|
||||
@@ -1257,8 +1271,9 @@ def _neg_evening_reserve_soc_anchors(
|
||||
battery: Any,
|
||||
) -> list[tuple[int, float]]:
|
||||
"""
|
||||
Kotva SoC ≤ reserve_soc na konci večera D−1 (typ. 23:45) před pražským dnem D s sell<0.
|
||||
Ranní slot před 1. sell<0 nekotvíme — koliduje s prep rampou v neg okně.
|
||||
Kotvy SoC ≤ reserve_soc před neg oknem:
|
||||
- večer D−1 (23:45) pokud je v horizontu,
|
||||
- slot těsně před 1. sell<0 (rolling: ráno bez včerejška v okně).
|
||||
"""
|
||||
from datetime import timedelta
|
||||
|
||||
@@ -1287,6 +1302,14 @@ def _neg_evening_reserve_soc_anchors(
|
||||
if t_eve not in seen:
|
||||
out.append((t_eve, reserve_wh))
|
||||
seen.add(t_eve)
|
||||
if first_neg > 0:
|
||||
t_pre = first_neg - 1
|
||||
if (
|
||||
t_pre not in seen
|
||||
and float(slots[t_pre].sell_price) >= 0.0
|
||||
):
|
||||
out.append((t_pre, reserve_wh))
|
||||
seen.add(t_pre)
|
||||
return out
|
||||
|
||||
|
||||
@@ -2112,6 +2135,10 @@ def solve_dispatch(
|
||||
slots,
|
||||
neg_sell_day_meta,
|
||||
)
|
||||
neg_evening_before_neg_ts |= _discharge_before_first_neg_sell_ts(
|
||||
slots,
|
||||
first_neg_sell_idx,
|
||||
)
|
||||
neg_evening_reserve_anchors = _neg_evening_reserve_soc_anchors(
|
||||
slots,
|
||||
neg_sell_day_meta,
|
||||
@@ -3297,6 +3324,15 @@ def solve_dispatch(
|
||||
# FVE export před sell<0 jen pokud forecast v sell<0 okně pokryje dobítí (v33).
|
||||
allow_pre_neg_pv_export = t in pre_neg_pv_export_ts
|
||||
pv_store_val = _pv_store_value_czk_kwh(s, min_spread)
|
||||
fixed_pre_neg_pv_export = (
|
||||
purchase_fixed_pre
|
||||
and sell_t >= 0.0
|
||||
and pv_surplus_w > 500.0
|
||||
and (
|
||||
first_neg_sell_idx is None
|
||||
or t < first_neg_sell_idx
|
||||
)
|
||||
)
|
||||
skip_pv_store_block = (
|
||||
float(s.pv_b_forecast_w) > 0
|
||||
and not getattr(grid, "block_export_on_negative_sell", False)
|
||||
@@ -3312,25 +3348,18 @@ def solve_dispatch(
|
||||
not purchase_fixed_pre
|
||||
and sell_t >= 0
|
||||
and pv_surplus_w > 500
|
||||
) or (
|
||||
# Fixed (BA81/KV1): před prvním sell<0 a sell≥0 neblokovat ge_pv — export A+B do site,
|
||||
# ne curtail (fixed_pv_b_export_cap pokrývá jen MI / pole B).
|
||||
purchase_fixed_pre
|
||||
and sell_t >= 0.0
|
||||
and pv_surplus_w > 500.0
|
||||
and (
|
||||
first_neg_sell_idx is None
|
||||
or t < first_neg_sell_idx
|
||||
)
|
||||
)
|
||||
# BA81: export pole B jen při kladném sell (po sell<0 jinak ge==0 výše).
|
||||
) or fixed_pre_neg_pv_export
|
||||
# BA81: export pole B jen při kladném sell mimo pre-neg okno (jinak jen ge_pv≤pv_b → curtail A).
|
||||
fixed_pv_b_export_cap = (
|
||||
purchase_fixed_pre
|
||||
and float(s.pv_b_forecast_w) > 0
|
||||
and not getattr(grid, "block_export_on_negative_sell", False)
|
||||
and sell_t >= 0
|
||||
and not fixed_pre_neg_pv_export
|
||||
)
|
||||
if fixed_pv_b_export_cap:
|
||||
if fixed_pre_neg_pv_export:
|
||||
prob += ge_pv[t] <= max(0.0, pv_surplus_w)
|
||||
elif fixed_pv_b_export_cap:
|
||||
if z_gen_cutoff is not None:
|
||||
prob += ge_pv[t] <= float(s.pv_b_forecast_w) * (1 - z_gen_cutoff[t])
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user