oprava zbytecneho curtailu A
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-31-evening-push-budget-primary-night-v49"
|
||||
PLANNER_BUILD_TAG = "2026-05-31-ba81-dawn-no-micro-curtail-v51"
|
||||
# Ranní slabá FVE: neaplikovat pv_store ge_pv=0 (jinak curtail při sell < večerní peak).
|
||||
DAWN_LOW_PV_NO_CURTAIL_W = 1500
|
||||
# Mimo evening_push: preferovat bd pro dům místo gi, když buy >> acq (účinná cena importu).
|
||||
@@ -1564,8 +1564,9 @@ def _slot_pv_surplus_w(slot: PlanningSlot) -> float:
|
||||
|
||||
def _battery_export_push_defer_to_pv(slot: PlanningSlot) -> bool:
|
||||
"""
|
||||
Při kladném sell a PV přebytku nevnucovat plný ge_bat push (pre-neg / ranní větve).
|
||||
Exportní cap má pokrýt ge_pv; baterii řeší večerní push a sell<0 okna.
|
||||
Při kladném sell a PV přebytku nevnucovat vývoz z baterie (ge_bat / z_export).
|
||||
Platí pro ranní pre-neg, večerní push i KV1 odpoledne (block_export + fixní tarif):
|
||||
přetok řeší ge_pv / Deye PASSIVE, ne BATTERY_SELL.
|
||||
"""
|
||||
if float(slot.sell_price) < 0.0:
|
||||
return False
|
||||
@@ -2629,6 +2630,11 @@ def solve_dispatch(
|
||||
slots, evening_push_ts
|
||||
)
|
||||
night_self_consume_discourage_ts |= post_evening_push_night_ts
|
||||
battery_export_defer_pv_ts = {
|
||||
t for t in range(T) if _battery_export_push_defer_to_pv(slots[t])
|
||||
}
|
||||
else:
|
||||
battery_export_defer_pv_ts = set()
|
||||
pre_neg_buy_soc_ceiling_wh = _pre_neg_buy_soc_ceiling_wh(
|
||||
slots,
|
||||
first_neg_buy_idx=first_neg_buy_idx,
|
||||
@@ -3249,6 +3255,8 @@ def solve_dispatch(
|
||||
for t_peak in sorted(evening_push_ts):
|
||||
if t_peak not in discharge_export_slots:
|
||||
continue
|
||||
if t_peak in battery_export_defer_pv_ts:
|
||||
continue
|
||||
push_floor_w = _evening_push_battery_export_w(
|
||||
slots[t_peak], battery, grid
|
||||
)
|
||||
@@ -3256,6 +3264,17 @@ def solve_dispatch(
|
||||
prob += z_export[t_peak] == 1
|
||||
prob += ge_bat[t_peak] >= push_floor_w
|
||||
prob += soc[t_peak] >= float(discharge_floor_wh)
|
||||
for t_pv in sorted(battery_export_defer_pv_ts):
|
||||
if t_pv in evening_push_ts:
|
||||
continue
|
||||
if t_pv in morning_pre_neg_export_ts:
|
||||
continue
|
||||
if t_pv in pre_neg_buy_discharge_ts:
|
||||
continue
|
||||
if t_pv in pre_neg_buy_empty_ts:
|
||||
continue
|
||||
prob += ge_bat[t_pv] == 0
|
||||
prob += z_export[t_pv] == 0
|
||||
# Ostatní profitable sloty: měkká shortfall penalizace (ne večerní push).
|
||||
if (
|
||||
last_pos_sell_pre_neg_buy is not None
|
||||
@@ -3738,35 +3757,56 @@ def solve_dispatch(
|
||||
fixed_pre_neg_pv_export = (
|
||||
purchase_fixed_pre
|
||||
and sell_t >= 0.0
|
||||
and pv_surplus_w > 500.0
|
||||
and pv_surplus_w > NIGHT_EXPORT_PV_SUNRISE_SURPLUS_W
|
||||
and (
|
||||
first_neg_sell_idx is None
|
||||
or t < first_neg_sell_idx
|
||||
)
|
||||
)
|
||||
skip_pv_store_block = (
|
||||
float(s.pv_b_forecast_w) > 0
|
||||
fixed_block_pv_surplus_export = (
|
||||
purchase_fixed_pre
|
||||
and bool(getattr(grid, "block_export_on_negative_sell", False))
|
||||
and sell_t >= 0.0
|
||||
and pv_surplus_w > NIGHT_EXPORT_PV_SUNRISE_SURPLUS_W
|
||||
)
|
||||
# BA81: ge_pv≤pv_b jen při významném poli A — při úsvitu nechat Deye bez plného curtail A.
|
||||
fixed_mi_low_pv_surplus_export = (
|
||||
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 buy_t >= 0.0
|
||||
and not purchase_fixed_pre
|
||||
and (
|
||||
first_neg_buy_idx is None
|
||||
or t < first_neg_buy_idx
|
||||
and sell_t >= 0.0
|
||||
and int(s.pv_a_forecast_w) < DAWN_LOW_PV_NO_CURTAIL_W
|
||||
and pv_surplus_w > 0.0
|
||||
)
|
||||
skip_pv_store_block = (
|
||||
(
|
||||
float(s.pv_b_forecast_w) > 0
|
||||
and not getattr(grid, "block_export_on_negative_sell", False)
|
||||
and sell_t < 0
|
||||
and buy_t >= 0.0
|
||||
and not purchase_fixed_pre
|
||||
and (
|
||||
first_neg_buy_idx is None
|
||||
or t < first_neg_buy_idx
|
||||
)
|
||||
)
|
||||
) or (
|
||||
# Spot: při sell>=0 neblokovat ge_pv (export vs bc_pv; večerní peak = ge_bat).
|
||||
not purchase_fixed_pre
|
||||
and sell_t >= 0
|
||||
and pv_surplus_w > 500
|
||||
) 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).
|
||||
or (
|
||||
# Spot: při sell>=0 neblokovat ge_pv (export vs bc_pv; večerní peak = ge_bat).
|
||||
not purchase_fixed_pre
|
||||
and sell_t >= 0
|
||||
and pv_surplus_w > NIGHT_EXPORT_PV_SUNRISE_SURPLUS_W
|
||||
)
|
||||
or fixed_pre_neg_pv_export
|
||||
or fixed_block_pv_surplus_export
|
||||
or fixed_mi_low_pv_surplus_export
|
||||
)
|
||||
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
|
||||
and int(s.pv_a_forecast_w) >= DAWN_LOW_PV_NO_CURTAIL_W
|
||||
)
|
||||
if fixed_pre_neg_pv_export:
|
||||
prob += ge_pv[t] <= max(0.0, pv_surplus_w)
|
||||
|
||||
Reference in New Issue
Block a user