Skip to content

Group-stepwise ORDC, load reserve provision, and OfflineReserve ORDC supply - #236

Open
rodrigomha wants to merge 7 commits into
rh/reserve_refactorfrom
rh/new_load_and_group_services
Open

Group-stepwise ORDC, load reserve provision, and OfflineReserve ORDC supply#236
rodrigomha wants to merge 7 commits into
rh/reserve_refactorfrom
rh/new_load_and_group_services

Conversation

@rodrigomha

@rodrigomha rodrigomha commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Stacked on #235 (base branch rh/reserve_refactor); the diff shows only this feature's commits.

New features (not refactor items) re-expressed on the psy6 reserve tree:

  • GroupStepwiseCostReserve: elastic group ORDC. One dense ServiceRequirementVariable per group, a clearing constraint sum(member awards) >= requirement variable, and the group's demand curve (static or time series) priced through the existing delta-PWL path. Mis-paired ServiceModels (GroupReserve with a non-group formulation and vice versa) fail at declaration.
  • Load reserve provision under PowerLoadDispatch: the inverse of a generator. Up reserve is committed shed (P - r_up >= 0), down reserve is committed extra consumption (P + r_down <= forecast), gated on an attached service model. A costless load selling reserves errors since nothing pins its consumption.
  • OfflineReserve (non-spin) as ORDC supply from storage and loads: non-spinning is upward-only, so it routes like an up reserve everywhere a device supplies it (new UP_RESERVE union). Previously only thermal was wired: the storage reserve-balance multipliers MethodError'd, two storage coverage branches silently skipped the service, complete coverage hit an @assert false, and _modify_device_model! no-opped every OfflineReserve model. The no-op is now scoped to NonSpinningReserve, whose awards ride ReservePowerConstraint instead of the device range expressions.
  • Integration test: energy + reserve co-clearing with an elastic service, a stepwise group, and per-resource offers from thermal, storage, and load participants.

Tests live in existing files: group-stepwise testsets in test_services_constructor.jl; market integration, load provision, and the OfflineReserve ORDC scenarios in test_device_reserve_offers.jl; the storage non-spin coverage testset in test_storage_device_models.jl.

Full suite green: 106708/106708. Docs build green.

🤖 Generated with Claude Code

…supply

One demand curve on a PSY.GroupReserve is cleared by the summed awards of its
contributing services: a dense ServiceRequirementVariable per group, a clearing
constraint sum(member awards) >= demand variable (its dual is the group price),
and the group curve priced through the delta-PWL path. Static and time-series
group curves are both supported via the existing service-side TS machinery.

- Group demand predicates mirror the service formulations: GroupRangeReserve is
  driven by the scalar requirement, GroupStepwiseCostReserve by the demand curve;
  degenerate groups skip as supply aggregates with a warning.
- Group deferral generalized to a vector so up and down groups coexist.
- RESERVE_PRODUCT_TYPES (definitions.jl) consolidates the open
  Union{PSY.AbstractReserve, PSY.GroupReserve} signature bound used across the
  reserve traits, PWL parameter chain, and objective plumbing.
- Formulation-pairing guards: a GroupReserve accepts only group formulations and
  vice versa, failing with ArgumentError at ServiceModel declaration.
- Tests cover build/solve, aggregation binding, merit order, no-group baseline,
  the degenerate skip, TS group curves, and the pairing guards.
PSY moved GroupReserve into the reserve tree, so the RESERVE_PRODUCT_TYPES
alias and the per-type methods that existed only because groups sat outside
it are gone: every former Union bound is plain PSY.AbstractReserve, the
group get_initial_conditions_service_model and the CostExpressions container
sibling fold into the AbstractReserve methods, and uses_compact_power opens
to the abstract type. Formulation-pair bounds
(Union{StepwiseCostReserve, GroupStepwiseCostReserve}) and the group demand
predicates stay - they encode formulation semantics, not typing.

The pairing guards merge with the #235 hardening set: valid direction-applied
pairs for both group formulations, the generic-defaults disambiguator, the
inverse guard over both formulations, and a direction-required error for
bare GroupReserve declarations.
A controllable load routes reserves inversely to generators: up reserve
is committed shed (P - r_up >= 0), down reserve is committed extra
consumption (P + r_down <= forecast). Dispatch limits move to the range
expressions only when a reserve service is attached, and a costless load
selling reserves fails loudly since nothing pins its consumption.
…-out

End-to-end market test: an elastic OnlineReserve (StepwiseCostReserve)
and a GroupStepwiseCostReserve group co-clear against per-resource
offers from thermal, storage, and load participants. Registers
GroupStepwiseCostReserve in the formulation library, refreshes the
stale group-reserve warnings there, and renames the remaining
market-specific reserve identifiers in hydro to generic ones.
Non-spinning is upward-only, so OfflineReserve routes like an up
reserve everywhere a device supplies it. New UP_RESERVE union in
reserve_traits.jl; storage reserve-balance multipliers, coverage
branches (two of which silently skipped OfflineReserve, one asserted),
get_fraction, and the TotalReserveOffering fold widened; load routing
and folding accept it as committed shed. The _modify_device_model!
no-op is scoped to NonSpinningReserve, whose awards ride
ReservePowerConstraint instead of the device range expressions.
@rodrigomha

Copy link
Copy Markdown
Contributor Author

New commit 3479231: OfflineReserve can now supply an ORDC (StepwiseCostReserve) from storage and loads, not just thermal. Non-spin is upward-only, so it routes like an up reserve everywhere (new UP_RESERVE union). This fixes two silent skip branches and an @assert false in the storage coverage constraints, and scopes the _modify_device_model! no-op to NonSpinningReserve only. Full suite 106708/106708.

@rodrigomha rodrigomha changed the title Group-stepwise ORDC and load reserve provision Group-stepwise ORDC, load reserve provision, and OfflineReserve ORDC supply Aug 13, 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.

1 participant