Ramp limits of a fixed modular committable unit scale with p_nom times the number of running modules
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 75/100
Direzione di ricerca
Inizia in pypsa/optimization/constraints.py, in corrispondenza di define_ramp_limit_constraints, intorno alle righe 1036–1038, e confronta le relative righe di rampa con i limiti operativi modulari intorno alle righe 479–501. Esegui il riproduttore fornito con uv run --script mre.py; il lavoro è completato quando le unità modulari fisse ed espandibili rispettano lo stesso limite di rampa e il caso fisso usa la generazione di punta per i 40 MW rimanenti.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
[!NOTE]
This issue was drafted by AI.
Version Checks (indicate both or one)
- I have confirmed this bug exists on the latest release of PyPSA (1.3.0).
- I have confirmed this bug exists on the current
masterbranch of PyPSA (51986084).
Issue Description
For a committable unit with p_nom_mod > 0, status is an integer that counts the running modules. The dispatch rows use p_nom_mod * status. The ramp rows of a fixed (not extendable) modular unit use p_nom * status. With N modules running, the ramp allowance is N times ramp_limit_up * p_nom, so it is N times too loose. The same applies to ramp_limit_start_up, ramp_limit_down and ramp_limit_shut_down.
An extendable modular committable unit uses p_nom_mod * status, which is correct. So the same plant ramps differently when it is written as fixed or as extendable with p_nom_min = p_nom_max.
In the example, the unit has 10 modules of 10 MW and ramp_limit_up = ramp_limit_start_up = 0.1. The ramp from snapshot 0 to 1 must be at most 10 MW. The fixed unit ramps by 50 MW.
Reproducible Example
Run with uv run --script mre.py.
# /// script
# dependencies = ["pypsa @ git+https://github.com/PyPSA/PyPSA@51986084bfb68d38e5b64021649cb339448112cb", "highspy"]
# ///
import pypsa
def solve(extendable: bool) -> None:
n = pypsa.Network()
n.set_snapshots(range(2))
n.add("Bus", "b")
n.add("Load", "l", bus="b", p_set=[50, 100])
n.add("Generator", "peak", bus="b", p_nom=1000, marginal_cost=100)
n.add(
"Generator",
"uc",
bus="b",
committable=True,
p_nom=0 if extendable else 100,
p_nom_extendable=extendable,
p_nom_min=100,
p_nom_max=100,
p_nom_mod=10,
ramp_limit_up=0.1,
ramp_limit_start_up=0.1,
marginal_cost=1,
)
n.optimize(log_to_console=False)
label = "extendable p_nom_min=p_nom_max=100" if extendable else "fixed p_nom=100"
print(f"{label}:")
print(" uc status:", n.generators_t.status["uc"].tolist())
print(" uc p: ", n.generators_t.p["uc"].tolist())
print(" peak p: ", n.generators_t.p["peak"].tolist())
solve(extendable=False)
solve(extendable=True)
Output (stdout, solver log and warnings removed):
fixed p_nom=100:
uc status: [10.0, 10.0]
uc p: [50.0, 100.0]
peak p: [0.0, 0.0]
extendable p_nom_min=p_nom_max=100:
uc status: [10.0, 10.0]
uc p: [50.0, 60.0]
peak p: [0.0, 40.0]
Expected Behavior
Both units give the same result: uc ramps by at most 0.1 * 10 * 10 = 10 MW, and peak covers 40 MW in snapshot 1. This matches the attribute description, "per unit of the nominal power", which also gives 10 MW.
Actual: the fixed unit ramps by 50 MW. Its row allows 0.1 * 100 * 10 = 100 MW.
Cause
On 51986084, in define_ramp_limit_constraints:
pypsa/optimization/constraints.py:1010:is_com_fix = is_com & ~is_com_ext, andis_com_extexcludes modular units. Sois_com_fixholds both fixed modular and extendable modular committables, and both getstatusas the module count (:1045-1050).:1036-1038:p_nomtakes the module sizep_nom_modonly foris_com_ext_mod. A fixed modular unit keepsp_nom.:1082,:1084,:1112,:1114multiplyp_nombystatus,status_prevor their difference.
The operational rows of all modular committables use p_nom_mod * status (:479-501). define_committability_variables_constraints_with_fixed_upper_limit bounds status by p_nom / p_nom_mod (:1948-1949).
Proposed direction
At :1037, use is_com & is_modular instead of is_com_ext_mod, so every modular committable ramps against p_nom_mod.
Related
- #1899 (closed by #1901) fixed the operational bounds of the same fixed modular committable units. The ramp rows were not changed.
- #1007 made committable, extendable and modular units compatible, and added the
p_nom_modcase for extendable units in the ramp rows.
Found while recording PyPSA reference models for energy-models/mathspec#783.
Installed Versions
- pypsa 1.3.0.post1.dev41+g51986084b
- linopy 0.9.1
- highspy 1.15.1
- pandas 3.0.6
- xarray 2026.9.0
- Python 3.13.11
- Lingua principale
- Python
- Stelle
- 2.2k
- Fork
- 709
- Merge medio
- 1g 20h
- PR unite (30g)
- 30
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di PyPSA/PyPSA
-
get_switchable_as_dense ignores order of inds and silently drops unknown namesForse già presa Una pull request collegata a questa issue è aperta o già unita. Apertabreaking components API data validation high priority needs triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
PyPSA/PyPSA#1977 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
documentation optimization
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
PyPSA/PyPSA#1976 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
investments operational realism optimization
Difficoltà 4/5 3-5 giorni Idoneità per principianti 55/100
I maintainer di solito rispondono entro 1 giorno
-
MGA budget with investment periods multiplies the cost statistics by the period weight a second timeApertainvestments optimization workflow
Difficoltà 3/5 1-2 giorni Idoneità per principianti 68/100
I maintainer di solito rispondono entro 1 giorno
-
AC power flow needs triage reliability & uncertainty
Difficoltà 4/5 3-5 giorni Idoneità per principianti 42/100
I maintainer di solito rispondono entro 1 giorno
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
I maintainer di solito rispondono entro 3 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
modelcontextprotocol/python-sdk#3648 ·
I maintainer di solito rispondono entro 1 giorno
-
docs good first issue
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
VenetoStato/giorgio#6 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
I maintainer di solito rispondono entro 1 giorno
-
Claiming namespace ddalusAperta
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 70/100
EclipseFdn/open-vsx.org#13831 ·
I maintainer di solito rispondono entro 1 giorno