Skip to content

dataset: add bias-corrected wind speeds from Copernicus - #535

Open
jome1 wants to merge 4 commits into
PyPSA:masterfrom
jome1:era5_wind_corrected
Open

jome1 wants to merge 4 commits into
PyPSA:masterfrom
jome1:era5_wind_corrected

Conversation

@jome1

@jome1 jome1 commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Closes #531

Note

This PR was assisted by AI. The new data module era5_corrected.py is based on the existing era5.py module.

There are probably smarter ways to handle the features. I am also unsure of the naming. One needs to be aware to not mix it with the ERA5 features.
I didn't test everything but for me it works quite well. Would be great if someone could have a look at the PR. There are probably things that can be improved or made more precise.
The differences in capacity factor between ERA5 and ERA5corrected can be quite large.

Changes proposed in this Pull Request

New module atlite/datasets/era5_corrected.py (registered as "era5-corrected"). It downloads the C3S Energy bias-corrected ERA5 wind data (CDS dataset sis-energy-global-reanalysis). Bias-correction is based on GWA2 (see product user manual)

Selectable features (use in cutout.prepare(features=[...])):

Feature Variable CDS source
wind_corrected wnd100m_corrected 100m_wind_speed
wind_corrected_extrapolated wnd100m_corrected_extrapolated 100m_wind_speed_extrapolated
wind_shear_exp_corrected wnd_shear_exp_corrected wind_power_law_coefficients
  • Each feature makes its own API request, which keeps request sizes small.
  • Monthly files: the CDS zip holds one NetCDF per month. All of them are now read and concatenated on time. A whole year in one request works, and so do monthly_requests=True in prepare().
  • wind power law coefficients (shear exponent): The shear exponents provided Copernicus are a month-by-hour climatology (288 steps) that is the same for every year (every day within a month has the same 24h shear exponent profile, but differs per month, more info here). They are requested once and mapped onto the cutout timestamps by (month, hour).
  • Cutouts longer than 12 months are rejected (limited API request size) and only the native 0.25° grid is supported.

atlite/datasets/era5.py and era5_edh.py:

  • New standalone roughness feature (the wind feature still includes it), because the default for extrapolation to different heights is logarithmic which needs roughness.

atlite/data.py:

  • The temp file is renamed with retries.
  • The old file's handle is closed and gc.collect() is called first.

Other:

  • atlite/wind.py: base-height regex changed to fullmatch. --> I dont know why AI did this.

What to consider when using era5-corrected

  1. Extrapolation to other heights. cutout.wind only uses wnd100m and wnd_shear_exp, so assign the corrected variables first:
    cutout.data["wnd100m"] = cutout.data["wnd100m_corrected"]  # or ..._extrapolated
    cutout.data["wnd_shear_exp"] = cutout.data["wnd_shear_exp_corrected"]
    cutout.wind(turbine, interpolation_method="power")
    These assignments are not saved to disk, so repeat them after reloading the cutout.
  2. Roughness (logarithmic method). The corrected data has no roughness. Use the roughness feature from era5/era5-edh together with interpolation_method="logarithmic".
  3. Shear exponent is a climatology. wnd_shear_exp_corrected is an average by month and hour, not a time series. It does not follow weather variability, unlike the ERA5 wnd_shear_exp.
  4. Pairing. Use the shear exponent that matches the wind speed you extrapolate from. Mixing ERA5 speeds with the corrected exponent (or the reverse) will give inconsistent profiles.
  5. Module order and features. Combine the modules, e.g. module=["era5-edh", "era5-corrected"], and name the features explicitly in prepare().
  6. Limits.
    • At most 12 months per cutout.
    • Only the 0.25° grid.
    • Requires CDS credentials in ~/.cdsapirc.

Image below compares the raw mean wind speeds at 100m (DK, DE, Alpes):
image

Image below shows the difference in mean wind between ERA5 and ERA5 corrected (100m)
image

You can compare image above loosely with Nayak et al. (different units though)
image

Image below shows the hourly shear factor (mean area).
image

Checklist

  • Code changes are sufficiently documented; i.e. new functions contain docstrings and further explanations may be given in doc.
  • Unit tests for new features were added (if applicable).
  • Newly introduced dependencies are added to environment.yaml, environment_docs.yaml and setup.py (if applicable).
  • A note for the release notes doc/release_notes.rst of the upcoming release is included.
  • I consent to the release of this PR's code under the MIT license.

@jome1

jome1 commented Oct 13, 2026

Copy link
Copy Markdown
Contributor Author

I am using the following notebook for my own tests:

atlite_ERA5corrected_test.ipynb

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support dataset Global climate and energy indicators from 1950 to present derived from reanalysis

1 participant