Skip to content

feat: fixed (no-load / commitment) cost per operation mode#2327

Open
Flix6x wants to merge 1 commit into
feat/2113-operation-mode-power-bandsfrom
feat/operation-mode-fixed-cost
Open

feat: fixed (no-load / commitment) cost per operation mode#2327
Flix6x wants to merge 1 commit into
feat/2113-operation-mode-power-bandsfrom
feat/operation-mode-fixed-cost

Conversation

@Flix6x

@Flix6x Flix6x commented Jul 18, 2026

Copy link
Copy Markdown
Member

Based on #2278 (operation-mode power bands).

The gap

Operation modes (#2113 / #2278) constrain a device's power to a set of signed bands, but carry no fixed cost. Real unit-commitment has a no-load / commitment cost incurred only while a unit is on — e.g. a cogeneration unit's full-speed-no-load fuel burn, or a fixed per-timestep running cost. Without it, an LP/MILP that can idle a unit still under-represents the cost of keeping it running at low output, so the schedule and objective diverge from the true unit-commitment optimum by the no-load term.

What this adds

An optional fixed-cost per operation mode, incurred at every time step during which that mode's binary is active.

  • Schema: each operation-modes entry may carry "fixed-cost": "1200 EUR" (per time step, in the flex-context currency). Absent ⇒ 0, so existing behaviour is unchanged. Kept in its native currency and converted to the flex-context's shared currency by the scheduler.
  • Objective: adds Σ_{d,b,j} device_band[d,b,j] · fixed_cost[d,b] to the cost expression, threaded through device_scheduler via a new device_band_fixed_costs argument, mirroring how the power bands themselves are threaded.
  • Plumbing: carried from the flex-model through StorageScheduler (device_constraints[d].attrs) to device_scheduler, alongside the existing operation_modes handling.
  • Tests: a generator with an off mode (0 cost) and an on mode with a fixed-cost — asserts the unit idles when its marginal benefit is below the fixed cost, and that the objective includes the fixed cost exactly when on (hand-computed on a 2-step instance).
  • Docs: changelog + metadata field documentation.

Min-up / min-down time is intentionally out of scope (follow-up).

🤖 Generated with Claude Code

Based on #2278 (operation-mode power bands).

Operation modes constrain a device's power to signed bands but carry no
fixed cost. Real unit-commitment has a no-load / commitment cost incurred
only while a unit is on (e.g. a cogeneration unit's full-speed-no-load
fuel burn). Without it, an LP/MILP that can idle a unit under-represents
the cost of staying on at low output.

Adds an optional per-mode `fixed-cost` (per timestep, in the flex-context
currency), incurred whenever that mode's binary is active:
- schema: OperationModeSchema.fixed-cost, parsed to a currency Quantity;
- objective: sum over (d,b,j) of device_band[d,b,j] * fixed_cost[d,b],
  threaded through device_scheduler as device_band_fixed_costs, mirroring
  the power bands;
- tests: a generator idles when marginal benefit < fixed cost, and the
  objective includes the fixed cost exactly when on (hand-computed);
- docs: changelog + metadata field.

Min-up / min-down time is out of scope (follow-up).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016MLCUiSdXDqDBmg8GbYp1B
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant