Remove flexible capacity balancing for circularities - #1539
Conversation
774a3b1 to
298f8a5
Compare
298f8a5 to
28c7b3b
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Documentation and configuration handling need tightening (docs still mention capacity_margin, and legacy capacity_margin in model.toml will be silently ignored without an explicit warning/error).
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR removes the “flexible capacity balancing” mechanism that previously helped cycle (circular) market investment runs converge by allowing newly selected assets to temporarily flex capacity during intermediate dispatch rebalances.
Changes:
- Removed flexible-capacity decision variables and the associated activity-limit formulation from dispatch optimisation.
- Removed the
capacity_marginmodel parameter (and its schema entry) and simplified cycle dispatch rebalancing to run with fixed capacities only. - Updated circularity test fixtures/expected outputs (flows, prices, and capacities) to match the new optimisation behaviour.
File summaries
| File | Description |
|---|---|
| tests/data/circularity/commodity_prices.csv | Updates expected commodity prices for the circularity example after removing flexible balancing. |
| tests/data/circularity/commodity_flows.csv | Updates expected dispatch flows for the circularity example after optimisation changes. |
| tests/data/circularity/asset_capacities.csv | Updates expected installed capacities (no longer adjusted by flexible balancing). |
| tests/data/circularity_npv/commodity_prices.csv | Same as above, for the NPV circularity fixture. |
| tests/data/circularity_npv/commodity_flows.csv | Same as above, for the NPV circularity fixture. |
| tests/data/circularity_npv/asset_capacities.csv | Same as above, for the NPV circularity fixture. |
| src/simulation/optimisation/constraints.rs | Simplifies activity constraints (removes flexible-capacity special casing) and includes all assets in equal-utilisation constraints. |
| src/simulation/optimisation.rs | Removes capacity-variable plumbing from the optimisation model and solution API. |
| src/simulation/market.rs | Removes cycle-stage capacity flexing and post-cycle capacity mutation; dispatch failures now surface without capacity-margin guidance. |
| src/model/parameters.rs | Removes capacity_margin from ModelParameters and defaults/validation. |
| schemas/input/model.yaml | Removes capacity_margin from the input schema. |
Review details
- Files reviewed: 11/11 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| pub max_ironing_out_iterations: u32, | ||
| /// The relative tolerance for price convergence in the ironing out loop | ||
| #[serde(deserialize_with = "deserialise_finite_non_negative")] | ||
| pub price_tolerance: Dimensionless, | ||
| /// Slack applied during cycle balancing, allowing newly selected assets to flex their capacity | ||
| /// by this proportion. | ||
| /// | ||
| /// Existing assets remain fixed; this gives newly selected assets the wiggle-room to absorb | ||
| /// small demand changes before we would otherwise need to break for re-investment. | ||
| #[serde(deserialize_with = "deserialise_finite_non_negative")] | ||
| pub capacity_margin: Dimensionless, | ||
| /// Number of years an asset can remain unused before being decommissioned |
| /// Iterates through the a pre-ordered set of markets forming a cycle, selecting assets for each | ||
| /// market in turn. | ||
| /// | ||
| /// Dispatch optimisation is performed after each market is visited to rebalance demand. | ||
| /// While dispatching, newly selected (`Ready`) assets are given flexible capacity (bounded by | ||
| /// `capacity_margin`) so small demand shifts caused by later markets can be absorbed. After all | ||
| /// markets have been visited once, the final set of assets is returned, applying any capacity | ||
| /// adjustments from the final full-system dispatch optimisation. | ||
| /// Dispatch optimisation is performed after each market is visited. | ||
| /// | ||
| /// Dispatch may fail at any point if new demands are encountered for previously visited markets, | ||
| /// and the `capacity_margin` is not sufficient to absorb the demand shift. At this point, the | ||
| /// simulation is terminated with an error prompting the user to increase the `capacity_margin`. | ||
| /// A longer-term solution (TODO) may be to trigger re-investment for the affected markets. Other | ||
| /// yet-to-implement features may also help to stabilise the cycle, such as capacity growth limits. | ||
| /// Dispatch may fail at any point if new demands are encountered for previously visited markets. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## circularity #1539 +/- ##
===============================================
- Coverage 90.83% 90.63% -0.21%
===============================================
Files 61 61
Lines 9014 8870 -144
Branches 9014 8870 -144
===============================================
- Hits 8188 8039 -149
- Misses 507 516 +9
+ Partials 319 315 -4 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Description
Removing flexible capacity balancing for circularities, to be replaced with another approach in the future. For now, models with circularities will likely fail, unless the circularity isn't used, or the system already has enough excess capacity to absorb demand imbalances caused by circularities. The example models pass, seemingly due to the latter.
Fixes # (issue)
Type of change
Key checklist
$ cargo test$ cargo docpresent in the previous release
Further checks