Skip to content
Open
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
117 changes: 117 additions & 0 deletions ard/farm_aero/floris.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@

import ard.utils.logging as ard_logging
import ard.farm_aero.templates as templates
from ard.farm_loads.surrogate_load_functions import (
ANN_DEL_BladeRoot,
ANN_DEL_Shaft,
ANN_DEL_TowerBase,
ANN_DEL_YawBearings,
)


def create_FLORIS_turbine_from_windIO(
Expand Down Expand Up @@ -210,6 +216,9 @@ def setup(self):
"reference_height",
None,
),
solver_settings=(
self.modeling_options.get("floris", {}).get("solver_settings")
),
)

self.case_title = self.options["case_title"]
Expand Down Expand Up @@ -275,6 +284,62 @@ def get_thrust_turbines(self):
else:
return thrust_turbines.T

def get_DELs(self):
SATI = self.fmodel.get_turbine_SATI() * 100
SAWS = self.fmodel.get_turbine_SAWS()
turbine_powers_percent = self.fmodel.get_turbine_powers_percent().flatten()

SATI_collapsed = SATI.reshape(-1, SATI.shape[-1])
SAWS_collapsed = SAWS.reshape(-1, SAWS.shape[-1])

Yaw = self.fmodel.core.farm.yaw_angles.flatten()

# [SAWSup SAWSright SAWSdown SAWSleft SATIup SATIright SATIdown SATIleft Yaw PowerDemand[%]]
input_data = np.concatenate(
(
SAWS_collapsed,
SATI_collapsed,
Yaw[:, None],
turbine_powers_percent[:, None],
),
axis=1,
)

# Make predictions using ANN surrogates
del_bladeroot_ann = ANN_DEL_BladeRoot(input_data)
del_shaft_ann = ANN_DEL_Shaft(input_data)
del_towerbase_ann = ANN_DEL_TowerBase(input_data)
del_yawbearings_ann = ANN_DEL_YawBearings(input_data)

# Weight predictions by frequency of wind conditions
weighted_del_bladeroot = np.zeros_like(del_towerbase_ann)
weighted_del_shaft = np.zeros_like(del_towerbase_ann)
weighted_del_towerbase = np.zeros_like(del_towerbase_ann)
weighted_del_yawbearings = np.zeros_like(del_towerbase_ann)

n_turbs = self.N_turbines

for i, f in enumerate(self.wind_query.freq_table.flatten()):
weighted_del_bladeroot[i * n_turbs : i * n_turbs + n_turbs] = (
del_bladeroot_ann[i * n_turbs : i * n_turbs + n_turbs] * f
)
weighted_del_shaft[i * n_turbs : i * n_turbs + n_turbs] = (
del_shaft_ann[i * n_turbs : i * n_turbs + n_turbs] * f
)
weighted_del_towerbase[i * n_turbs : i * n_turbs + n_turbs] = (
del_towerbase_ann[i * n_turbs : i * n_turbs + n_turbs] * f
)
weighted_del_yawbearings[i * n_turbs : i * n_turbs + n_turbs] = (
del_yawbearings_ann[i * n_turbs : i * n_turbs + n_turbs] * f
)

return (
np.sum(weighted_del_bladeroot),
np.sum(weighted_del_shaft),
np.sum(weighted_del_towerbase),
np.sum(weighted_del_yawbearings),
)

def dump_floris_yamlfile(self, dir_output=None):
"""
Export the current FLORIS inputs to a YAML file file for reproducibility of the analysis.
Expand Down Expand Up @@ -489,3 +554,55 @@ def compute(self, inputs, outputs):
@ard_logging.component_log_capture
def setup_partials(self):
FLORISFarmComponent.setup_partials(self)


class FLORISSurrogateDELs(FLORISAEP):
"""
Component class for computing surrogate DELs using FLORIS.
"""

def initialize(self):
super().initialize() # run super class script first!

def setup(self):
super().setup() # run super class script first!

self.add_output(
"blade_root_DEL",
0.0,
units="kN*m",
desc="frequency weighted sum of blade root DEL across all wind conditions",
)
self.add_output(
"shaft_DEL",
0.0,
units="kN*m",
desc="frequency weighted sum of shaft DEL across all wind conditions",
)
self.add_output(
"tower_base_DEL",
0.0,
units="kN*m",
desc="frequency weighted sum of tower base DEL across all wind conditions",
)
self.add_output(
"yaw_bearings_DEL",
0.0,
units="kN*m",
desc="frequency weighted sum of yaw bearings DELs across all wind conditions",
)

def setup_partials(self):
super().setup_partials()

def compute(self, inputs, outputs):
super().compute(inputs, outputs)
DEL_outputs = FLORISFarmComponent.get_DELs(self)
outputs["blade_root_DEL"] = DEL_outputs[0]
outputs["shaft_DEL"] = DEL_outputs[1]
outputs["tower_base_DEL"] = DEL_outputs[2]
outputs["yaw_bearings_DEL"] = DEL_outputs[3]
outputs["AEP_farm"] = FLORISFarmComponent.get_AEP_farm(self)

def setup_partials(self):
FLORISFarmComponent.setup_partials(self)
1 change: 1 addition & 0 deletions ard/farm_loads/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import surrogate_load_functions
Loading
Loading