Skip to content

Add CVAR and NCVAR resource adequacy reporting - #201

Open
bcakire wants to merge 13 commits into
mainfrom
bc_cvar_review_fixes
Open

Add CVAR and NCVAR resource adequacy reporting#201
bcakire wants to merge 13 commits into
mainfrom
bc_cvar_review_fixes

Conversation

@bcakire

@bcakire bcakire commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

This PR continues the work and review discussion from #160. The updated implementation was moved to an upstream ReEDS branch so the GitHub Actions tests can run.

Most of the review comments from #160 were addressed in bs/cvar; this branch is based on that work and includes the remaining dependency-related changes.

Branch is tested against the corresponding main baseline using USA_defaults. The two runs produced identical core model results: capacity, generation, new capacity, retirements, curtailment, transmission, electricity prices, and present value of system cost all matched in the final year, with no observed differences in the comparison plots. The additional CVAR/NCVAR reporting therefore does not appear to affect the ReEDS solution.

Runtime increased slightly, as expected, due to writing sample-level PRAS shortfall totals and calculating the additional RA metrics.

Metric Main baseline CVAR/NCVAR branch Difference Change
Total runtime 10.86 h 11.00 h +0.14 h +1.28%
Final-year runtime 0.99 h 1.04 h +0.04 h +4.17%
image image image image image

Illustrative CVAR/NCVAR diagnostics

The figures below illustrate the new CVAR/NCVAR reporting using the USA_defaults test case. The run used 100 PRAS samples and GSw_PRM_CVARalpha = 0.95, so each CVAR estimate is the mean of the five largest sample-total shortfalls.

PRAS sample-total shortfalls span the full 15-weather-year resource adequacy horizon and are annualized before being reported. These results are intended to validate the calculation. The national results show substantial variation in tail shortfall across solve years. The regional diagnostics indicate that the national tail risk is often concentrated in a small number of regions, with ND_MISO accounting for the largest regional CVAR in several of the illustrated years.

image **National CVAR by solve year.** CVAR is reported as the annualized mean of the worst 5% of PRAS sample-total shortfalls. With 100 samples, the α = 0.95 tail contains five samples. image **Regional CVAR hotspots by solve year.** Bubble size represents annualized CVAR at the ReEDS region level. Only positive region–year observations are shown. image **USA shortfall exceedance curve for 2029. The dashed vertical line marks the 5% tail boundary. VaR95 is the shortfall at that boundary, while CVAR95 is the mean annualized shortfall across the five samples in the upper tail.

+ (
(pd.Timedelta('5D') if sw.GSw_HourlyType == 'wek' else pd.Timedelta('1D'))
- pd.Timedelta('1h')
- pd.Timedelta('1H')

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.

The Pacific run test on the github actions failed with this error (see log output in the "run ReEDS model" step here):

solve.py | 2026-08-27 22:52:34 | ERROR | ValueError: Invalid frequency: 1H. Failed to parse with error message: ValueError("Invalid frequency: H. Failed to parse with error message: KeyError('H'). Did you mean h?")

Given that I think we should revert these to '1h' to '1H' changes. Was this change working for your runs? If it was, were you testing with a clean reeds environment?

@bcakire bcakire Sep 1, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

yes I had the same issue when testing, fixed and pushed the change.

for i, row in eue_events.iterrows():
dates.append(
pd.Series(index=pd.date_range(row.start, row.end, freq='h'), data=1)
pd.Series(index=pd.date_range(row.start, row.end, freq='H'), data=1)

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.

Looks like another one to revert

Suggested change
pd.Series(index=pd.date_range(row.start, row.end, freq='H'), data=1)
pd.Series(index=pd.date_range(row.start, row.end, freq='h'), data=1)

Comment on lines -514 to -515

### Check all stress criteria; for regions that fail, add new stress periods

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.

Let's keep this comment

Suggested change
### Check all stress criteria; for regions that fail, add new stress periods
### Check all stress criteria; for regions that fail, add new stress periods

write_surplus=False,
write_energy=False,
write_shortfall_samples=False,
write_shortfall_samples_totals=True,

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.

It sounds like PRAS.ShortfallSamples() increases memory use within PRAS, but NatLabRockies/PRAS#109 fixes it. Can we check the PRAS memory use on a full-US run on this branch and on main before merging (I think Kodi has done this before)? If it goes up a lot, we should probably wait to merge this PR until we can switch to a new PRAS release that includes this PRAS PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants