Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up TODOs prior to v4 release #876

Merged
merged 4 commits into from
Apr 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions floris/core/rotor_velocity.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,18 @@
from floris.utilities import cosd


def rotor_velocity_yaw_correction(
def rotor_velocity_yaw_cosine_correction(
cosine_loss_exponent_yaw: float,
yaw_angles: NDArrayFloat,
rotor_effective_velocities: NDArrayFloat,
) -> NDArrayFloat:
# Compute the rotor effective velocity adjusting for yaw settings
pW = cosine_loss_exponent_yaw / 3.0 # Convert from cosine_loss_exponent_yaw to w
# TODO: cosine loss hard coded
rotor_effective_velocities = rotor_effective_velocities * cosd(yaw_angles) ** pW

return rotor_effective_velocities

def rotor_velocity_tilt_correction(
def rotor_velocity_tilt_cosine_correction(
tilt_angles: NDArrayFloat,
ref_tilt: NDArrayFloat,
cosine_loss_exponent_tilt: float,
Expand All @@ -48,7 +47,6 @@ def rotor_velocity_tilt_correction(
tilt_angles = np.where(correct_cp_ct_for_tilt, tilt_angles, old_tilt_angle)

# Compute the rotor effective velocity adjusting for tilt
# TODO: cosine loss hard coded
relative_tilt = tilt_angles - ref_tilt
rotor_effective_velocities = (
rotor_effective_velocities
Expand Down Expand Up @@ -214,14 +212,14 @@ def rotor_effective_velocity(
rotor_effective_velocities = (air_density/ref_air_density)**(1/3) * average_velocities

# Compute the rotor effective velocity adjusting for yaw settings
rotor_effective_velocities = rotor_velocity_yaw_correction(
rotor_effective_velocities = rotor_velocity_yaw_cosine_correction(
cosine_loss_exponent_yaw,
yaw_angle,
rotor_effective_velocities
)

# Compute the tilt, if using floating turbines
rotor_effective_velocities = rotor_velocity_tilt_correction(
rotor_effective_velocities = rotor_velocity_tilt_cosine_correction(
turbine_type_map,
tilt_angle,
ref_tilt,
Expand All @@ -232,3 +230,12 @@ def rotor_effective_velocity(
)

return rotor_effective_velocities

def rotor_velocity_air_density_correction(
velocities: NDArrayFloat,
air_density: float,
ref_air_density: float,
) -> NDArrayFloat:
# Produce equivalent velocities at the reference air density

return (air_density/ref_air_density)**(1/3) * velocities
27 changes: 9 additions & 18 deletions floris/core/turbine/operation_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
from floris.core.rotor_velocity import (
average_velocity,
compute_tilt_angles_for_floating_turbines,
rotor_velocity_tilt_correction,
rotor_velocity_yaw_correction,
rotor_velocity_air_density_correction,
rotor_velocity_tilt_cosine_correction,
rotor_velocity_yaw_cosine_correction,
)
from floris.type_dec import (
NDArrayFloat,
Expand All @@ -30,15 +31,6 @@
POWER_SETPOINT_DEFAULT = 1e12
POWER_SETPOINT_DISABLED = 0.001

def rotor_velocity_air_density_correction(
velocities: NDArrayFloat,
air_density: float,
ref_air_density: float,
) -> NDArrayFloat:
# Produce equivalent velocities at the reference air density
# TODO: This could go on BaseTurbineModel
return (air_density/ref_air_density)**(1/3) * velocities


@define
class BaseOperationModel(BaseClass):
Expand Down Expand Up @@ -67,6 +59,9 @@ def thrust_coefficient() -> None:
@staticmethod
@abstractmethod
def axial_induction() -> None:
# TODO: Consider whether we can make a generic axial_induction method
# based purely on thrust_coefficient so that we don't need to implement
# axial_induciton() in individual operation models.
raise NotImplementedError("BaseOperationModel.axial_induction")

@define
Expand All @@ -78,8 +73,6 @@ class SimpleTurbine(BaseOperationModel):
As with all turbine submodules, implements only static power() and thrust_coefficient() methods,
which are called by power() and thrust_coefficient() on turbine.py, respectively. This class is
not intended to be instantiated; it simply defines a library of static methods.

TODO: Should the turbine submodels each implement axial_induction()?
"""

def power(
Expand Down Expand Up @@ -174,8 +167,6 @@ class CosineLossTurbine(BaseOperationModel):
As with all turbine submodules, implements only static power() and thrust_coefficient() methods,
which are called by power() and thrust_coefficient() on turbine.py, respectively. This class is
not intended to be instantiated; it simply defines a library of static methods.

TODO: Should the turbine submodels each implement axial_induction()?
"""

def power(
Expand Down Expand Up @@ -211,13 +202,13 @@ def power(
ref_air_density=power_thrust_table["ref_air_density"]
)

rotor_effective_velocities = rotor_velocity_yaw_correction(
rotor_effective_velocities = rotor_velocity_yaw_cosine_correction(
cosine_loss_exponent_yaw=power_thrust_table["cosine_loss_exponent_yaw"],
yaw_angles=yaw_angles,
rotor_effective_velocities=rotor_effective_velocities,
)

rotor_effective_velocities = rotor_velocity_tilt_correction(
rotor_effective_velocities = rotor_velocity_tilt_cosine_correction(
tilt_angles=tilt_angles,
ref_tilt=power_thrust_table["ref_tilt"],
cosine_loss_exponent_tilt=power_thrust_table["cosine_loss_exponent_tilt"],
Expand Down Expand Up @@ -531,7 +522,7 @@ def power(
+ power_thrust_table['helix_power_c']*base_powers
)
*awc_amplitudes**power_thrust_table['helix_a']
) ## TODO: Should probably add max function here
) # TODO: Should probably add max function here
if (awc_modes == 'baseline').any():
return base_powers
else:
Expand Down
9 changes: 0 additions & 9 deletions floris/core/turbine/turbine.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,6 @@ def power(
Returns:
NDArrayFloat: The power, in Watts, for each turbine after adjusting for yaw and tilt.
"""
# TODO: Change the order of input arguments to be consistent with the other
# utility functions - velocities first...
# Update to power calculation which replaces the fixed cosine_loss_exponent_yaw exponent
# (which applies to the cosine of the yaw misalignment) with an exponent pW, that changes the
# effective wind speed input to the power calculation, rather than scaling the power. This
# better handles power loss to yaw in above rated conditions
#
# Based on the paper "Optimising yaw control at wind farm level" by
# Ervin Bossanyi

# Down-select inputs if ix_filter is given
if ix_filter is not None:
Expand Down
7 changes: 6 additions & 1 deletion floris/core/wake_deflection/gauss.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,12 @@ def function(
for details on the methods used.

Args:
# TODO
x_i (np.array): x-coordinates of turbine i.
y_i (np.array): y-coordinates of turbine i.
yaw_i (np.array): Yaw angle of turbine i.
turbulence_intensity_i (np.array): Turbulence intensity at turbine i.
ct_i (np.array): Thrust coefficient of turbine i.
rotor_diameter_i (float): Rotor diameter of turbine i.

Returns:
np.array: Deflection field for the wake.
Expand Down
4 changes: 2 additions & 2 deletions floris/core/wake_velocity/empirical_gauss.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def rCalt(wind_veer, sigma_y, sigma_z, y, y_i, delta_y, delta_z, z, HH, Ct,

def sigmoid_integral(x, center=0, width=1):
y = np.zeros_like(x)
#TODO: Can this be made faster?
# TODO: Can this be made faster?
above_smoothing_zone = (x-center) > width/2
y[above_smoothing_zone] = (x-center)[above_smoothing_zone]
in_smoothing_zone = ((x-center) >= -width/2) & ((x-center) <= width/2)
Expand Down Expand Up @@ -293,7 +293,7 @@ def awc_added_wake_mixing(
awc_wake_denominator
):

## TODO: Add TI in the mix, finetune amplitude/freq effect
# TODO: Add TI in the mix, finetune amplitude/freq effect
if (awc_mode_i == "helix").any():
return awc_amplitude_i[:,:,0,0]**awc_wake_exp/awc_wake_denominator
elif (awc_mode_i == "baseline").any():
Expand Down
2 changes: 1 addition & 1 deletion floris/core/wake_velocity/gauss.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def function(
# Another linear ramp, but positive upstream of the far wake and negative in the
# far wake; 0 at the start of the far wake
near_wake_ramp_down = (x0 - x) / (x0 - xR)
# near_wake_ramp_down = -1 * (near_wake_ramp_up - 1) # TODO: this is equivalent, right?
# near_wake_ramp_down = -1 * (near_wake_ramp_up - 1) # : this is equivalent, right?

sigma_y = near_wake_ramp_down * 0.501 * rotor_diameter_i * np.sqrt(ct_i / 2.0)
sigma_y += near_wake_ramp_up * sigma_y0
Expand Down
6 changes: 0 additions & 6 deletions floris/floris_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -576,12 +576,6 @@ def _get_farm_power(
Returns:
float: Sum of wind turbine powers in W.
"""
# TODO: Turbulence correction used in the power calculation, but may not be in
# the model yet
# TODO: Turbines need a switch for using turbulence correction
# TODO: Uncomment out the following two lines once the above are resolved
# for turbine in self.core.farm.turbines:
# turbine.use_turbulence_correction = use_turbulence_correction
if use_turbulence_correction:
raise NotImplementedError(
"Turbulence correction is not yet implemented in the power calculation."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ def __init__(
minimum_yaw_angle=-30.0,
maximum_yaw_angle=30.0,
)
# TODO: is this being used?
fmodel.run()

if self.use_value:
Expand Down
2 changes: 1 addition & 1 deletion floris/parallel_floris_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ def _postprocessing(self, output):

return turbine_powers

def run(self): # TODO: Remove or update this function?
def run(self):
raise UserWarning(
"'run' not supported on ParallelFlorisModel. Please use "
"'get_turbine_powers' or 'get_farm_power' directly."
Expand Down
6 changes: 0 additions & 6 deletions floris/uncertain_floris_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,12 +325,6 @@ def _get_farm_power(
Returns:
float: Sum of wind turbine powers in W.
"""
# TODO: Turbulence correction used in the power calculation, but may not be in
# the model yet
# TODO: Turbines need a switch for using turbulence correction
# TODO: Uncomment out the following two lines once the above are resolved
# for turbine in self.core.farm.turbines:
# turbine.use_turbulence_correction = use_turbulence_correction
if use_turbulence_correction:
raise NotImplementedError(
"Turbulence correction is not yet implemented in the power calculation."
Expand Down
44 changes: 32 additions & 12 deletions tests/rotor_velocity_unit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,53 +6,73 @@
compute_tilt_angles_for_floating_turbines,
compute_tilt_angles_for_floating_turbines_map,
cubic_cubature,
rotor_velocity_tilt_correction,
rotor_velocity_yaw_correction,
rotor_velocity_air_density_correction,
rotor_velocity_tilt_cosine_correction,
rotor_velocity_yaw_cosine_correction,
simple_cubature,
)
from tests.conftest import SampleInputs, WIND_SPEEDS


def test_rotor_velocity_yaw_correction():
def test_rotor_velocity_air_density_correction():

wind_speed = 10.
ref_air_density = 1.225
test_density = 1.2

test_speed = rotor_velocity_air_density_correction(wind_speed, ref_air_density, ref_air_density)
assert test_speed == wind_speed

test_speed = rotor_velocity_air_density_correction(wind_speed, test_density, test_density)
assert test_speed == wind_speed

test_speed = rotor_velocity_air_density_correction(0., test_density, ref_air_density)
assert test_speed == 0.

test_speed = rotor_velocity_air_density_correction(wind_speed, test_density, ref_air_density)
assert np.allclose((test_speed/wind_speed)**3, test_density/ref_air_density)


def test_rotor_velocity_yaw_cosine_correction():
N_TURBINES = 4

wind_speed = average_velocity(10.0 * np.ones((1, 1, 3, 3)))
wind_speed_N_TURBINES = average_velocity(10.0 * np.ones((1, N_TURBINES, 3, 3)))

# Test a single turbine for zero yaw
yaw_corrected_velocities = rotor_velocity_yaw_correction(
yaw_corrected_velocities = rotor_velocity_yaw_cosine_correction(
cosine_loss_exponent_yaw=3.0,
yaw_angles=0.0,
rotor_effective_velocities=wind_speed,
)
np.testing.assert_allclose(yaw_corrected_velocities, wind_speed)

# Test a single turbine for non-zero yaw
yaw_corrected_velocities = rotor_velocity_yaw_correction(
yaw_corrected_velocities = rotor_velocity_yaw_cosine_correction(
cosine_loss_exponent_yaw=3.0,
yaw_angles=60.0,
rotor_effective_velocities=wind_speed,
)
np.testing.assert_allclose(yaw_corrected_velocities, 0.5 * wind_speed)

# Test multiple turbines for zero yaw
yaw_corrected_velocities = rotor_velocity_yaw_correction(
yaw_corrected_velocities = rotor_velocity_yaw_cosine_correction(
cosine_loss_exponent_yaw=3.0,
yaw_angles=np.zeros((1, N_TURBINES)),
rotor_effective_velocities=wind_speed_N_TURBINES,
)
np.testing.assert_allclose(yaw_corrected_velocities, wind_speed_N_TURBINES)

# Test multiple turbines for non-zero yaw
yaw_corrected_velocities = rotor_velocity_yaw_correction(
yaw_corrected_velocities = rotor_velocity_yaw_cosine_correction(
cosine_loss_exponent_yaw=3.0,
yaw_angles=np.ones((1, N_TURBINES)) * 60.0,
rotor_effective_velocities=wind_speed_N_TURBINES,
)
np.testing.assert_allclose(yaw_corrected_velocities, 0.5 * wind_speed_N_TURBINES)


def test_rotor_velocity_tilt_correction():
def test_rotor_velocity_tilt_cosine_correction():
N_TURBINES = 4

wind_speed = average_velocity(10.0 * np.ones((1, 1, 3, 3)))
Expand All @@ -66,7 +86,7 @@ def test_rotor_velocity_tilt_correction():
turbine_type_map = turbine_type_map[None, :]

# Test single non-floating turbine
tilt_corrected_velocities = rotor_velocity_tilt_correction(
tilt_corrected_velocities = rotor_velocity_tilt_cosine_correction(
#turbine_type_map=np.array([turbine_type_map[:, 0]]),
tilt_angles=5.0*np.ones((1, 1)),
ref_tilt=np.array([turbine.power_thrust_table["ref_tilt"]]),
Expand All @@ -81,7 +101,7 @@ def test_rotor_velocity_tilt_correction():
np.testing.assert_allclose(tilt_corrected_velocities, wind_speed)

# Test multiple non-floating turbines
tilt_corrected_velocities = rotor_velocity_tilt_correction(
tilt_corrected_velocities = rotor_velocity_tilt_cosine_correction(
#turbine_type_map=turbine_type_map,
tilt_angles=5.0*np.ones((1, N_TURBINES)),
ref_tilt=np.array([turbine.power_thrust_table["ref_tilt"]] * N_TURBINES),
Expand All @@ -96,7 +116,7 @@ def test_rotor_velocity_tilt_correction():
np.testing.assert_allclose(tilt_corrected_velocities, wind_speed_N_TURBINES)

# Test single floating turbine
tilt_corrected_velocities = rotor_velocity_tilt_correction(
tilt_corrected_velocities = rotor_velocity_tilt_cosine_correction(
#turbine_type_map=np.array([turbine_type_map[:, 0]]),
tilt_angles=5.0*np.ones((1, 1)),
ref_tilt=np.array([turbine_floating.power_thrust_table["ref_tilt"]]),
Expand All @@ -111,7 +131,7 @@ def test_rotor_velocity_tilt_correction():
np.testing.assert_allclose(tilt_corrected_velocities, wind_speed)

# Test multiple floating turbines
tilt_corrected_velocities = rotor_velocity_tilt_correction(
tilt_corrected_velocities = rotor_velocity_tilt_cosine_correction(
#turbine_type_map,
tilt_angles=5.0*np.ones((1, N_TURBINES)),
ref_tilt=np.array([turbine_floating.power_thrust_table["ref_tilt"]] * N_TURBINES),
Expand Down
19 changes: 0 additions & 19 deletions tests/turbine_operation_models_integration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,13 @@
CosineLossTurbine,
MixedOperationTurbine,
POWER_SETPOINT_DEFAULT,
rotor_velocity_air_density_correction,
SimpleDeratingTurbine,
SimpleTurbine,
)
from floris.utilities import cosd
from tests.conftest import SampleInputs, WIND_SPEEDS


def test_rotor_velocity_air_density_correction():

wind_speed = 10.
ref_air_density = 1.225
test_density = 1.2

test_speed = rotor_velocity_air_density_correction(wind_speed, ref_air_density, ref_air_density)
assert test_speed == wind_speed

test_speed = rotor_velocity_air_density_correction(wind_speed, test_density, test_density)
assert test_speed == wind_speed

test_speed = rotor_velocity_air_density_correction(0., test_density, ref_air_density)
assert test_speed == 0.

test_speed = rotor_velocity_air_density_correction(wind_speed, test_density, ref_air_density)
assert np.allclose((test_speed/wind_speed)**3, test_density/ref_air_density)

def test_submodel_attributes():

assert hasattr(SimpleTurbine, "power")
Expand Down
Loading
Loading