Skip to content

Add faster method for assigning actual to representative periods#105

Open
patrickbrown4 wants to merge 10 commits into
mainfrom
pb/rep15
Open

Add faster method for assigning actual to representative periods#105
patrickbrown4 wants to merge 10 commits into
mainfrom
pb/rep15

Conversation

@patrickbrown4
Copy link
Copy Markdown
Contributor

@patrickbrown4 patrickbrown4 commented May 22, 2026

Summary

When using 7 or 15 weather years in GSw_HourlyWeatherYears, the second stage of the representative period selection (mapping actual to representative periods using a MILP) is exceedingly slow. This PR adds an alternative method that runs in seconds and produces actual-to-representative period maps that look pretty much the same.

The defaults are unchanged, but the new method can be used in the meantime until we decide what to do by default.

Technical details

Implementation notes

The new method, implemented in reeds.timeseries.match_act2rep_bestfirst(), works as follows:

  1. Begin with a table of weights for each representative (rep) period
  2. Calculate the distance in (feature × region)-dimensional space between each actual and rep period.
  3. While there is still weight remaining in the rep-period weight table:
    a. Match each rep period to the single remaining actual period that is closest to it, recording its match in the actual-to-rep-period table
    b. Decrement the remaining weight for each rep period. If any weights reach zero, remove them from future consideration for matches. (So the lowest-weighted rep periods will fill up and drop out of consideration first.)
    c. Remove the actual periods that were matched from the table of distances
    d. Return to 3.a. and repeat until there are no remaining weights in the rep-period weight table (and no remaining unmatched actual periods)

Additional changes

  • I moved most of the portable functions from reeds.inputs_processing.hourly_repperiods into reeds.timeseries
    • Reworked a few to cut down on code duplication
  • Tweaked reedsplots.plot_repdays() to include the year when GSw_HourlyWeatherYears has more than one weather year
  • Moved the determination of nextszn from 2_temporal_params.gms to hourly_repperiods.py, which cuts off roughly 1 hour of solve time per model year when using 7-15 weather years
  • Changed the Pacific_rep7 test case to Pacific_rep15, which uses the new method

Switches added/removed/changed

  • GSw_HourlyClusterMapMethod (default milp): How to map actual periods to representative periods: 'milp' minimizes sum of absolute errors but is slow; 'bestfirst' is orders of magnitude faster when using many weather years in GSw_HourlyWeatherYears

Issues resolved

Known incompatibilities

  • 7- or 15-year runs are still slow, but can be accelerated by setting:
    • GSw_H2 = 0
    • GSw_H2_PTC = 0
    • GSw_StartCost = 0

Validation, testing, and comparison report(s)

Compare report is here: 20260522 - rep15.pptx

  • Changes to the USA_defaults case are within the noise (≤0.05 GW, ≤0.01 $B) (nonzero change is expected because I rounded some temporal parameters that were not rounded before)
  • If we switch to 15 weather years without changing anything else, the model runs into an infeasibility in 2032. There's no conflict info though; all I get is the following message.
    Infeasibility model not feasible; tightening tolerances.
    Infeasibility model infeasible!
    Problem is feasible; no conflict available.
    
  • If GSw_StartCost=0, GSw_H2=0, and GSw_H2_PTC=0, the 15-year case solves in 12 hours. A comparison to the default 1-year case with the same settings is included in the compare report linked above.

Checklist for author

Details to double-check

  • Charge code provided to reviewers
  • Included comparison reports for appropriate test cases
  • Documentation updated if necessary (if/when we change the default, I'll add a description of the new method to model_documentation.md)
  • Code formatting standardized
  • Reusable functions used where possible instead of copy/pasted code

General information to guide review

  • Zero impact on results of default case
  • No large data file(s) added/modified
  • No substantive impact on runtime for full-US reference case
  • No substantive impact on folder size for full-US reference case
  • No change to process flow (runreeds.py, reeds/core/solve/solve.py)
  • No change to code organization
  • No change to package requirements (environment.yml or Project.toml)

Did you use LLM tools (chatbot or copilot) in the preparation of this PR? If so, describe how

No

@github-actions github-actions Bot added the tests label May 23, 2026
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.

Draw representative periods from all weather years (or reproduce the all-year average)

1 participant