Skip to content

Add per-turbine timeseries air density support#47

Open
bjarketol wants to merge 9 commits intoEUFLOW:mainfrom
bjarketol:pywake-air-density-support
Open

Add per-turbine timeseries air density support#47
bjarketol wants to merge 9 commits intoEUFLOW:mainfrom
bjarketol:pywake-air-density-support

Conversation

@bjarketol
Copy link
Contributor

Summary

  • Pass density from wind_resource as the Air_density simulation kwarg to PyWake's wind farm model, enabling DensityScale to correctly scale power output
  • Drop density from the XRSite dataset where PyWake was silently ignoring it
  • Extract per-turbine or uniform density in the timeseries branch, mirroring the existing operating flag pattern
  • Enhance the density test to verify that density actually affects AEP results

Changes

  • wifa/pywake_api.py: Drop density from site dataset, initialize air_density, extract density in timeseries branch, add Air_density to sim_kwargs
  • tests/conftest.py: New shared test fixture make_timeseries_per_turbine_system_dict with per-turbine density data
  • tests/test_pywake.py: Enhanced test comparing AEP with and without density
  • pyproject.toml: Add tests to pythonpath so conftest is importable

Test plan

  • test_pywake_dict_timeseries_per_turbine_with_density passes and verifies density affects AEP
  • All 11 pywake tests pass with no regressions
  • Full test suite passes (except pre-existing test_cs.py failures unrelated to this change)

🤖 Generated with Claude Code

@bjarketol bjarketol force-pushed the pywake-air-density-support branch from 6522e1b to 2a75ee1 Compare February 11, 2026 20:57
@bjarketol
Copy link
Contributor Author

@kilojoules can you review this one?

@bjarketol
Copy link
Contributor Author

@SchmJo

@SchmJo
Copy link
Contributor

SchmJo commented Feb 17, 2026

@bjarketol I rebased this on #48 such that now also foxes passes a similar turbine-based timeseries test with air density

@bjarketol bjarketol force-pushed the pywake-air-density-support branch from 5796c21 to e9ad394 Compare February 19, 2026 14:18
@SchmJo
Copy link
Contributor

SchmJo commented Feb 19, 2026

I am not a fan of numpy < 2, since it blocks future updates of numpy. Can we convince the wayve team to replace np.trapz by np.trapezoid instead? @koendev

@koendev
Copy link

koendev commented Feb 19, 2026

As far as I can tell, it's essentially the same function, just renamed? If that's the case I can refactor the code to handle that, yes. Would any other changes be needed?

@bjarketol
Copy link
Contributor Author

@koendev, you can use something like the code below to support both numpy 1 and 2:

        _trapezoid = np.trapezoid if hasattr(np, "trapezoid") else np.trapz
        U3 = _trapezoid(np.interp(z, zs, us), z) / (15.0e3 - h)
        V3 = _trapezoid(np.interp(z, zs, vs), z) / (15.0e3 - h)

@kilojoules
Copy link
Member

Adresses #31

Copy link
Member

@kilojoules kilojoules left a comment

Choose a reason for hiding this comment

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

Looks great

pyproject.toml Outdated
"foxes @ git+https://github.com/FraunhoferIWES/foxes.git@eu_flow",
"windIO @ git+https://github.com/EUFlow/windIO.git",
"wayve @ git+https://gitlab.kuleuven.be/TFSO-software/wayve@dev_foxes",
"numpy<2.0",
Copy link
Member

Choose a reason for hiding this comment

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

I would like to support numpy > 2

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, agree, once @koendev has a numpy 2 update ready for wayve ready we can change the pin

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Loosened the numpy pin to "numpy>=1.22,<3.0"

kilojoules added a commit that referenced this pull request Feb 20, 2026
@kilojoules
Copy link
Member

@koendev, you can use something like the code below to support both numpy 1 and 2:

        _trapezoid = np.trapezoid if hasattr(np, "trapezoid") else np.trapz
        U3 = _trapezoid(np.interp(z, zs, us), z) / (15.0e3 - h)
        V3 = _trapezoid(np.interp(z, zs, vs), z) / (15.0e3 - h)

I thied this and I can't get it to work. Tests are still failing.

#49

@bjarketol
Copy link
Contributor Author

@koendev, you can use something like the code below to support both numpy 1 and 2:

        _trapezoid = np.trapezoid if hasattr(np, "trapezoid") else np.trapz
        U3 = _trapezoid(np.interp(z, zs, us), z) / (15.0e3 - h)
        V3 = _trapezoid(np.interp(z, zs, vs), z) / (15.0e3 - h)

I thied this and I can't get it to work. Tests are still failing.

#49

It needs to be fixed upstream in wayve

@koendev
Copy link

koendev commented Feb 24, 2026

Hi all, wayve has been updated to use numpy >2. Please use the main branch, the couplings to foxes and PyWake are available there as well.

bjarketol and others added 4 commits February 24, 2026 19:34
Pass density from wind_resource as the Air_density simulation kwarg so
PyWake's DensityScale model correctly scales power output. Previously
density was embedded in the XRSite dataset where PyWake silently ignored it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The wayve dependency uses np.trapz extensively, which was removed
in NumPy 2.0. Pin numpy<2.0 until wayve is updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bjarketol bjarketol force-pushed the pywake-air-density-support branch from 0de3ab2 to 74b9ebf Compare February 24, 2026 18:35
@bjarketol bjarketol requested a review from kilojoules February 25, 2026 09:08
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.

4 participants