Exawind / amr-wind

AMReX-based structured wind solver
https://exawind.github.io/amr-wind
Other
103 stars 78 forks source link

Underestimated power predictions from OpenFAST/ALM turbine models in unsteady flows #1009

Closed lawrenceccheung closed 2 months ago

lawrenceccheung commented 3 months ago

I am working with @jfrederik-nrel, @ndevelder, @gyalla, and others at NREL/SNL regarding a turbine performance issue that we see with OpenFAST/ALM runs in unsteady ABL runs.

The problem is observed with the IEA 15MW reference turbine, although we need to investigate if it's seen for other models. In steady, uniform flow, the actuator line parameters (grid spacing, epsilon, number of blade points) can be calibrated so that the turbine predictions are relatively accurate across a range of wind speeds when compared against the design curves. However, when the same turbine is used in an unsteady inflow created through a precursor ABL, the power predictions are noticeably lower. image

This case is for a precursor with hub-height wind speed 9m/s, shear exponent ~0.17, and 3.7% TI, and using OpenFAST 3.4.1 with ROSCO 2.8. We've tested several combinations, including using an equivalent Joukowski disk model, and they suggest that the wind power available to the turbine should be close to the uniform flow case, but is not being extracted through the ALM model.

Other debugging tests we've tried indicate that it may not be the fault of the controller (fixing rotor speed to the correct value leads to a similar problem), that shear effects don't have strong effect, and OpenFAST alone calculations with turbsim based inflow are reasonably matching expectations: image

Additional tests to be completed are to determine whether this impacts both the OpenFAST ADM models as well as ALM.

We will follow up this github issue with some additional details and information, but let us know if there are any questions.

Lawrence

marchdf commented 3 months ago

Excellent issue description. Thank you. Let me know if/how I can help.

mbkuhn commented 3 months ago

Just clarifying: the faulty points on the power curve are the orange and cyan? AMR-Wind, precursor and AMR-Wind, precursor, fixed rot-speed?

gyalla commented 3 months ago

Yes, that's correct

gyalla commented 3 months ago

Here is an example input file that corresponds to the orange dot on the power curve (ARM-Wind, precursor)

MedWS_LowTI_farmrun1_inp.txt

lawrenceccheung commented 3 months ago

Here is an example input file that corresponds to the orange dot on the power curve (ARM-Wind, precursor)

MedWS_LowTI_farmrun1_inp.txt

Thanks @gyalla. In case anybody wants to try testing this, we have the precursor and boundary I/O files for this case on Eagle at /scratch/lcheung/2024/AdvControls/precursor6_4kmX2km_5m.bndrydata and the corresponding precursor input file at https://github.com/lawrenceccheung/ALCC_Frontier_WindFarm/blob/main/farmruns/MedWS_LowTI/template/MedWS_LowTI_precursor1_spectra.inp

tonyinme commented 3 months ago

Hi @lawrenceccheung , do you have a plane at the rotor-plane (y-z if flow is in x) of the actuator force field? We just had a long discussion with @mbkuhn and Regis, and found that the value of epsilon and spacing are not in line with recommended values.

Actuator grid spacing recommendation: epsilon/dr > 1

Grid resolution recommendation: epsilon/dx>2

jfrederik-nrel commented 3 months ago

Hi @tonyinme, I took a quick snapshot of the wind speed for precursor (left) and uniform (right) for these simulations in my precursor (neutral, 3.5% TI, 8m/s). See below.

image

I want to add though that this issue is not exclusive to low values of epsilon. I started with simulations with a higher epsilon of 4-6 (same grid size), which satisfies your recommendations, and also for these values of epsilon I experienced significant underpredictions of power.

tonyinme commented 3 months ago

Thanks @jfrederik-nrel ! Do you have that same plot but for the actuator force?

jfrederik-nrel commented 3 months ago

@tonyinme unfortunately not, I only sampled velocities on these simulations.

lawrenceccheung commented 3 months ago

I just thought of another test that we could do. We can make use of ABLForcing.velocity_timetable to ramp the wind speed from a constant $U_1$ to another speed $U_2$ over a controlled amount of time, and see how the turbine responds to it. Ideally it will settle to the constant, steady point of operation that it's supposed to, but we might be able to find out what input is getting messed up in this process.

rthedin commented 3 months ago

I've successfully run some cases using 100 actuator points and epsilon of 3.125 on a 1.25 m near-actuator grid. I checked the actuator force field with Tony yesterday for these cases.

This is what it looked like for one of the blades (the other blades are slightly out of the plane shown): Screenshot 2024-03-28 at 6 13 09 PM

And then I re-run, matching the grid resolution and actuator parameters you guys have, and this is what the actuator force field looked like: Screenshot 2024-03-28 at 6 13 17 PM

I'd be curious to see how the force field looks like in the case Joeri mentioned the choice of epsilon satisfied the requirements. Tony might have some further comments about the figures above.

marchdf commented 3 months ago

@rthedin thanks for running that. For someone new to this (like me), how am I to interpret these plots?

jfrederik-nrel commented 3 months ago

Hi Regis, very interesting, thanks for looking into that. I can definitely see how our settings as we are using here, might not be appropriate. However, as I mentioned before, for different settings I've so far seen the same problem where power is way lower for precursor simulations. Therefore I'd be very interested to learn what powers you are getting for the settings you are using, and how close these are to simulations with similar wind speeds in OpenFAST.

rthedin commented 3 months ago

I'm getting more power on the stable case, which has lower turbulence and you could argue is the closest to the uniform inflow. Here are the power values I'm getting:

Cond: stable  , Power T1: 8003.547 kW
Cond: neutral , Power T1: 7929.298 kW
Cond: unstable, Power T1: 7857.647 kW

These values were obtained with turbulent precursors with 8 m/s at 150 m. Here is a quick summary of the conditions I used: image

lawrenceccheung commented 3 months ago

Hi @rthedin, thanks for sharing that. This is interesting, because at 8m/s, the IEA 15MW is only supposed to generate around 6.3MW of power (according to the design doc), so there might be a slight overestimation of power.

jfrederik-nrel commented 3 months ago

Hm, that is very interesting. I ran a very similar case using my own 8m/s neutral precursor with refinements down to 1.25m and epsilon = 3.125, and my average power was only 6034.339 kW. That's a lot closer to the expected 6.3MW, but still lower. Also, I didn't run a uniform simulation with these settings, but I would expect that the power would also be much higher than in the precursor case here. I'm running this case now to verify.

I do have to note that there is one important difference between @rthedin and my own simulation: I'm running my case with 50 blade points, not 100. Also, I'm not sure what time step you are using? My simulation ran with a 0.05s time step. Would we really expect a power increase of ~30% when we increase the number of blade points by a factor 2 (and/or possibly decrease the time step)?

More importantly though, changing these settings affects power, but it doesn't necessarily explain why, with the same settings, power is much lower in precursor simulations than in uniform simulations. I think the core of this issue is that we want to be able to tune turbine and grid settings in uniform conditions to match expected power and thrust curves, and than apply those same settings to precursor simulations.

The issue is not that we can't get the power to match design curves, just that we need different settings at different flow conditions, which is undesirable.

tonyinme commented 3 months ago

@jfrederik-nrel can you please share the case in uniform inflow so we can take a look at the input files and some outputs from that simulation?

jfrederik-nrel commented 3 months ago

@tonyinme yes happy to share those results once they come in. Input file is attached here: simulation.i.txt

tonyinme commented 3 months ago

@jfrederik-nrel , thanks for sharing. It looks like you have 3 levels of refinement. So the grid resolution should be 1.25m near the turbine is that correct? I believe that the other simulations used only a resolution of 2.5m near the turbine?

jfrederik-nrel commented 3 months ago

Yes correct. In my original simulations, I use 2 refinements for a resolution of 2.5m near the turbine. I added a third refinement to mimic Regis' simulation with 1.25m resolution and an epsilon of 3.125 to verify that the discrepancy between uniform and precursor simulation is unrelated to turbine and grid settings.

tonyinme commented 3 months ago

ok, can you please share the results / input files of the simulation with 2.5m refinement?

mbkuhn commented 3 months ago

@lawrenceccheung @gyalla The comparison with the Joukowsky disk is informative. As far as I can tell, all actuator methods use the same velocity sampling approach to get the flow velocity at actuator points. There are still a lot of other differences, though, like the position of the points, how the forces are computed using the sampled velocities, and how the forces are applied back to the flow itself. Although there are still a lot of differences between the OpenFAST ALM and ADM, would it be helpful to compare the OpenFAST ALM results to OpenFAST ADM results? Because they both share the OpenFAST interface.

gyalla commented 3 months ago

Sorry for the delay in getting the ADM results -- there was a change in the module systems on our end that caused a bit of a slowdown. I've added a point on the power curve I shared earlier for the ADM with precursor as well as a two-minute time series.

image image

The ADM-precursor lands in between the ALM-precursor and ALM-uniform results, with a 12% loss in power (compared to 21% for ALM-precursor). This is with the same epsilon and resolution as the ALM case (epsilon=2.0, dx=2.5m)

jfrederik-nrel commented 3 months ago

@tonyinme @mbkuhn I've also looked at the case with eps=3.125 and grid size=1.25 at turbine rotor to check whether the actuator grid spacing ratio causes the difference in power. It seems like this is not the case, or only barely. For the eps=3.125, dx=1.25 case, I still see power being over 15% lower in a precursor simulation w.r.t. a uniform simulation. See plot below.

image

lawrenceccheung commented 3 months ago

For another data point on the ADM runs, we've been running some comparisons using a neutral 6.3 m/s precursor and the NREL 2.8-127 turbine model. Using the OpenFAST+ADM model in AMR-Wind and Nalu-Wind gives consistent power results with the design curve and the uniform flow cases: image

We're still looking at thrust and other wake-centric quantities, so I won't say that the ADM model is perfect, but it doesn't drastically underestimate power like the IEA15MW ALM cases do.

Lawrence

mbkuhn commented 3 months ago

Looking at that curve, Lawrence, there's no comparison between the precursor and the uniform. The precursor points are both below the curve and the uniform points are all above it. There could easily be a 12% boost to the precursor points, like in Gopal's run, and it would still look "close". Seems like the same pattern exists for the ADM cases, just to a lesser extent compared with the ALM. Which makes me wonder how we know what is "right" and what is a reasonable amount of error. For the first red square, it's actually a significant percentage above the power curve for the same WS. Should this be a concern?

It may be helpful to run that Nalu-Wind ADM case with a uniform inflow and see how much it deviates. If there is a significant deviation, along the same lines as the AMR-Wind ADM case, it would indicate to me that it is not a problem with the AMR-Wind implementation; it is a problem with how we use OpenFAST or it is model error.

mbkuhn commented 3 months ago

BIG Update, and something that will soon lead us to figuring out this problem.

I ran a uniform flow case (green curve) with the same domain, flow direction, turbine (including the yaw angle) as Joeri's precursor case. This led to getting the same power as the precursor (turbulent ABL inflow) case (orange curve), not the same power as Joeri's uniform case (blue curve). This is a clear indication that the discrepancy between uniform and precursor-based results is not due to the presence of turbulence; it must be due to the difference in the setup between the two cases.

Our current hypothesis is that the yaw angle is being somehow misinterpreted within the AMR-Wind - OpenFAST framework. We have some other runs going to try to confirm that hypothesis. As it stands, if we take the 5.4 MW results from the diminished cases and divide that by cos(30 degrees), we get 6.2 MW, which is in the ballpark of the 6.7 MW results from the original uniform case. It's not enough to confirm anything other than the possibility of a bug related to yaw. image (6)

jfrederik-nrel commented 3 months ago

Thanks for the update Michael, this is very very informative! To clarify: in my cases, the wind direction is 240 for the precursor case, and 270 for the uniform case. As the default in OpenFAST is facing west (270 degrees in AMR), I set the yaw angle (in ElastoDyn > NacYaw) to 30 degrees for the precursor case, and 0 degrees for the uniform case. I've also checked the wakes in these simulations, which indicate that there is no wake steering going on, and the turbines seem to be properly aligned with the wind. One question I have based on this hypothesis: do the runs from @gyalla also have a wind direction mismatch between the uniform and precursor cases? As far as I am aware, both those cases run at 270 degrees, right? So in that case, we wouldn't expect a power mismatch if @mbkuhn's hypothesis is correct, would we?

gyalla commented 3 months ago

Good find Michael, and thanks for the update! @jfrederik-nrel is correct that all of the cases I've done so far are run at 270 degrees.

rybchuk commented 2 months ago

Dropping in with a comment just FYI. There are two places that yaw is specified for an individual turbine in an AMR-Wind simulation, one is in the .i file (example) and one is in the OpenFAST file. I have the impression that only one of these gets used in the code, and I also have the impression that these are both defined in different coordinate systems. Something to keep in mind.

jfrederik-nrel commented 2 months ago

Hi @rybchuk, thanks for your comment. I am aware that there are two placed where the yaw is defined and that they use different coordinate systems (for AMR, 0 is north and positive direction is clockwise as seen from above, for OpenFAST 0 is west and positive direction is counterclockwise). However, as I mentioned in one of my previous posts, we also looked at the wakes behind the turbine, and they do show a wake that is not steered by the turbine, indicating that at least in AMR-Wind, there is no yaw misalignment.

mbkuhn commented 2 months ago

I looked into the example and the code and can confirm that yaw is only specified to AMR-Wind for actuator disks, not actuator lines. We'll keep this in mind if we look at actuator disk behavior more, but the majority of the cases we've looked at are for actuator lines.

psakievich commented 2 months ago

I looked into the example and the code and can confirm that yaw is only specified to AMR-Wind for actuator disks, not actuator lines.

Maybe this is what was meant by acutator disks, but to be explicit here, yaw is only for non-openfast actuator disks. Any openfast model (ALM or ADM) relies solely on the openfast parameters.

gyalla commented 2 months ago

To follow up from our discussion on Monday, I've repeated the uniform flow case with the same grid as the precursor flow. Recall that the previous uniform cases were run on a grid with three refinements from 20m to 2.5m: image image where as the precursor cases and the new uniform case are run on a grid with one refinement from 5m to 2.5m: image image

There is a no significant change in power between the two uniform cases. In fact, the new uniform case has around a 1.5% increase from the previous. This aligns with our thought experiment from Monday that there should be slightly more power in the precursor-grid since the 2.5m mesh has a larger extent, although it is a bit curious for a purely uniform flow. Nonetheless, here are the power curves with the three cases: image as well as time series from several cases: image

Note that the uniform flow cases (without shear) are run using periodic boundary conditions, whereas the precursor cases are inflow/outflow, so there is still that difference. I can repeat the uniform case with inflow/outflow BCs if anyone thinks it's worthwhile.

I was also looking at blade loading so I figured I'd send over those plots as well for all the cases: image image

marchdf commented 2 months ago

I can repeat the uniform case with inflow/outflow BCs if anyone thinks it's worthwhile.

I would think that it would be worth it if it's not too much hassle. Just to be sure.

A follow-up question: could you extract mean velocity fields (at HH for example)? I would be curious to see if there is a momentum difference in the precursor flow sims.

mbkuhn commented 2 months ago

Which boundary conditions are periodic for the uniform cases? If the x boundary conditions are periodic, then wouldn't the turbine be in its own wake?

gyalla commented 2 months ago

Sorry for the confusion -- all of the cases, including the uniform ones, are run with mass inflow / pressure outflow boundary conditions. It seems some Friday-afternoon brain-fog made it's way into my last message, but I've updated it retroactively. Sorry again!

mbkuhn commented 2 months ago

@gyalla do you have velocity information as a function of axial position, like you have for the blade loading? It would be valuable to see if there are differences in wind speed or angle of attack.

gyalla commented 2 months ago

I have similar figures for angle of attack and relative wind-speed as a function of axial position: image

image

As well as timeseries of the two:

image

image

These are both variables coming out of openFAST, namely AB1N[0-50]Alpha and AB1N[0-50]Vrel.

mbkuhn commented 2 months ago

@gyalla , thanks for sharing the precursor-based turbine run input file (MedWS_LowTI_farmrun1_inp.txt). Could you also share the input file for your uniform flow case? Can be the original one or the precursor grid one.

gyalla commented 2 months ago

Sure thing! Here is the uniform flow input file for the case with the precursor grid:

uniform_precursor_grid_inp.txt

as well as for the original grid I shared with 3 mesh-refinements:

uniform_original_grid_inp.txt

mbkuhn commented 2 months ago

Hey all, I have found the root of the problem.

It comes down to the specification of density for the turbine in the input file. When an OpenFAST turbine type is used, the code looks for a density specified for that turbine. This is intended to match the AirDens parameter in the OpenFAST turbine model because it is used to normalize the forces coming from the OpenFAST model. However, for no good reason, this AMR-Wind input argument (in the form Actuator.TurbineFastLine.density for an ALM run) is not required for the code to run, and if it is absent, a default value of 1.0 will be used instead. As a result, for our cases with air densities around 1.2, the omission of this input argument leads to the forces from OpenFAST being erroneously scaled up by ~20%, leading to a slowdown of the flow in front of the turbine. This percent difference is roughly the power difference that we have been seeing between the precursor-based runs (which omitted the density argument) and the uniform runs (which included it). Although this is a setup issue, it was repeated in both Joeri's and Gopal's input files, which I have shown in the code block below.

The proof of this issue is shown in the figure, which demonstrates that a precursor-based run aligns with the original uniform run when the actuator density argument is included. This figure also confirms that the reason I was able to get a uniform case to align with the original precursor-based run was because I had used the precursor-based actuator input arguments exclusively, which omitted density.

I want to admit that finding such a simple fix to a seemingly baffling problem is disappointing, and it's surprising that it took so long. Nevertheless, I think it's important to not focus on blame -- though it comes down to the setup, this is poor code design and poor UI design. Moving forward, we will modify the code and the interface to make sure that errors like this are impossible to make. For a code that is overwhelmingly used as a constant-density solver, density should never be an issue. As a side note, the standalone actuator models in AMR-Wind (uniform_ct and Joukowsky disks) do not take an input density argument, instead directly sampling the density from the flow variable.

$ grep -hi "density" jfrederi_120_uniform_simulation.i 
incflo.density             = 1.225             # Reference density 
Actuator.TurbineFastLine.density = 1.225
ConstValue.density.value = 1.225
xlo.density = 1.225

$ grep -hi "density" jfrederi_030_precursor_abl_turbine.i 
incflo.density                           = 1.225         # Reference density
xlo.density                              = 1.225               
ylo.density                              = 1.225           

$ grep -hi "density" gyalla_uniform_original_grid_inp.txt 
incflo.density                           = 1.225               # Fluid density [kg/m^3]
ConstValue.density.value                 = 1.225               
xlo.density                              = 1.225               
Actuator.TurbineFastLine.density         = 1.225         

$ grep -hi "density" gyalla_uniform_precursor_grid_inp.txt 
incflo.density                           = 1.225               # Fluid density [kg/m^3]
ConstValue.density.value                 = 1.225               
xlo.density                              = 1.225               
Actuator.TurbineFastLine.density         = 1.225            

$ grep -hi "density" gyalla_MedWS_LowTI_farmrun1_inp.txt 
incflo.density                           = 1.2456              # Fluid density [kg/m^3]
xlo.density                              = 1.2456  

GenPwrComparison

lawrenceccheung commented 2 months ago

Thanks @mbkuhn for finding this, great work!

Lawrence

psakievich commented 2 months ago

I want to admit that finding such a simple fix to a seemingly baffling problem is disappointing, and it's surprising that it took so long.

FWIW it has been my experience that this description fits a majority of the hardest bugs I've dealt with. So subtle and small that they keep getting overlooked. Great job being persistent and finding the resolution @mbkuhn!

lawrenceccheung commented 2 months ago

In case this is useful to anyone, I've updated amr-wind-frontend so that it will now automatically set all of the required densities consistently, including the Actuator.TurbineFast[Line|Disk].density, incflo.density, and AirDens in all OpenFAST turbines. It will also warn you about mismatched densities if you use the validate() routine.

Hopefully this will help with setup problems like this, at least until the next time density is changed in amr-wind.

Lawrence

lawrenceccheung commented 2 months ago

As an addendum to this issue, I also re-ran the original case of interest with the correct densities, and did a comparison with the quantities of interest. The full case set up is here: https://github.com/lawrenceccheung/ALCC_Frontier_WindFarm/blob/main/farmruns/MedWS_LowTI/template/farmrun1.ipynb, and you can see how the results line up in this table:

Param OpenFAST AMR-Wind w/ABL
GenPwr 9.2843 9.3200
RotSpeed 6.4067 6.4175
BldPitch1 0.0000 0.0000
RotTorq 14.4473 14.4810
RotThrust 2.0920 2.1153

and in these plots: image image

One side note now that I'm thinking about it -- when comparing against the design power curve, we need to make sure that we compare against the density corrected versions of the power curve. In this case, the density difference is 1.225 kg/m^3 versus 1.2456 kg/m^3, so it's all in the noise, but could be a factor when the simulation density is something like 1.1 kg/m^3.

There's still a few issues we need to cover (e.g., using OpenFAST v3.5+, and how to deal with this long term), but I'll set up a meeting with those interested later on.

Thanks again for everybody's help.

Lawrence

gyalla commented 2 months ago

Great work tracking this down, @mbkuhn! And thanks to everyone who helped in the process.

Gopal

mbkuhn commented 2 months ago

Great team effort, everyone! Those design curve comparisons (thanks Lawrence!) add a nice exclamation point to concluding this issue. The PR #1031 has been merged into main, and corresponds to the release v1.4.0. This means that density is now required for OpenFAST Turbine types, and there are abort statements, warnings, and messages depending on the comparison between other AMR-Wind density inputs and the density specified with the turbine type.