Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions documentation/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ Infrastructure / Support

Bugfixes
-----------
* Ensure EMS-level flow commitments constrain aggregate device flow [see `issue #2326 <https://github.com/FlexMeasures/flexmeasures/issues/2326>`_]
* Scheduling jobs no longer print ``Job ... made schedule.`` before ``scheduler.compute()`` runs (only after a successful schedule) [see `PR #2342 <https://www.github.com/FlexMeasures/flexmeasures/pull/2342>`_]
* ``flexmeasures add user --roles`` now correctly accepts a comma-separated list of roles (and repeated ``--roles`` options) instead of creating one role whose name contains commas [see `PR #2339 <https://www.github.com/FlexMeasures/flexmeasures/pull/2339>`_]
* Raise a clear ``ValueError`` when a flex-model references a missing sensor ID instead of ``AttributeError: 'NoneType' object has no attribute 'asset_id'`` [see `PR #2343 <https://www.github.com/FlexMeasures/flexmeasures/pull/2343>`_]
Expand Down
4 changes: 2 additions & 2 deletions flexmeasures/data/models/planning/linear_optimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -766,12 +766,12 @@ def ems_flow_commitment_equalities(m, c, j):
return Constraint.Skip

return (
None,
0 if "upwards deviation price" in commitments[c].columns else None,
m.commitment_quantity[c, j]
+ m.commitment_downwards_deviation[c]
+ m.commitment_upwards_deviation[c]
- sum(m.ems_power[d, j] for d in devices),
None,
0 if "downwards deviation price" in commitments[c].columns else None,
)

def device_derivative_equalities(m, d, j):
Expand Down
49 changes: 49 additions & 0 deletions flexmeasures/data/models/planning/tests/test_commitments.py
Original file line number Diff line number Diff line change
Expand Up @@ -1988,6 +1988,55 @@ def test_stock_scoped_commitment_binds_group_stock(named_device):
np.testing.assert_allclose(total_energy, 20.0, atol=1e-6)


def test_ems_flow_commitment_binds_all_devices():
start = pd.Timestamp("2026-01-01T00:00+01")
end = pd.Timestamp("2026-01-01T01:00+01")
resolution = pd.Timedelta("PT1H")
index = initialize_index(start=start, end=end, resolution=resolution)

device_constraints = [
pd.DataFrame(
{
"min": -100.0,
"max": 100.0,
"equals": np.nan,
"derivative min": -10.0,
"derivative max": 10.0,
"derivative equals": np.nan,
"derivative down efficiency": 1.0,
"derivative up efficiency": 1.0,
},
index=index,
)
for _ in range(2)
]
ems_constraints = pd.DataFrame(
{"derivative min": -100.0, "derivative max": 100.0}, index=index
)
commitments = [
FlowCommitment(
name="EMS target",
index=index,
quantity=5,
upwards_deviation_price=10,
downwards_deviation_price=-10,
)
]

planned_power, planned_costs, results, _ = device_scheduler(
device_constraints=device_constraints,
ems_constraints=ems_constraints,
commitments=commitments,
initial_stock=0,
)

assert results.solver.termination_condition == "optimal"
np.testing.assert_allclose(
sum(schedule.iloc[0] for schedule in planned_power), 5.0, atol=1e-6
)
assert planned_costs == pytest.approx(0)


def test_commitment_commodity_does_not_bind_other_commodity_devices():
"""A commitment
listed under the flex-context's `commitments` should only bind devices of its own
Expand Down