Skip to content

2025 Supply Curves Update - #183

Open
bsergi wants to merge 45 commits into
mainfrom
bs/supply_curves
Open

bsergi wants to merge 45 commits into
mainfrom
bs/supply_curves

Conversation

@bsergi

@bsergi bsergi commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Updates the offshore wind and enhanced geothermal (EGS) supply curves to their 2025 versions and addresses bugs in hourlize.

Remaining to-do items:

  • Update offshore wind profiles on Zenodo.
  • Update documentation reference to 2025 reV supply curve report when available.
  • Copy supply curve data from HPC to nrelnas01 and Yampa

Technical details

  • Updated the wind-ofs and EGS supply curves to their 2025 versions as provided by the reV team.
    • Both upv and wind-ons were already using 2025 but were re-run with hourlize to confirm, which resulted in slight changes to the class assignment of some supply curve points but no changes to the total capacity
  • Updated the rev_paths.csv to include the latest paths for all technologies.
  • Fixed hourlize to work with changes introduced in Adding technology classes #12 and did some general maintenance
    • Added copy_rev_folders.py with a function to automate copying the reV data using rsync when an hourlize run is launched.
    • Removed the cases.json files; these were unnecessary once we stopped having separate supply curves by spatial resolution. The cases to run is now determined from the rev_paths.csv file, with the option to subset via arguments to run_hourlize.py
  • Updated documentation figures
    • Added a new script for reproducing these figures to docs/source/plotting_scripts; this script relies on the existing input_plots.map_supplycurves function with a few small tweaks.
    • The reV documentation report for the 2025 supply curves should be released soon, at which point we can update the references in the documentation and on Zenodo.

Issues resolved

Addresses hourlize portion of #158 .

Validation, testing, and comparison report(s)

Total capacity supply curve capacity before and after (see updated figures in the docs for the maps):

sc_totals_all (1)

All three access cases successfully solve. Changes in capacity vary depending on the case but are generally < 40 GW.

Reference:
image

Open:
image

Limited:
image

Compare cases reports:

Checklist for author

Details to double-check

  • Charge code provided to reviewers
  • Included comparison reports for appropriate test cases
  • Documentation updated if necessary
  • If input data added/modified:
    • Dollar year recorded and converted to 2004$ for GAMS
    • Timeseries are in Central Time
    • Units are specified
    • Preprocessing steps have been documented and committed to ReEDS_Input_Processing
    • New large data files handled with .h5 instead of .csv
    • If new parameters are added to d_objective.gms, they are included in objective_function_params.yaml for completeness checking
    • If spatially resolved inputs are modified, the following visualizations for each file are included in the PR description (time-averaged if the inputs are time-resolved):
      • Map of absolute values before
      • Map of absolute values after
      • Map of differences: (after - before) or (after / before)
    • If entries are added/removed/changed in the EIA-NEMS unit database:
      • Changes have been committed to ReEDS_Input_Processing
      • hourlize/resource.py was rerun to regenerate the existing/prescribed VRE capacity data
  • 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

I used copilot to help draft initial versions of the copy_rev_folders.py and supply_curve_plots.py scripts, which I subsequently modified and tested on my own.

Tag points of contact here if you would like additional review of the relevant parts of the model

bsergi added 28 commits August 4, 2026 13:14
@bsergi
bsergi marked this pull request as ready for review August 18, 2026 15:33

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.

We should probably recreate Fig29. for EGS technical potential since the supply curve is updated? Or since reV supply curves for geohydro are forthcoming so we could update it for both technologies together later.

@bsergi bsergi Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good point. I took a first pass at recreating the EGS portion and got the following:

supplycurve-egs

The map looks pretty different from what's in the docs, and the total supply curve capacity here (~13 TW) is lower than the ~17 GW of near-field + deep EGS listed in Table 6. This might be because the original map shows the full technical potential whereas this one shows what goes into ReEDS after picking the best resources at each depth. Do you know if that's the case or if something else if going on here?

As for hydrothermal I think we might consider dropping that figure for now since it isn't supported by the model and then adding it back in once we get the updated reV data.

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.

This is very handy!

Comment thread hourlize/run_hourlize.py

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.

Since the parser arguments have been modified we'll need to update README.md - specifically setup for reV supply curves, running hourlize sections.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated. I also did a broader cleanup of a lot of the stale config settings. Take a look and let me know what you think here.

@patrickbrown4
patrickbrown4 self-requested a review August 21, 2026 18:55

@patrickbrown4 patrickbrown4 left a comment

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.

Thanks Brian and sorry for the late followup.

  1. I updated input_diff_plots.py for the new CF and supply-curve formats; now it works for everything.
    1. Here are the results for reference access: 20260908 - supply curves.pptx. The main thing to know is that reference-access siting for offshore wind removes a bunch of sites. Unclear if it's on the basis of depth or distance from shore (my guess is depth since it's not a uniform distance); we should confirm with the reV team to make sure we understand the reasoning.
      1. Image
  2. I tried running the reference case but forgot it won't work until the new offshore wind profiles are uploaded to Zenodo. Let me know if it's helpful to talk through any of that. Once it's done I'll retry the run and then approve.
    1. Let's rerun input_diff_plots.py after the offshore wind profiles are uploaded just to double check.
  3. I'm pretty sure most of the differences in the compare report come from different representative periods, but it'd be nice to double check if not too much trouble (if helpful, I have the rep periods for a recent main-branch run at /projects/reedsweto/pbrown/github/ReEDS/inputs/temporal/period_szn_user_v20260911_mainK0_USA_defaults.csv; can copy these and then set GSw_HourlyClusterAlgorithm = user_v20260911_mainK0_USA_defaults).

Comment on lines +897 to 914
{numref}`geothermal-technical-resource-potential` lists the technical resource potential for the different geothermal categories.

```{table} Technical Resource Potential (GW)
:name: technical-resource-potential
:name: geothermal-technical-resource-potential
| **Resource Class** | Reservoir Temperature **(°C)** | **Hydrothermal** | **Near-Field EGS** | **Deep EGS** |
|:------------------:|:------------------------------:|:----------------:|:------------------:|:------------:|
| Class 1 | \> 325 | \- | 0.2 | 7.3 |
| Class 2 | 300–325 | 2.2 | 0.2 | 35 |
| Class 3 | 275–300 | 1.2 | 0.1 | 177 |
| Class 4 | 250–275 | 0.7 | 0.1 | 1696 |
| Class 5 | 225–250 | 0.2 | 0.1 | 4633 |
| Class 6 | 200–225 | 0.9 | 0.2 | 6467 |
| Class 7 | 175–200 | 12 | 0.3 | 3234 |
| Class 8 | 150–175 | 342 | 0.3 | \- |
| Class 9 | 125–150 | 2823 | 0.03 | \- |
| Class 10 | \<125 | 699 | \- | \- |
| Total | | 3881 | 1.4 | 16249 |
| Class 1 | \> 325 | \- | 0.2 | 544 |
| Class 2 | 300–325 | 1.8 | 0.2 | 18 |
| Class 3 | 275–300 | 9.3 | 1.3 | \- |
| Class 4 | 250–275 | 0.7 | 8.3 | \- |
| Class 5 | 225–250 | 1.1 | 74 | 1 |
| Class 6 | 200–225 | 2.4 | 320 | 169 |
| Class 7 | 175–200 | 0.2 | 709 | 3509 |
| Class 8 | 150–175 | 2.6 | 996 | 8012 |
| Class 9 | 125–150 | 1.1 | 1268 | 686 |
| Class 10 | \<125 | 4.7 | \- | 8 |
| Total | | 23.9 | 3377 | 12947 |
```

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.

I think it'd be ok to remove this table since 1) we don't show similar tables for wind/solar and 2) it's hard to remember to keep it up to date, but your call since you've already updated it.
(Ideally it might be nice to have a jupyter notebook with questions like "What's the technical potential of PV/wind/geothermal" and little code blocks that pull it from the repo and display it, both to illustrate where to find things and to automate the table creation, but that'd be a different PR obviously. (And it might still be hard to remember to run it.))

Comment thread hourlize/README.md
* on the nrelnas01 device at `\\nrelnas01\ReEDS\Supply_Curve_Data`
* on Eagle at `/shared-projects/reeds/Supply_Curve_Data`
* on Kestrel at `/kfs2/shared-projects/reeds/Supply_Curve_Data`
The `srun_template.sh` file is used to govern HPC submission settings. Update with your allocation, email, and any other slurm specifications before submitting jobs. There is also a command line argument to via `run_hourlize.py` for running jobs using the debug partition.

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 seems like we could drop this copy and just use reeds/hpc/srun_template.sh for everything (and avoid having two files with the same name), but your call.

Comment thread hourlize/README.md
| scale_factor | Factor used to scale capacity-factor values when writing hourly profiles | 1e4 |
| state_abbrev | Path to the state-abbreviation file | '{hourlize_path}/inputs/resource/state_abbrev.csv' |
| subsetvars | Columns in `rev_paths_file` used to select the appropriate reV path | ['tech', 'access_case'] |
| subtract_exog | Legacy flag passed to supply-curve output processing; currently has no effect | false |

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.

I'd just remove this row (and the argument)

Comment thread hourlize/resource.py
Comment on lines +829 to +830
#%% copy reV folders
copy_rev_folders.main(cf.rev_paths_file, [cf.tech], overwrite=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.

I might be misinterpreting but does this mean that every time someone runs hourlize (even just for testing), it will overwrite shared files that R2X depends on? That seems risky to me. Could we make it controlled by a switch that is off by default?

Comment thread hourlize/run_hourlize.py
elif args.mode == "resource":
setup_resource(args)
else:
print("Unsupported method for hourlize")

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.

I would print the mode and raise an error

Suggested change
print("Unsupported method for hourlize")
raise ValueError(f"Unsupported method for hourlize: {args.mode}")

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