Skip to content

Commit

Permalink
Merge branch 'control_testbench' of github.com:WISDEM/WEIS into contr…
Browse files Browse the repository at this point in the history
…ol_testbench
  • Loading branch information
Joeri Frederik committed Jan 17, 2025
2 parents 0f5dbc4 + fc03532 commit 2c54757
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 19 deletions.
59 changes: 41 additions & 18 deletions examples/19_controller_test_bench/testbench_options.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
General:
openfast_configuration:
save_iterations: True
save_timeseries: True

Testbench_Options:
output_directory: outputs/9_test_ramp # relative to this file
output_filebase: testbench
Expand Down Expand Up @@ -56,22 +61,40 @@ DLC_driver:
- DLC: "AEP"
TI_factor: 0.5
wind_speed: [12]
- DLC: "Ramp" # Up
- DLC: "Ramp" # 0 to cutin+1
turbine_status: parked-still
wind_speed: [0]
transient_time: 20
analysis_time: 200.
ramp_speeddelta: 6
ramp_duration: 200.
rot_speed_initial: 0
pitch_initial: 90
- DLC: "Ramp" # Cutin-1 to cutin+1
turbine_status: parked-still
wind_speed: [4]
transient_time: 20
analysis_time: 200.
ramp_speeddelta: 2
ramp_duration: 200.
rot_speed_initial: 0
pitch_initial: 90
- DLC: "Ramp" # Cutin to rated
wind_speed: [5]
analysis_time: 1000.
ramp_speeddelta: 20
ramp_duration: 1000.
- DLC: "Ramp" # Down
wind_speed: [25]
analysis_time: 1000.
ramp_speeddelta: -20
ramp_duration: 1000.
- DLC: "Step" # Down
wind_speed: [18]
analysis_time: 100.
step_speeddelta: 2.0
step_time: 50.0
# - DLC: "Steady"
# wind_speed: [8]
# analysis_time: 10.
# transient_time: 5.0
transient_time: 20
analysis_time: 200.
ramp_speeddelta: 6.4
ramp_duration: 200.
- DLC: "Ramp" # Rated-2 to rated+2
wind_speed: [9.4]
transient_time: 20
analysis_time: 400.
ramp_speeddelta: 13.4
ramp_duration: 400.
- DLC: "Ramp" # Rated to Cutout + 2
wind_speed: [11.4]
transient_time: 20
analysis_time: 400.
ramp_speeddelta: 27
ramp_duration: 400.

62 changes: 62 additions & 0 deletions weis/aeroelasticse/openmdao_openfast.py
Original file line number Diff line number Diff line change
Expand Up @@ -1996,6 +1996,9 @@ def setup_cases(self,modeling_options,inputs,discrete_inputs,fst_vt):
case_df.insert(0,'case_name',case_name)
text_table = case_df.to_string(index=False)

# Save case_df
self.case_df = case_df

# Write the text table to a yaml, text file
write_yaml(case_df.to_dict(),os.path.join(self.FAST_runDirectory,'case_matrix_combined.yaml'))
with open(os.path.join(self.FAST_runDirectory,'case_matrix_combined.txt'), 'w') as file:
Expand Down Expand Up @@ -2219,6 +2222,8 @@ def post_process(self, summary_stats, extreme_table, DELs, damage, case_list, ca

outputs, discrete_outputs = self.get_control_measures(summary_stats, chan_time, inputs, discrete_inputs, outputs, discrete_outputs)

self.get_charateristic_loads(summary_stats,inputs,outputs)

if modopt['flags']['floating'] or (modopt['Level3']['from_openfast'] and self.fst_vt['Fst']['CompMooring']>0):
self.get_floating_measures(summary_stats, chan_time, inputs, discrete_inputs,outputs, discrete_outputs)

Expand Down Expand Up @@ -2707,6 +2712,63 @@ def get_floating_measures(self,sum_stats, chan_time, inputs, discrete_inputs, ou
# Max platform offset
outputs['Max_Offset'] = sum_stats['PtfmOffset']['max'].max()

def get_charateristic_loads(self,sum_stats,inputs,outputs):
# Characteristic loads are described in IEC 61400-1:2019, Section 7.6.2.2

cm = self.case_df

# Get all unique channel names
channel_names = sum_stats.columns.get_level_values(0).unique().to_list()
channel_names = [str(cn) for cn in channel_names] # Convert to non-numpy strings

# Get all DLCs
dlcs = cm['DLC'].unique()

char_loads = {}

for dlc in dlcs:

# Filter for only stats of this dlc
dlc_ind = cm['DLC'] == dlc
ss_dlc = sum_stats[dlc_ind]
cm_dlc = cm[dlc_ind]

# Init this dlc char_load dict
char_loads[dlc] = {}

mean_wind_speed = cm_dlc[('InflowWind', 'HWindSpeed')]
unique_mws = mean_wind_speed.unique()

# For each channel in sum_stats
for chan in channel_names:
char_loads[dlc][chan] = {}
char_loads[dlc][chan]['wind_speed'] = unique_mws
char_loads[dlc][chan]['load_values'] = np.zeros_like(unique_mws)

# Over each wind speed simulated
for i, mws in enumerate(unique_mws):
mws_ind = cm_dlc[('InflowWind', 'HWindSpeed')] == mws
ss_mws = ss_dlc[mws_ind]

# average maximums (absolute value), most cases
char_loads[dlc][chan]['load_values'][i] = ss_mws[chan]['abs'].mean()

# average top-half (DLC 5.1, 2.1, 2.2)
if dlc in ['2.1','2.2','5.1']:
n_cases = len(ss_mws[chan]['abs'])
n_top_half = int(np.ceil(n_cases/2))
ss_top_half = ss_mws[chan].sort_values('abs',ascending=False)[:n_top_half]
char_loads[dlc][chan]['load_values'][i] = ss_top_half['abs'].mean()



# The characteristic load is the max of all the means
char_loads[dlc][chan]['characteristic_load'] = np.max(char_loads[dlc][chan]['load_values'])

save_dir = os.path.join(self.FAST_runDirectory,'iteration_'+str(self.of_inumber))
write_yaml(char_loads,os.path.join(save_dir,'charateristic_loads.yaml'))


def get_OL2CL_error(self,chan_time,outputs):
ol_case_names = [os.path.join(
weis_dir,
Expand Down
13 changes: 12 additions & 1 deletion weis/dlc_driver/dlc_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -870,10 +870,21 @@ def generate_Ramp(self, dlc_options):
else:
dlc_options['gust_wait_time'] = 0

generic_case_inputs = []

# Add initial conditions
# Note that for initial conditions to not be overwritten, turbine_status should be parked (still or idling)
group0 = ['total_time','transient_time','wake_mod','wave_model']
if 'pitch_initial' in dlc_options:
group0.extend(['pitch_initial'])
if 'rot_speed_initial' in dlc_options:
group0.extend(['rot_speed_initial'])


# DLC-specific: define groups
# These options should be the same length and we will generate a matrix of all cases
generic_case_inputs = []
generic_case_inputs.append(['total_time','transient_time','wake_mod','wave_model']) # group 0, (usually constants) turbine variables, DT, aero_modeling
generic_case_inputs.append(group0) # group 0, (usually constants) turbine variables, DT, aero_modeling
generic_case_inputs.append(['wind_speed','wave_height','wave_period', 'wind_seed', 'wave_seed']) # group 1, initial conditions will be added here, define some method that maps wind speed to ICs and add those variables to this group
generic_case_inputs.append(['yaw_misalign']) # group 2

Expand Down

0 comments on commit 2c54757

Please sign in to comment.