Version Checks (indicate both or one)
Issue Description
In PyPSA versions ≥ 1.0.0, generators and links with NaN ramp_limit_up/down will receive ramp constraints once ramping is enabled for any other asset of the same component.
In this situation, NaN ramp limits appear to be effectively interpreted as zero, leading to constraints such as:
As a result, assets that are intended to be fully flexible (e.g. load-shedding or slack generators) are prevented from changing output between snapshots, which can cause infeasibilities.
Reproducible Example
"""Simple example network with one generator having ramp limits and another without"""
import pandas as pd
import pypsa
n = pypsa.Network()
n.set_snapshots(pd.date_range("2025-01-01", periods=2, freq="h"))
n.add(class_name="Bus", name="bus")
n.add(
class_name="Load",
name="load",
bus="bus",
p_set=pd.Series([0.0, 50.0], index=n.snapshots), # sudden load increase
)
# Small generator with ramp limits
n.add(
class_name="Generator",
name="generator",
bus="bus",
p_nom=10,
ramp_limit_up=0.5,
ramp_limit_down=0.5,
marginal_cost=0,
)
# Load shedding generator without ramp limits
n.add(
class_name="Generator",
name="load_shedding",
bus="bus",
p_nom=1000,
marginal_cost=10,
)
n.optimize(solver_name="highs")
print(n.model.constraints["Generator-fix-p-ramp_limit_up"])
Expected Behavior
Here is what the optimization results currently look like:
WARNING:pypsa.consistency:The following buses have carriers which are not defined:
Index(['bus'], dtype='object', name='name')
INFO:linopy.model: Solve problem using Highs solver
INFO:linopy.io: Writing time: 0.02s
Running HiGHS 1.12.0 (git hash: 755a8e0): Copyright (c) 2025 HiGHS under MIT licence terms
LP linopy-problem-b0a5luci has 14 rows; 4 cols; 20 nonzeros
Coefficient ranges:
Matrix [1e+00, 1e+00]
Cost [1e+01, 1e+01]
Bound [0e+00, 0e+00]
RHS [5e+00, 1e+03]
Presolving model
4 rows, 1 cols, 4 nonzeros 0s
Problem status detected on presolve: Infeasible
Model name : linopy-problem-b0a5luci
Model status : Infeasible
Objective value : 0.0000000000e+00
HiGHS run time : 0.00
WARNING:linopy.constants:Optimization potentially failed:
Status: warning
Termination condition: infeasible
Solution: 0 primals, 0 duals
Objective: nan
Solver model: available
Solver message: Infeasible
Constraint `Generator-fix-p-ramp_limit_up` [snapshot: 1, name: 2]:
------------------------------------------------------------------
[2025-01-01 01:00:00, generator]: +1 Generator-p[2025-01-01 01:00:00, generator] - 1 Generator-p[2025-01-01 00:00:00, generator] ≤ 5.0
[2025-01-01 01:00:00, load_shedding]: +1 Generator-p[2025-01-01 01:00:00, load_shedding] - 1 Generator-p[2025-01-01 00:00:00, load_shedding] ≤ -0.0
This clearly shows the infeasibility and indicates that a zero ramp limit is being imposed on the load-shedding generator, preventing it from increasing output to cover the load.
The expected behavior is that ramp constraints are ignored for the load-shedding generator (since no ramp limits are specified for it), which would result in a feasible solution.
Installed Versions
Details
This bug happens in pypsa>=1.0.0
Version Checks (indicate both or one)
I have confirmed this bug exists on the lastest release of PyPSA.
I have confirmed this bug exists on the current
masterbranch of PyPSA.Issue Description
In PyPSA versions ≥ 1.0.0, generators and links with NaN ramp_limit_up/down will receive ramp constraints once ramping is enabled for any other asset of the same component.
In this situation, NaN ramp limits appear to be effectively interpreted as zero, leading to constraints such as:
As a result, assets that are intended to be fully flexible (e.g. load-shedding or slack generators) are prevented from changing output between snapshots, which can cause infeasibilities.
Reproducible Example
Expected Behavior
Here is what the optimization results currently look like:
This clearly shows the infeasibility and indicates that a zero ramp limit is being imposed on the load-shedding generator, preventing it from increasing output to cover the load.
The expected behavior is that ramp constraints are ignored for the load-shedding generator (since no ramp limits are specified for it), which would result in a feasible solution.
Installed Versions
Details
This bug happens in pypsa>=1.0.0