New approach for partial dispatch - #1542
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## circularity #1542 +/- ##
===============================================
- Coverage 90.63% 90.60% -0.03%
===============================================
Files 61 62 +1
Lines 8870 8860 -10
Branches 8870 8860 -10
===============================================
- Hits 8039 8028 -11
Misses 516 516
- Partials 315 316 +1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
🔵 Needs a closer look
It changes core investment/dispatch semantics and updates many golden outputs, so it needs careful domain validation beyond automated review confidence.
Pull request overview
Updates the simulation’s partial-dispatch workflow so that, during sequential investment, dispatch is re-run only for the currently-invested market (rather than cumulatively re-dispatching all downstream markets), with demand passed explicitly into the dispatch optimiser.
Changes:
- Introduces a shared
simulation::demandmodule and threads anAllDemandMapintoDispatchRun/ dispatch constraints so partial dispatch can use internal (propagated) demands. - Adjusts investment-time dispatch to balance only the current market set, using internal demand propagation between investment stages.
- Updates multiple golden-test CSV outputs to reflect the new dispatch/investment behaviour.
File summaries
| File | Description |
|---|---|
| tests/data/two_outputs/commodity_prices.csv | Updated expected prices for the two_outputs fixture under the new partial-dispatch behaviour. |
| tests/data/two_outputs/asset_capacities.csv | Updated expected capacities/tranches for two_outputs. |
| tests/data/simple/debug_solver.csv | Updated expected objective values for intermediate dispatch runs. |
| tests/data/simple/debug_commodity_balance_duals.csv | Updated expected commodity balance duals for intermediate dispatch runs. |
| tests/data/simple/debug_appraisal_results.csv | Updated expected appraisal outputs due to changed dispatch inputs/duals. |
| tests/data/simple/debug_appraisal_results_time_slices.csv | Updated expected appraisal time-slice outputs. |
| tests/data/simple_tranche_size/commodity_flows.csv | Updated expected flows (minor floating-point differences). |
| tests/data/simple_tranche_size/asset_capacities.csv | Updated expected capacities (minor floating-point differences). |
| tests/data/missing_commodity/commodity_prices.csv | Updated expected prices for missing_commodity. |
| tests/data/missing_commodity/commodity_flows.csv | Updated expected flows for missing_commodity. |
| tests/data/missing_commodity/asset_capacities.csv | Updated expected capacities/tranches for missing_commodity. |
| tests/data/circularity/commodity_prices.csv | Updated expected prices for circularity. |
| tests/data/circularity/commodity_flows.csv | Updated expected flows for circularity. |
| tests/data/circularity/asset_capacities.csv | Updated expected capacities/tranches for circularity. |
| tests/data/circularity_npv/commodity_prices.csv | Updated expected prices for circularity_npv. |
| tests/data/circularity_npv/commodity_flows.csv | Updated expected flows for circularity_npv. |
| tests/data/circularity_npv/asset_capacities.csv | Updated expected capacities/tranches for circularity_npv. |
| src/simulation/optimisation/constraints.rs | Makes commodity-balance lower bounds come from an explicit demand map (supports internal demand in partial dispatch). |
| src/simulation/optimisation.rs | Threads AllDemandMap through DispatchRun and into constraint construction. |
| src/simulation/market.rs | Updates dispatch calls used in cycle selection to provide current demand map. |
| src/simulation/investment.rs | Switches post-investment dispatch to balance only the current market set and uses internal demand propagation. |
| src/simulation/demand.rs | New module defining demand map types and collecting preset demands for a year. |
| src/simulation.rs | Collects preset demands once per year and passes them into final dispatch runs. |
| benches/assets.rs | Updates benchmark setup dispatch calls to provide demand maps. |
Review details
- Files reviewed: 26/26 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
091a08c to
769d469
Compare
Description
The current approach for partial dispatch (dispatch on intermediate systems during investment, which we perform successively after investments in each market to generate demands for upstream markets) is to run dispatch on the cumulative system. For example, consider:
A (SED) -> B (SED) -> C (SVD) -> Demand
We begin by doing investments for C, then we dispatch the system passing in the exogenous C demands and only balancing C. This generates demands for B. We then do investments for B, then we dispatch the system again passing in the exogenous demands for C, this time balancing C and B. Then we invest for A and dispatch balancing C, B and A.
In the new approach, we would do the following, in order:
Each round we only dispatch for a single commodity (i.e. the commodity we've just invested in), rather than re-dispatching every commodity we've already visited. This obviously avoids wasted computation, but it's also helps with the circularity problem, as a big problem with circularities using the previous partial dispatch approach was that cumulative systems could be unresolvable (hence the need to do "cycle balancing", which I'm moving away from).
Circularities are currently temporarily broken (as of #1539), but I have a plan for fixing them which follows on from this.
One implication is that this could lead to excess capacity for processes with multiple output commodities (see
two_outputs), which was previously "optimised away" in the cumulative approach. Not too concerned about this as I think the current approach for dealing with multiple outputs is very imperfect anyway and the previous approach was just a plaster.There may also be some unpredictable effects of this, for example see
missing_commodity. Overall capacities haven't changed, but the tranche size forBIOPROhas changed considerably. This appears to be due to changing shape of the BIOPRD demand profile seen at the BIOPRD investment stage. I asked Claude to explain for me exactly what's going on here, as it's a bit complicated, and here's what it said:Maybe that makes sense? I think actually the root cause is that in the previous approach we were effectively using new shadow prices for all downstream commodities (as we were balancing them in the cumulative dispatch), whereas now we're consistently using previous year shadow prices. I think that's better?
Fixes # (issue)
Type of change
Key checklist
$ cargo test$ cargo docpresent in the previous release
Further checks