Add time-varying ORDC; port SC slacks#138
Conversation
Port of PowerSimulations.jl#1629 (time-varying ORDC), adapted to the psy6 data
model where a time-varying ORDC is a `ReserveDemandTimeSeriesCurve` whose
`variable` is a `CostCurve{TimeSeriesPiecewiseIncrementalCurve}` (rather than a
`ReserveDemandCurve` carrying a bare `TimeSeriesKey`).
- add_parameters.jl: service-level piecewise slope/breakpoint cost-parameter
population for `ReserveDemandTimeSeriesCurve` (calc_additional_axes,
get_max_tranches, _get_time_series_name, _add_parameters!, _param_to_vars).
- reserves.jl / market_bid_overrides.jl: drop the "not supported" error and route
ORDC cost through the decremental block-offer path, reading per-timestep data
from the parameter arrays (time-varying) or the curve (static); time-varying
cost goes to the variant objective expression.
- services_constructor.jl: route time-series-backed ORDC to parameter setup.
- Broaden shared reserve / production-cost-expression methods to
Union{ReserveDemandCurve, ReserveDemandTimeSeriesCurve}; update hybrid/storage
disambiguators to keep dispatch unambiguous.
- test/test_services_constructor.jl: build, and build & solve, time-varying ORDC.
- Fix a stray `end` in hybrid_systems.jl that blocked precompilation.
- Point the IOM source at the ac/ordc branch (companion changes live there).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds modeling support for time-varying ORDC by treating it as a ReserveDemandTimeSeriesCurve with a time-series-backed CostCurve, routing its stepwise cost through the decremental block-offer path and populating per-timestep breakpoint/slope parameters.
Changes:
- Add parameter-container population for ORDC time-series breakpoint/slope data and route time-varying ORDC costs to the variant objective expression.
- Broaden reserve-demand-curve dispatch across reserves/objective/expression plumbing to include
ReserveDemandTimeSeriesCurvealongsideReserveDemandCurve. - Add tests that build (and build & solve) models with one or more time-varying ORDC services, and fix a precompilation-blocking stray
end.
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/common_models/add_parameters.jl |
Adds service-side breakpoint/slope parameter population for time-varying ORDC and tranche-axis sizing logic. |
src/common_models/market_bid_overrides.jl |
Routes ORDC through decremental block-offer constraints and adds per-timestep PWL data retrieval from parameter arrays for TS-backed curves. |
src/services_models/reserves.jl |
Broadens ORDC handling to TS curves; routes TS-backed ORDC cost into the variant objective expression; adds parameter processing hook. |
src/services_models/services_constructor.jl |
Hooks ORDC TS parameter setup into service construction when the ORDC curve is time-series-backed. |
src/common_models/add_to_expression.jl |
Broadens cost-expression dispatch to include ReserveDemandTimeSeriesCurve. |
src/hybrid_system_models/hybrid_systems.jl |
Updates ORDC-related method disambiguation for hybrids and removes a stray end that blocked precompilation. |
src/energy_storage_models/storage_models.jl |
Broadens ORDC-related reserve upper-bound dispatch to include ReserveDemandTimeSeriesCurve. |
test/test_services_constructor.jl |
New tests exercising time-varying ORDC build and solve paths (including varying tranche counts). |
Project.toml |
Points InfrastructureOptimizationModels source override to ac/ordc branch. |
test/Project.toml |
Points test environment InfrastructureOptimizationModels source override to ac/ordc branch. |
Comments suppressed due to low confidence (1)
test/Project.toml:41
- Pinning
InfrastructureOptimizationModelsto a moving branch (rev = "ac/ordc") in the test environment reduces reproducibility and can cause CI drift. Prefer pinning to a commit SHA (or tagged release) that contains the required companion changes.
[sources]
InfrastructureOptimizationModels = {rev = "ac/ordc", url = "https://github.com/Sienna-Platform/InfrastructureOptimizationModels.jl"}
InfrastructureSystems = {rev = "IS4", url = "https://github.com/Sienna-Platform/InfrastructureSystems.jl"}
PowerSystems = {rev = "psy6", url = "https://github.com/Sienna-Platform/PowerSystems.jl"}
PowerFlows = {rev = "psy6", url = "https://github.com/Sienna-Platform/PowerFlows.jl"}
PowerNetworkMatrices = {rev = "psy6", url = "https://github.com/Sienna-Platform/PowerNetworkMatrices.jl"}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Track the IOM helper renames: IOM._get_max_tranches/_unwrap_for_param -> IOM.get_max_tranches/unwrap_for_param at the call sites. - Use the semantic IOM.is_time_variant alias instead of raw IS.is_time_series_backed when splitting the reserve cost into the variant vs invariant objective expression. - Make _maybe_process_stepwise dispatch on PSY.ReserveDemandTimeSeriesCurve (with a no-op fallback) instead of unconditionally inspecting get_variable(service), so a misconfigured service surfaces in the later, more specific cost-data validation rather than throwing during construction. - Tidy ORDC comments/error message. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The native DCP/ACP branch builders and the PowerModels translator called PNM functions that do not exist in the pinned PowerNetworkMatrices psy6 rev: branch_admittance and winding_admittance / three_winding_arcs (the latter two never landed in PNM), and the single-arg get_equivalent_physical_branch_parameters (psy6 added a required NetworkReductionData argument). - AC_branches.jl: add POM-local π-admittance adapters (_branch_admittance, _segment_admittance, _winding_admittance, _three_winding_arcs) that rebuild the (g, b, g_fr, b_fr, g_to, b_to, tap, shift) NamedTuples the Ohm's-law and 3W builders consume, sourced from PSY accessors and psy6's reduction-aware EquivalentBranch / ThreeWindingTransformerWinding API. - pm_translator.jl: thread net_reduction_data into the four series/parallel get_branch_to_pm methods for the new two-arg signature; route the call site by segment type; fix a stale double_circuit reference in a BranchesSeries method. - test_native_dcp_acp_models.jl: migrate the admittance primitive tests to the new POM helpers; rewrite the winding unit test against a real ThreeWindingTransformerWinding. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- pm_translator: collapse the runtime `isa` branch that selected the reduction-aware `get_branch_to_pm` overload into multiple dispatch, via a 7-arg forwarding method that drops the network-reduction data for direct branches (the parallel/series methods remain strictly more specific). - test_ac_transmission_security_constrained_models: compare post-contingency MODF/PTDF expressions up to factorization round-off (`_affexpr_approx_equal`) instead of exact `isequal_canonical`. Apple Accelerate's sparse factorization (PNM's macOS default) is not bit-reproducible across builds, so two independently built matrices differ by ~1e-15; the test's intentionally-fresh ground-truth matrix surfaced this as intermittent failures. - Minor: comment cleanups (AC_branches, reserves, services_constructor) and "repin once IOM merged" TODOs in Project.toml/test/Project.toml. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
On the "port former PNM methods" side, can someone explain to me why these things were removed from PNM in the first place? imo they'd belong better back there.
On the ORDC side: very little of the code I'm seeing is ORDC specific. 95% of it applies equally well to other PWL offer curves. That tells me we should be calling helpers back in IOM instead of copy-pasting. I had Claude code take a look:
_add_parameters!should be unified. The deviceObjectiveFunctionParametermethod already handles N components; pass the service as a 1-element collection._get_reserve_pwl_datashould route throughOfferDirection, like the other 3 consumers of the PWL offer abstraction (gen incremental, load decremental, and market-bid). Right now, it re-derives the TS/static split and hard codesDecremental*. Same for the block-offer var/constraint selection inadd_pwl_term_delta!.- The hardcoded
Decremental*types mean the reserve path silently can't ever be incremental; going through_slope_param(dir)makes that a one-line dispatch rather than a structural assumption.
I did a search in the PNM repo: we haven't had a edit: confirmed that there never was such a function. Now, what's the similar function in PNM that does/did exist... |
The StepwiseCostReserve cost path (over ReserveDemandCurve / ReserveDemandTimeSeriesCurve) duplicated logic IOM already provides generically. Route it through the OfferDirection machinery instead of hardcoding Decremental*: - reserves.jl: add the `_reserve_offer_direction` trait (decremental); derive the stepwise param loop from it. - market_bid_plumbing.jl: add `get_offer_curves` for reserve curves; thread `meta` through `_get_pwl_data` and the static `_get_raw_pwl_data`. - market_bid_overrides.jl: delete `_get_reserve_pwl_data` and the reserve `add_pwl_constraint_delta!`; slim `add_pwl_term_delta!` to call the IOM helpers with `dir` + `meta = name` (both static and time-series curves now flow through `IOM._get_pwl_data`). - add_parameters.jl: share the device ObjectiveFunctionParameter body via `_add_objective_function_parameters!(...; meta)`; device + ORDC `_add_parameters!` become thin wrappers; `_calc_additional_axes` dispatches the collection-vs-single `calc_additional_axes` call by model type. Depends on the meta-aware IOM delta-PWL helpers (IOM ac/ordc d43dd12). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ports the still-missing pieces of PowerSimulations.jl PR #1633 into POM, adapted to the POM/IOM split (the core per-contingency SC slack feature was already present on this branch). - MonitoredLine `model_all_branches` attribute (AC_branches.jl): pins both endpoint buses of every covered MonitoredLine irreducible so zero-impedance lines survive the network reduction. Forwarded `irreducible_buses` to the no-reduction VirtualPTDF path so the pin actually takes effect there. - Network-reduction pruning/warnings (instantiate_network_model.jl): drop and warn about branch types fully merged away by the reduction, and warn about individual MonitoredLines partially merged away while their type survives. - Multi-type outage post-contingency slack aliasing (security_constrained_branch.jl): alias shared slack refs into the reusing branch type's container so has_container_key/get_variable stay consistent regardless of build order. - Tests for the SC slack reach, multi-type slack aliasing, and the MonitoredLine reduction retain/prune/warn behavior. Companion IOM change (compute_conflict! hardening + covariant check_conflict_status) lands on InfrastructureOptimizationModels.jl ac/ordc. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Port of PowerSimulations.jl#1629 (time-varying ORDC), adapted to the psy6 data model where a time-varying ORDC is a
ReserveDemandTimeSeriesCurvewhosevariableis aCostCurve{TimeSeriesPiecewiseIncrementalCurve}(rather than aReserveDemandCurvecarrying a bareTimeSeriesKey).ReserveDemandTimeSeriesCurve(calc_additional_axes, get_max_tranches, _get_time_series_name, _add_parameters!, _param_to_vars).endin hybrid_systems.jl that blocked precompilation.Thanks for opening a PR to PowerOperationsModels.jl, please take note of the following when making a PR:
Check the contributor guidelines