Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/control_testbench' into control_…
Browse files Browse the repository at this point in the history
…testbench
  • Loading branch information
dzalkind committed Jan 17, 2025
2 parents 48a5ddd + 2c54757 commit e82effa
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 47 deletions.
84 changes: 52 additions & 32 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 @@ -49,35 +54,50 @@ DLC_driver:
wave_period50: 13.6
DLCs:
- DLC: "1.1"
n_seeds: 2
wind_speed: [6,12]
transient_time: 0
analysis_time: 400
# - DLC: "1.3"
# n_seeds: 6
# - DLC: "1.4"
# - DLC: "1.5"
# - DLC: "1.6"
# - DLC: "5.1"
# - DLC: "AEP"
# TI_factor: 0.5
# wind_speed: [12]
# - DLC: "Ramp" # Up
# 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
n_seeds: 6
- DLC: "1.3"
n_seeds: 6
- DLC: "1.4"
- DLC: "1.5"
- DLC: "1.6"
- DLC: "5.1"
- DLC: "AEP"
TI_factor: 0.5
wind_speed: [12]
- 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]
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.

64 changes: 50 additions & 14 deletions weis/aeroelasticse/IEC_CoeherentGusts.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ def write_wnd(self, fname, data, hd):

# Headers
hd1 = ['Time', 'Wind', 'Wind', 'Vertical', 'Horiz.', 'Pwr. Law', 'Lin. Vert.', 'Gust', 'Upflow']
hd2 = ['', 'Speed', 'Dir', 'Speed', 'Shear', 'Vert. Shr', 'Shear', 'Speed', 'Angle']
hd2 = ['', 'Speed', 'Dir', 'Speed', 'Shear', 'Vert. Shr', 'Shear', 'Speed', 'Angle']
hd3 = ['(s)', '(m/s)', '(deg)', '(m/s)', '(-)', '(-)', '(-)', '(m/s)', '(deg)']

fid = open(fname, 'w')
Expand All @@ -301,7 +301,41 @@ def write_wnd(self, fname, data, hd):

fid.close()

def add_turbulence(filename, u, v = None, w = None, time = None, ref_height = None, new_filename = None):
def write_bts(self, bts_fname, wnd_fname, new_fname = None):

data = np.loadtxt(wnd_fname, skiprows=6)

## TODO: more advanced function to convert wnd to bts
ts = self.wnd2bts(data, 0, self.HH)
if new_fname: self.add_turbulence(bts_fname, ts['u'], ts['v'], ts['w'], data[:,0], self.HH, new_fname)
else: return self.add_turbulence(bts_fname, ts['u'], ts['v'], ts['w'], data[:,0], self.HH, new_fname)

def wnd2bts(self, data, y, z):
"""
Converts wnd-style data to bts-style data
0: Time
1: Wind speed
2: Wind dir
3: Vertical speed
4: Horizontal shear
5: Pwr law vert shear
6: Linear vertical shear
7: Gust speed
8: Upflow angle
"""
ts = {}
u = np.cos(data[:,2]*np.pi/180) * np.cos(data[:,8]*np.pi/180) * data[:,1] + \
np.sin(data[:,8]*np.pi/180) * data[:,3]
v = -np.sin(data[:,2]*np.pi/180)
w = -np.cos(data[:,2]*np.pi/180) * np.sin(data[:,8]*np.pi/180) * data[:,1] + \
np.cos(data[:,8]*np.pi/180) * data[:,3]
ts['u'] = u
ts['v'] = v
ts['w'] = w

return ts

def add_turbulence(fname, u, v = None, w = None, time = None, HH = None, new_fname = None):
"""
Creates a new BTS file using the turbulence of an existing BTS file,
combined with time-varying u (and possibly v and w) signals.
Expand All @@ -310,27 +344,27 @@ def add_turbulence(filename, u, v = None, w = None, time = None, ref_height = No
of the turbsim file (Nt, Ny, Nz).
Inputs:
filename (str): path to BTS file to grab turbulence from.
u (array): time-varying velocity in x-direction.
v (array, optional): time-varying velocity in x-direction (assumed 0).
u (array, optional): time-varying velocity in x-direction (assumed 0).
time (array, optional): time array, must be same size as u (and v and w).
fname (str): path to BTS file to grab turbulence from.
u (array): time-varying velocity in x-direction.
v (array, optional): time-varying velocity in x-direction (assumed 0).
u (array, optional): time-varying velocity in x-direction (assumed 0).
time (array, optional): time array, must be same size as u (and v and w).
If undefined, velocity inputs must match BTS file size.
ref_height (float, opt): user-defined height to take average WS at.
HH (float, opt): user-defined height to take average WS at.
Assumed to be middle of grid.
new_filename (str, opt): filename for the new BTS file. If undefined, the function
new_fname (str, opt): filename for the new BTS file. If undefined, the function
returns the TurbSimFile object instead.
"""

if v is None: v = np.zeros_like(u)
if w is None: w = np.zeros_like(u)

## Load BTS file
ts = turbsim_file.TurbSimFile(filename)
ts = turbsim_file.TurbSimFile(fname)
ts_shape = ts['u'].shape
if ref_height:
if HH:
## Find z location closest to reference height
ref_idx = np.argmin(abs(ts['z']-ref_height))
ref_idx = np.argmin(abs(ts['z']-HH))
## If ref_height not defined, assume it to be in the middle
elif ts_shape[3] % 2 == 1:
ref_idx = int(ts_shape[3]/2-0.5)
Expand Down Expand Up @@ -361,7 +395,9 @@ def add_turbulence(filename, u, v = None, w = None, time = None, ref_height = No
ts_new['u'][2,:,:,:] = ts['u'][2,:,:,:] + \
np.tile(w[:, np.newaxis, np.newaxis],(1, ts_shape[2], ts_shape[3]))

if new_filename:
ts_new.write(new_filename)
if new_fname:
ts_new.write(new_fname)
else:
return ts_new


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 e82effa

Please sign in to comment.