Skip to content

Add time-varying ORDC; port SC slacks#138

Open
acostarelli wants to merge 9 commits into
mainfrom
ac/ORDC-time-series
Open

Add time-varying ORDC; port SC slacks#138
acostarelli wants to merge 9 commits into
mainfrom
ac/ORDC-time-series

Conversation

@acostarelli

Copy link
Copy Markdown
Member

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).

Thanks for opening a PR to PowerOperationsModels.jl, please take note of the following when making a PR:

Check the contributor guidelines

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>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 ReserveDemandTimeSeriesCurve alongside ReserveDemandCurve.
  • 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 InfrastructureOptimizationModels to 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.

Comment thread src/services_models/services_constructor.jl Outdated
Comment thread src/services_models/reserves.jl
Comment thread src/common_models/market_bid_overrides.jl
Comment thread src/common_models/add_parameters.jl
Anthony Costarelli and others added 2 commits June 15, 2026 15:21
- 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>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 12 out of 13 changed files in this pull request and generated 1 comment.

Comment thread src/services_models/reserves.jl
- 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>
@acostarelli acostarelli changed the title [WIP] Add time-varying ORDC (ReserveDemandTimeSeriesCurve) support [WIP] Add time-varying ORDC; port former PNM methods Jun 15, 2026
@acostarelli acostarelli changed the title [WIP] Add time-varying ORDC; port former PNM methods Add time-varying ORDC; port former PNM methods Jun 16, 2026

@luke-kiernan luke-kiernan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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:

  1. _add_parameters! should be unified. The device ObjectiveFunctionParameter method already handles N components; pass the service as a 1-element collection.
  2. _get_reserve_pwl_data should route through OfferDirection, 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 codes Decremental*. Same for the block-offer var/constraint selection in add_pwl_term_delta!.
  3. 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.

@luke-kiernan

luke-kiernan commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

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.

I did a search in the PNM repo: we haven't had a branch_admittance function in a long time, perhaps ever. The closest thing I see is some branch_admittance_from_to fields in the BranchAdmittanceMatrix struct, since renamed to use arc instead of branch. So I'm puzzled: why did the native-networkmodels work introduce that PNM.branch_admittance call? AI hallucinations perhaps?

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>
@acostarelli acostarelli changed the title Add time-varying ORDC; port former PNM methods Add time-varying ORDC; port former PNM methods; port SC slacks Jun 16, 2026
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>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 17 out of 18 changed files in this pull request and generated 3 comments.

Comment thread src/ac_transmission_models/security_constrained_branch.jl Outdated
Comment thread src/network_models/instantiate_network_model.jl Outdated
Comment thread test/Project.toml
@acostarelli acostarelli changed the title Add time-varying ORDC; port former PNM methods; port SC slacks Add time-varying ORDC; port SC slacks Jun 16, 2026
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.

4 participants