uprava solver gneport cutoff u ba81
This commit is contained in:
1
.idea/data_source_mapping.xml
generated
1
.idea/data_source_mapping.xml
generated
@@ -2,6 +2,7 @@
|
||||
<project version="4">
|
||||
<component name="DataSourcePerFileMappings">
|
||||
<file url="file://$PROJECT_DIR$/../ems-cursor-db-pracovni/debug-forecast.sql" value="26ebef46-ff23-475b-8adc-082723263a02" />
|
||||
<file url="file://$PROJECT_DIR$/../ems-cursor-db-pracovni/naplneni-base-line-ba81.sql" value="26ebef46-ff23-475b-8adc-082723263a02" />
|
||||
<file url="file://$PROJECT_DIR$/../ems-cursor-db-pracovni/porovnani-view-status.sql" value="26ebef46-ff23-475b-8adc-082723263a02" />
|
||||
<file url="file://$PROJECT_DIR$/db/migration/V009__postgrest_roles.sql" value="26ebef46-ff23-475b-8adc-082723263a02" />
|
||||
<file url="file://$PROJECT_DIR$/db/routines/R__079_fn_forecast_pv_slots_range_corrected.sql" value="26ebef46-ff23-475b-8adc-082723263a02" />
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
| Mode | Solver constraints | Deye fyzický režim | Baterie |
|
||||
|------|-------------------|-------------------|---------|
|
||||
| AUTO | žádné | PASSIVE/SELL/CHARGE dle plánu | dle plánu |
|
||||
| SELF_SUSTAIN | no_export, min_import | vždy PASSIVE | plné limity |
|
||||
| SELF_SUSTAIN | min_import; export jen jako nouzový ventil (silně penalizovaný) | vždy PASSIVE | plné limity |
|
||||
| CHARGE_CHEAP | no_export, no_discharge | CHARGE | nabíjení max |
|
||||
| PRESERVE | no_charge, no_discharge | PASSIVE | lock (0/0) |
|
||||
| MANUAL | solver neběží | EMS nezapisuje | — |
|
||||
|
||||
@@ -267,12 +267,17 @@ kde:
|
||||
- `batt_charge_cap_w` = min(`battery.max_charge_power_w`, \((soc_{max}-soc)_{wh} / 0.25h\)) – tj. výkonově omezené a SoC-headroom omezené
|
||||
- `flexible_load_w` = plánované EV/TČ setpointy v daném slotu (pokud jsou připojené / povolené)
|
||||
|
||||
#### Doporučená implementace v EMS (aby se to chovalo správně)
|
||||
#### Implementace v EMS (aktuální chování)
|
||||
|
||||
- **Správně (v solveru / plánu)**: řešit cut-off přímo v LP binární proměnnou `z_gen_cutoff[t]` (0/1), která modeluje, zda je GEN port odpojen.
|
||||
- Cut-off se řeší přímo v LP binární proměnnou `z_gen_cutoff[t]` (0/1), která modeluje, zda je GEN port odpojen.
|
||||
- Efektivní výkon z GEN do bilance: `pv_b_effective[t] = pv_b_forecast_w * (1 - z_gen_cutoff[t])`
|
||||
- Solver nechá GEN připojený vždy, když je výkon užitečný (sníží import / nabije baterii / pokryje zátěž).
|
||||
- Při `sell_price < 0` a zároveň hrozícím přebytku (ge je zakázané) solver může zvolit `z_gen_cutoff[t]=1` (cut-off) jako poslední možnost.
|
||||
- `z_gen_cutoff[t]` je **vůbec povolené jen** v režimech/politikách, kde to dává smysl:
|
||||
- `SELF_SUSTAIN`
|
||||
- sloty s `sell_price < 0` („BLOCK_EXPORT“ okna)
|
||||
- (případně) explicitní `no_export` politika, pokud je v kontextu dostupná
|
||||
Mimo tyto případy je `z_gen_cutoff[t]` vynucené na `0`.
|
||||
- Cut-off je v účelové funkci **penalizované** (za „zahozenou“ GEN výrobu), aby se zapínalo jen jako poslední možnost.
|
||||
- Výstup se ukládá do `planning_interval.deye_gen_cutoff_enabled` (nullable) a exporter pak jen provede reg 179.
|
||||
|
||||
**Scope / bezpečnost:** proměnná i flag existují jen na lokalitách, kde je zapnutý `asset_inverter.deye_gen_microinverter_cutoff_enabled` (tj. kde je GEN port s mikroinvertory reálně zapojen). Jinde se nic neřeší ani nezobrazuje.
|
||||
|
||||
Reference in New Issue
Block a user