NREL / floris

A controls-oriented engineering wake model.
http://nrel.github.io/floris
BSD 3-Clause "New" or "Revised" License
216 stars 156 forks source link

Bug report: shape mismatch error when evaluating yaw angles with zero-frequency entries in the wind rose #963

Open Bartdoekemeijer opened 3 months ago

Bartdoekemeijer commented 3 months ago

Shape mismatch error when evaluating yaw angles with zero-frequency entries in the wind rose

I tried to evaluate wake steering for one of our sites, and got an error message. I have created a minimal reproducible script and found that the error arises when there are entries in the wind rose with zero frequency.

How to reproduce

Here's a minimal reproducible script:

import numpy as np
from floris import FlorisModel, WindRose

# Create FLORIS model with 3-turbine layout
fmodel = FlorisModel("examples/inputs/gch.yaml")
fmodel.set(layout_x=[0, 126 * 5, 126 * 10], layout_y=[0, 0, 0])

# Set up a wind rose
wd_array = np.arange(0.0, 360.0, 30.0)
ws_array = np.arange(1.0, 25.01, 1.0)
wd_grid, ws_grid = np.meshgrid(wd_array, ws_array, indexing="ij")
freq_grid = np.ones_like(wd_grid)
freq_grid[0, 0] = 0.0  # Force one entry to zero
freq_grid = freq_grid / np.sum(freq_grid)
wind_rose = WindRose(wind_directions=wd_array, wind_speeds=ws_array, ti_table=0.06, freq_table=freq_grid)

# Set up a set of yaw angles
yaw_angles = 25.0 * np.ones((len(wind_rose.wd_flat), len(fmodel.layout_x)))

# Evaluate FLORIS with the wind rose
fmodel.set(wind_data=wind_rose, yaw_angles=yaw_angles)
fmodel.run()
turbine_powers = fmodel.get_turbine_powers()

Relevant output

I receive the following error with

Exception has occurred: IndexError
shape mismatch: indexing arrays could not be broadcast together with shapes (300,1) (299,3) 
  File "/mnt/c/Users/Bart.Doekemeijer/OneDrive - Shell/Documents/python_scripts/floris_v4/floris/core/farm.py", line 234, in initialize
    self.yaw_angles_sorted = np.take_along_axis(
                             ^^^^^^^^^^^^^^^^^^^
  File "/mnt/c/Users/Bart.Doekemeijer/OneDrive - Shell/Documents/python_scripts/floris_v4/floris/core/core.py", line 147, in initialize_domain
    self.farm.initialize(self.grid.sorted_indices)
  File "/mnt/c/Users/Bart.Doekemeijer/OneDrive - Shell/Documents/python_scripts/floris_v4/floris/floris_model.py", line 468, in run
    self.core.initialize_domain()
  File "/mnt/c/Users/Bart.Doekemeijer/OneDrive - Shell/Documents/python_scripts/floris_v4/examples/005_getting_power.py", line 26, in <module>
    fmodel.run()
IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (300,1) (299,3) 

Floris version

The latest FLORIS main branch (v4.1.1, 2c3be).

System Information

Ubuntu 22.04.3 LTS. numpy==1.26.4.

paulf81 commented 3 months ago

Hi @Bartdoekemeijer, thank you for catching this! As a quick fix, if you change line 16 to:

wind_rose = WindRose(wind_directions=wd_array, wind_speeds=ws_array, ti_table=0.06, freq_table=freq_grid, compute_zero_freq_occurrence=True,)

That removes the error for me, but I'll get with @misi9170 on a more general solution soon

Bartdoekemeijer commented 3 months ago

Hi @paulf81, thanks for the quick reply! The OpRose PR in #964 seems helpful but perhaps also not necessary? It may just be an extra class to create, document and maintain but that receives limited usage. I think it's fair to expect people to switch to the new FLORIS timeseries format. On my end, it seems totally manageable.

On the issue -- With my very limited understanding, I think the FlorisModel reduces the evaluation dataset to remove zero-frequency entries. So if your wind rose (or timeseries) has 30x25 values and with three zero-frequency entries, you have 750-3=747 findices that you need to evaluate. The variables inside FlorisModel are reduced to 747 findices to evaluate the reduced dataset, but that same reduction does not happen for the control variables. I would assume just extending the variable reduction to the control variables would resolve the issue.

Let me know if I'm totally wrong here!

misi9170 commented 1 week ago

@Bartdoekemeijer just seeing we never responded to your message here---yes, that is what is happening (the dropped zero frequency calculations are not mapped onto the control setpoints). It is likely possible to fix this with a patch of some sort, but we'd need to do it for every type of control setpoint, which won't be very well future-proofed against possible future control setpoints. We have internally been having a discussion regarding how to handle control setpoints more thoroughly---I will create a discussion for this now.