Migrate services to the psy6 reserve tree (OnlineReserve/OfflineReserve/GroupReserve) - #235
Open
rodrigomha wants to merge 5 commits into
Open
Migrate services to the psy6 reserve tree (OnlineReserve/OfflineReserve/GroupReserve)#235rodrigomha wants to merge 5 commits into
rodrigomha wants to merge 5 commits into
Conversation
Reserve dispatch moves from the retired struct types to OnlineReserve/
OfflineReserve/GroupReserve, with distinctions recovered from state:
direction and non-spin via the reserve_traits helpers, ORDCs via the demand
curve on the reserve's variable field, static vs time-varying requirements
via the attached requirement series.
- Degenerate-demand skip: a reserve with no demand driver (zero requirement,
or no curve under StepwiseCostReserve) is built as supply only, so it can
serve a GroupReserve; standalone cases get a warning.
- ServiceModel types can be partially applied (OnlineReserve{ReserveUp}, a
UnionAll), so service-vector signatures are decoupled from the model type
and device-side container metas derive from the service instance
(_service_container_meta).
- POM formulation GroupReserve renamed GroupRangeReserve to avoid clashing
with the PSY.GroupReserve component type.
- Formulation-combination enumeration includes parametric leaf service types
(IS.get_all_concrete_subtypes drops UnionAll leaves).
- Storage complete-coverage expectations updated: constraints are built once
per unique service type and side, plus a guard that award variables are
wired into each storage total-reserve balance.
The device-template lookup used Symbol(device_type), which module-qualifies the name whenever the type is not visible from Main - true in every parallel test worker - while the template keys are made with nameof(D). The key miss silently skipped wiring reserve award variables into device-side expressions (thermal range expressions, storage TotalReserveOffering), letting services clear with no physical backing while all constraint counts still matched. Look up with nameof(device_type).
get_max_shunt_current requires the unit-system argument; PSY.SU returns the system-base per-unit value directly, replacing the manual base-power division.
Contributor
Author
|
Test fixtures for this branch come from the paired PRs Sienna-Platform/PowerSystemsTestData#124 (reserve fixtures on the new tree, required |
…disable-stubs #232 commented out the reserve code referencing retired PSY types so POM loads against psy6; this branch migrates those same sites for real, so the merge keeps our implementations everywhere and takes only the docs-workflow change from main.
rodrigomha
marked this pull request as ready for review
August 12, 2026 21:50
PSY moved GroupReserve into the reserve tree (it was <: Service), so the type split no longer separates groups from device-backed reserve code. Restore the boundaries explicitly: - add_reserve_offer_costs! on a GroupReserve throws: per-resource offers live on a group's contributing services, never on the group. - _is_group_member(::System, ::GroupReserve) = false: groups do not nest, and the AbstractReserve method now matches groups. - Formulation-pairing guards fail at ServiceModel declaration with an actionable ArgumentError: a GroupReserve accepts only group formulations, group formulations accept only GroupReserve, and a bare (direction-less) GroupReserve declaration says to apply the direction. Extra methods disambiguate against the generic reserve defaults now that the bounds overlap. - Comment updates where AbstractReserve bounds admit groups type-wise but the paths are unreachable for them (slacks, the deviceless exemption). - Fix a latent misspelled log-group constant in the @debug skip branch. Full suite green with the new PSY tree: 105898/105898.
rodrigomha
added a commit
that referenced
this pull request
Aug 13, 2026
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.
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.
Reserve dispatch re-expressed on the psy6 reserve tree, with distinctions recovered from state instead of struct types: direction and non-spin via
reserve_traits.jl, ORDCs via the demand curve onvariable, static vs time-varying requirements via the attached series. Includes the degenerate-demand supply-only skip (services can serve aGroupReserve), theGroupRangeReserverename, instance-derived container metas, and two independent fixes in their own commits: theSymbol(T)-vs-nameofsilent service-device wiring skip under parallel test workers, and the units-mandatoryget_max_shunt_currentread.Full suite green locally against the local psy6 stack: 105891/105891.
Scope note: this PR is the refactor only. The elastic group ORDC (
GroupStepwiseCostReserve) and load reserve provision (PowerLoadDispatchup/down reserves with the costless-load guard) are NEW features, not migrations of existing behavior, and will land in a follow-up PR together with the market integration test and theirformulation_library.mdentries.Depends on the PSY reserve changes (
jd/schema_matching), Sienna-Platform/PowerSystemsTestData#124, and Sienna-Platform/PowerSystemCaseBuilder.jl#212 - CI cannot pass until those merge and[sources]resolve.🤖 Generated with Claude Code