Group-stepwise ORDC, load reserve provision, and OfflineReserve ORDC supply - #236
Open
rodrigomha wants to merge 7 commits into
Open
Group-stepwise ORDC, load reserve provision, and OfflineReserve ORDC supply#236rodrigomha wants to merge 7 commits into
rodrigomha wants to merge 7 commits into
Conversation
…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.
Contributor
Author
|
New commit |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 denseServiceRequirementVariableper group, a clearing constraintsum(member awards) >= requirement variable, and the group's demand curve (static or time series) priced through the existing delta-PWL path. Mis-pairedServiceModels (GroupReservewith a non-group formulation and vice versa) fail at declaration.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 (newUP_RESERVEunion). 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 everyOfflineReservemodel. The no-op is now scoped toNonSpinningReserve, whose awards rideReservePowerConstraintinstead of the device range expressions.Tests live in existing files: group-stepwise testsets in
test_services_constructor.jl; market integration, load provision, and theOfflineReserveORDC scenarios intest_device_reserve_offers.jl; the storage non-spin coverage testset intest_storage_device_models.jl.Full suite green: 106708/106708. Docs build green.
🤖 Generated with Claude Code