uprava solver gneport cutoff u ba81
This commit is contained in:
@@ -551,6 +551,18 @@ def solve_dispatch(
|
||||
else None
|
||||
)
|
||||
|
||||
om = (operating_mode or "AUTO").strip().upper()
|
||||
# SELF_SUSTAIN dřív vynucoval ge[t] == 0, což umí udělat MILP infeasible v okamžiku, kdy:
|
||||
# - baterie je na max SoC (nelze nabíjet),
|
||||
# - PV pole B není curtailable,
|
||||
# - a pv_b_forecast_w > load_baseline_w (typicky po ručním snížení baseline).
|
||||
# Export v SELF_SUSTAIN proto povolíme jako nouzový ventil, ale silně penalizujeme,
|
||||
# aby k němu docházelo jen když už neexistuje jiné fyzikálně možné řešení.
|
||||
SELF_SUSTAIN_EXPORT_PENALTY_CZK_KWH = 100.0
|
||||
# Penalizace vypnutí GEN portu (mikroinvertory): preferujeme nechat zapnuto a vypnout jen když
|
||||
# by to jinak vedlo k nežádoucímu exportu / infeasible řešení.
|
||||
GEN_CUTOFF_PENALTY_CZK_KWH = 5.0
|
||||
|
||||
# EV proměnné per vozidlo
|
||||
ev_direct = [[pulp.LpVariable(f"evd_{e}_{t}", 0,
|
||||
min(vehicles[e].max_charge_power_w, grid.max_import_power_w))
|
||||
@@ -582,6 +594,16 @@ def solve_dispatch(
|
||||
pulp.lpSum(
|
||||
gi[t] * slots[t].buy_price * INTERVAL_H / 1000
|
||||
- ge[t] * slots[t].sell_price * INTERVAL_H / 1000
|
||||
+ (
|
||||
ge[t] * SELF_SUSTAIN_EXPORT_PENALTY_CZK_KWH * INTERVAL_H / 1000
|
||||
if om == "SELF_SUSTAIN"
|
||||
else 0
|
||||
)
|
||||
+ (
|
||||
(slots[t].pv_b_forecast_w * z_gen_cutoff[t]) * GEN_CUTOFF_PENALTY_CZK_KWH * INTERVAL_H / 1000
|
||||
if z_gen_cutoff is not None
|
||||
else 0
|
||||
)
|
||||
+ gi_over[t] * IMPORT_OVER_BREAKER_PENALTY_CZK_KWH * INTERVAL_H / 1000
|
||||
+ 0.5 * (bc[t] + bd[t]) * degradation_cost_effective * INTERVAL_H / 1000
|
||||
+ pulp.lpSum(
|
||||
@@ -638,10 +660,16 @@ def solve_dispatch(
|
||||
# ev_via_bat kryto z discharge
|
||||
prob += pulp.lpSum(ev_via_bat[e][t] for e in range(EV)) <= bd[t]
|
||||
|
||||
# Záporná prodejní cena: export nepovinně zakazovat — účelovka už obsahuje -ge*sell
|
||||
# (záporné sell zvyšuje náklad exportu). GEN cut-off držíme vypnutý (jinak by z_gen_cutoff
|
||||
# uměle nulovalo forecast pole B).
|
||||
if z_gen_cutoff is not None:
|
||||
# GEN port cut-off chceme vůbec připustit jen v režimech/politikách, kde má smysl:
|
||||
# - SELF_SUSTAIN (no-export intent; typicky ge=0, takže cut-off je bezpečnostní ventil),
|
||||
# - BLOCK_EXPORT okna (v projektu reprezentované sloty se sell_price < 0),
|
||||
# - případně explicitní no_export politika (pokud bude v kontextu dostupná).
|
||||
allow_gen_cutoff = (
|
||||
om == "SELF_SUSTAIN"
|
||||
or float(s.sell_price) < 0
|
||||
or bool(getattr(grid, "no_export", False))
|
||||
)
|
||||
if z_gen_cutoff is not None and not allow_gen_cutoff:
|
||||
prob += z_gen_cutoff[t] == 0
|
||||
|
||||
# Záporná nákupní cena → cap import (baseline domu + akumulace + řízené zátěže)
|
||||
@@ -703,10 +731,8 @@ def solve_dispatch(
|
||||
else:
|
||||
prob += ev_direct[e][t] + ev_via_bat[e][t] <= vehicles[e].max_charge_power_w
|
||||
|
||||
om = (operating_mode or "AUTO").strip().upper()
|
||||
if om == "SELF_SUSTAIN":
|
||||
for t in range(T):
|
||||
prob += ge[t] == 0
|
||||
prob += gi[t] <= slots[t].load_baseline_w
|
||||
elif om == "PRESERVE":
|
||||
for t in range(T):
|
||||
|
||||
Reference in New Issue
Block a user