Skip to content

S2: plan the declared leakage as part of the usage - #289

Open
Flix6x wants to merge 7 commits into
feat/s2-usage-correctionfrom
feat/s2-leakage-as-usage
Open

Flix6x wants to merge 7 commits into
feat/s2-usage-correctionfrom
feat/s2-leakage-as-usage

Conversation

@Flix6x

@Flix6x Flix6x commented Nov 9, 2026

Copy link
Copy Markdown
Member

Stacked on #286 (base feat/s2-usage-correction). Merge #286 first.

Follows up on a review comment on #283: "If S2 states a rate, shouldn't this then be better modelled as an extra component in the soc-usage list?"

Why

S2 states leakage as a rate per fill-level range, in fill-level units per second. FRBCSimple planned it as a storage-efficiency, which FlexMeasures takes as a share of the stock. So the plan had the storage leak in proportion to how full it was, which was exact at one fill level only, and S2 does not say leakage is proportional.

What

  • Leakage as usage. The leakage rate of the fill-level range the storage starts in is added to soc-usage, constant over the schedule window, and sent with the request. No storage-efficiency is sent any more.
  • With a usage correction (feat(FRBC): correct a usage forecast no plan can absorb, instead of clipping it #286), the correction's limits and the stock's usage cover the forecast and the leakage together. An empty storage cannot give its leakage either, so the correction can take that away like any other forced usage.
  • Without a correction, the forecast and the leakage are added up first and then clipped at zero, as the forecast alone was.
  • Recorded as a rate. The leakage sensor now records the rate itself, in the fill-rate unit, over the window, so what the resource manager declares can still be seen next to the schedule. A failed recording no longer blocks the plan, since the leakage goes with the request. The site sensor is now called leakage (kWh/s) instead of storage efficiency (%), in FRBC_SITE_SENSORS and the example server.
  • Older servers. Only a usage given with the request can carry the leakage, which FlexMeasures supports from v0.23.0. An older server is planned without leakage, and this is logged.
  • Correction price. Leakage planned as a usage drains the same whatever the stock, so the storage term of the correction price's bound is now 1.

Caveats

  • A flat rate keeps draining an empty storage, where physical leakage stops. That is the same situation as a usage forecast the storage cannot absorb, which the usage correction handles.
  • The rate depends on the fill-level range, and the plan moves the fill level. With one series, the range the storage starts in is used, as before.

Evidence

  • Tests: 815 pass. New or rewritten tests cover the rate per starting range, scaling by fill_level_scale, recording the rate (and not again for the same window), planning despite a failed recording, an older server, leakage without a usage forecast or its sensor, the correction covering both, clipping both together without a correction, and the correction price's storage term. Each fails when its behaviour is broken.
  • Mutation gate: 14 of 14 mutants killed, including three ported from feat(FRBC): correct a usage forecast no plan can absorb, instead of clipping it #286's set whose code this changes.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CcpawsJs74cSwFLXkz7ZwW

S2 states leakage as a rate per fill-level range. It was planned as a
storage efficiency, which FlexMeasures takes as a share of the stock, so the
storage leaked in proportion to how full it was, exact at one fill level
only. The leakage rate of the range the storage starts in is now added to
the usage, over the whole window, and sent with the schedule request. With
a usage correction, the correction covers usage and leakage together, so an
empty storage's leakage can be taken away like any other forced usage.

The leakage sensor records that rate, in the fill-rate unit, and the site
sensor is now called "leakage". It needs FlexMeasures v0.23.0, which takes a
usage with the request; an older server is planned without leakage.

As asked in the review of #283.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcpawsJs74cSwFLXkz7ZwW
Signed-off-by: F.N. Claessen <claessen@seita.nl>
@Flix6x Flix6x added the S2 label Nov 9, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcpawsJs74cSwFLXkz7ZwW
Signed-off-by: F.N. Claessen <claessen@seita.nl>
@coveralls

coveralls commented Nov 9, 2026 •

Copy link
Copy Markdown

Coverage Report for CI Build 42683851519

Warning

No base build found for commit 905254e on feat/s2-usage-correction.
Coverage changes can't be calculated without a base build.
If a base build is processing, this comment will update automatically when it completes.

Coverage: 96.203%

Details

  • Patch coverage: 44 of 44 lines across 2 files are fully covered (100%).

Uncovered Changes

No uncovered changes found.

Coverage Regressions

Requires a base build to compare against. How to fix this →


Coverage Stats

Coverage Status
Relevant Lines: 3397
Covered Lines: 3268
Line Coverage: 96.2%
Coverage Strength: 4.41 hits per line

💛 - Coveralls

Comment thread CHANGELOG-S2.rst Outdated
- A fill-level target profile is recorded on the minima and maxima sensors, if both are given. It is recorded on the handler's ``resolution`` steps, starting from the step its start falls in. It is kept inside the declared fill-level range: a target past either end, such as a night setback below the range, is cut back to the range, and a target band wholly outside the range is recorded at its nearest end, with a warning. If one of the two bounds cannot be recorded, this is logged and the other is still recorded.
- A usage forecast is recorded in ``<energy_unit>/s``. A negative expected usage, which S2 allows, is recorded as stated. Without a usage correction (see below), a schedule request carries the latest forecast without its negative values, since FlexMeasures would plan them as a gain the storage cannot refuse. A FlexMeasures server before v0.23.0 only plans with what is recorded, so there a negative expected usage is recorded as zero, with a warning [`#286 <https://github.com/FlexMeasures/flexmeasures-client/pull/286>`__].
- A leakage behaviour is recorded as a storage efficiency, each time a schedule is requested (see Changed).
- A leakage behaviour is recorded as the leakage rate it states, in ``<energy_unit>/s``, each time a schedule is requested (see Changed) [`#289 <https://github.com/FlexMeasures/flexmeasures-client/pull/289>`__].

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kWh/s would be a terrible unit to read typical residential values in (in FM UI and logs). I would pick a better FM sensor unit.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Rates of fill level (the fill rate, the usage forecast and the leakage) are now recorded in a power unit instead of per second. There is a new fill_rate_unit setting, like energy_unit and power_unit: W (the default), kW or MW. The site creates these three sensors in W, so the example's leakage reads 62.5 W instead of 1.7e-5 kWh/s (ca1bfb7, 83fbf23; changelog updated). An existing site keeps the fill rate and usage forecast sensors it already has in kWh/s; FlexMeasures converts the posted values into them.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied to every sensor the CEM sets up, in 3b18345: power, measured-power and usage correction are now in W as well, so every power and rate of fill level a new site gets is in W, the handler's default. Energy and fill levels stay in kWh, and prices per kWh. A larger site, such as one with charge points, can pass its own sensors and set power_unit and fill_rate_unit. A site created before this keeps its sensors, and the CEM now logs a warning for each one in a different unit than a new site would get.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dropped the warning about a kept sensor in another unit again (f2d9cca): FlexMeasures converts what is posted into the sensor's own unit, so there is nothing to warn about.

S2 states these rates per second, so in kWh/s a heat buffer's leakage of some tens of watts reads about 0.00001.
They are now recorded in the power unit that goes with the energy unit (kW for kWh, W for J and Wh, MW for MJ and MWh), and the site's fill rate, usage forecast and leakage sensors are created in kW.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcpawsJs74cSwFLXkz7ZwW
Signed-off-by: F.N. Claessen <claessen@seita.nl>
@Flix6x Flix6x added this to the 0.10.0 milestone Nov 9, 2026
Flix6x and others added 4 commits November 9, 2026 19:31
Like the energy and power units, the unit that rates of fill level are recorded in is the deployment's to set: W (the default), kW or MW.
Watts read a residential heat buffer's leakage of some tens of watts as such; the site's fill rate, usage forecast and leakage sensors are created in W.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcpawsJs74cSwFLXkz7ZwW
Signed-off-by: F.N. Claessen <claessen@seita.nl>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcpawsJs74cSwFLXkz7ZwW
Signed-off-by: F.N. Claessen <claessen@seita.nl>
Every power and rate of fill level the CEM sets up is now in W, the handler's default: power, measured-power and usage correction joined fill rate, usage forecast and leakage.
Watts read a residential site's small powers as such; a larger site passes its own sensors.
An existing site keeps its sensors, and one in another unit than a new site would get is logged as a warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcpawsJs74cSwFLXkz7ZwW
Signed-off-by: F.N. Claessen <claessen@seita.nl>
FlexMeasures converts what is posted into a sensor's own unit, so an older site's sensor in kW is a valid choice, not a fault.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcpawsJs74cSwFLXkz7ZwW
Signed-off-by: F.N. Claessen <claessen@seita.nl>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants