Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds new reliability metrics—LOLD (loss of load days), LOLEv (loss of load events), and MeanEventDuration—by introducing a new event-based result type (ShortfallEvents) and extending existing shortfall-sample metrics.
Changes:
- Add new
ReliabilityMetrictypes:LOLD,LOLEv, andMeanEventDuration. - Implement
LOLDcomputation fromShortfallSamplesResultusing day grouping derived from timestamps. - Introduce
ShortfallEventsresult recording/finalization to enable event-based metrics and add corresponding simulation tests.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| PRASCore.jl/test/Simulations/runtests.jl | Adds tests for LOLD and event-based metrics (LOLEv/MeanEventDuration). |
| PRASCore.jl/src/Simulations/utils.jl | Extends init_regionshortfall dispatch to include ShortfallEvents. |
| PRASCore.jl/src/Simulations/recording.jl | Adds record!/reset! logic to accumulate contiguous shortfall events. |
| PRASCore.jl/src/Results/utils.jl | Adds _day_ids helper to map timestamps to day identifiers. |
| PRASCore.jl/src/Results/metrics.jl | Defines new metric structs and show/val/stderror behavior. |
| PRASCore.jl/src/Results/ShortfallSamples.jl | Implements LOLD constructors and day-counting logic for samples. |
| PRASCore.jl/src/Results/ShortfallEvents.jl | Adds new ShortfallEvents resultspec, accumulator/result types, and event-based metric constructors. |
| PRASCore.jl/src/Results/Results.jl | Exports new metrics and includes the new ShortfallEvents result file/type. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| @testset "Shortfall Event Metrics" begin | ||
| # Single-region system | ||
| @test val(LOLEv(events_1a)) >= 0 | ||
| @test stderror(LOLEv(events_1a)) >= 0 | ||
| @test val(MeanEventDuration(events_1a)) >= 0 | ||
| @test stderror(MeanEventDuration(events_1a)) >= 0 | ||
|
|
||
| @test LOLEv(events_1a) ≈ LOLEv(events_1a, "Region") | ||
| @test MeanEventDuration(events_1a) ≈ MeanEventDuration(events_1a, "Region") | ||
|
|
||
| # Multi-region system | ||
| @test val(LOLEv(events_3)) >= 0 | ||
| @test val(MeanEventDuration(events_3)) >= 0 | ||
| @test val(LOLEv(events_3, "Region A")) >= 0 | ||
| @test val(MeanEventDuration(events_3, "Region A")) >= 0 | ||
|
|
||
| @test val(LOLEv(events_3)) >= val(LOLEv(events_3, "Region A")) | ||
|
|
||
| @test PRAS.PRASCore.Results.totalevents(events_1a) >= 0 | ||
| @test PRAS.PRASCore.Results.totalevents(events_3, "Region A") >= 0 | ||
| end |
| @testset "LOLD Results" begin | ||
| lold_1a = LOLD(shortfall2_1a) | ||
| regional_lold_1a = LOLD(shortfall2_1a, "Region") | ||
|
|
||
| @test val(lold_1a) isa Float64 | ||
| @test stderror(lold_1a) isa Float64 | ||
| @test val(regional_lold_1a) isa Float64 | ||
| @test stderror(regional_lold_1a) isa Float64 | ||
|
|
||
| @test val(lold_1a) >= 0 | ||
| @test stderror(lold_1a) >= 0 | ||
| @test val(regional_lold_1a) >= 0 | ||
| @test stderror(regional_lold_1a) >= 0 | ||
|
|
||
| @test val(lold_1a) <= length(unique(Date.(shortfall2_1a.timestamps))) | ||
| @test val(regional_lold_1a) <= length(unique(Date.(shortfall2_1a.timestamps))) | ||
| @test val(lold_1a) >= val(regional_lold_1a) |
| struct ShortfallEvents <: ResultSpec end | ||
| struct DemandResponseShortfallEvents <: ResultSpec end | ||
|
|
| function init_regionshortfall( | ||
| ::Type{S}, | ||
| edges, | ||
| region) where {S <: Union{ | ||
| Results.Shortfall, | ||
| Results.ShortfallSamples}} | ||
| Results.ShortfallSamples, | ||
| Results.ShortfallEvents}} | ||
| return edges[region].flow | ||
| end |
| @test val(LOLEv(events_1a)) >= 0 | ||
| @test stderror(LOLEv(events_1a)) >= 0 | ||
| @test val(MeanEventDuration(events_1a)) >= 0 | ||
| @test stderror(MeanEventDuration(events_1a)) >= 0 | ||
|
|
||
| @test LOLEv(events_1a) ≈ LOLEv(events_1a, "Region") | ||
| @test MeanEventDuration(events_1a) ≈ MeanEventDuration(events_1a, "Region") | ||
|
|
||
| # Multi-region system | ||
| @test val(LOLEv(events_3)) >= 0 | ||
| @test val(MeanEventDuration(events_3)) >= 0 | ||
| @test val(LOLEv(events_3, "Region A")) >= 0 | ||
| @test val(MeanEventDuration(events_3, "Region A")) >= 0 | ||
|
|
||
| @test val(LOLEv(events_3)) >= val(LOLEv(events_3, "Region A")) | ||
|
|
||
| @test PRAS.PRASCore.Results.totalevents(events_1a) >= 0 | ||
| @test PRAS.PRASCore.Results.totalevents(events_3, "Region A") >= 0 |
|
Thanks @akrivi for the PR! Can you please check the test syntax and make sure tests are passing? Also please address any valid copilot comments and resolve them, and whatever you feel are not valid, leave them as it is or reply and I will resolve them. For the docs, you just need to add the new metrics to the Please lmk if you want any inputs on getting the tests to pass and we can chat. |
This PR implements the following metrics:
With the implementation of the above, all metrics defined in [2] are included in PRAS
Additionally, the following metrics commonly used in analysis are implemented:
References:
[1] “Clarifying the interpretation and use of the LOLE Resource Adequacy Metric,”
[2] "Probabilistic Adequacy and Measures", NERC