Skip to content

Commit

Permalink
Update ofTools for OpenFAST 2.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
dzalkind committed Feb 2, 2021
1 parent 68fc918 commit 639a23f
Show file tree
Hide file tree
Showing 6 changed files with 249 additions and 101 deletions.
5 changes: 5 additions & 0 deletions ofTools/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# OpenFAST Tools
A set of OpenFAST tools is provided to ease the use of the ROSCO toolbox in conjuction with [OpenFAST](https://github.com/openfast/openfast).

OpenFAST can be installed using conda-forge using
```
conda install -c conda-forge openfast
```

Note that most of these scripts are copy and pasted from [weis's aeroleasticse](https://github.com/WISDEM/WEIS/tree/master/weis/aeroelasticse)

### case_gen
Expand Down
51 changes: 32 additions & 19 deletions ofTools/case_gen/CaseGen_IEC.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,10 @@ def execute(self, case_inputs={}):
IEC_WindType = 'NTM'
alpha = 0.2
iecwind = pyIECWind_turb()
TMax = 630.
if self.TMax == 0:
TMax = 720.
else:
TMax = self.TMax

elif dlc in [1.3, 6.1, 6.3]:
if self.Turbine_Class == 'I':
Expand All @@ -93,19 +96,28 @@ def execute(self, case_inputs={}):
IEC_WindType = '%uETM'%x
alpha = 0.11
iecwind = pyIECWind_turb()
TMax = 630.
if self.TMax == 0:
TMax = 720.
else:
TMax = self.TMax

elif dlc == 1.4:
IEC_WindType = 'ECD'
alpha = 0.2
iecwind = pyIECWind_extreme()
TMax = 90.
if self.TMax == 0:
TMax = 120.
else:
TMax = self.TMax

elif dlc == 1.5:
IEC_WindType = 'EWS'
alpha = 0.2
iecwind = pyIECWind_extreme()
TMax = 90.
if self.TMax == 0:
TMax = 120.
else:
TMax = self.TMax

# Windfile generation setup
if self.TMax == 0.:
Expand Down Expand Up @@ -144,24 +156,24 @@ def execute(self, case_inputs={}):
case_inputs_i[("ServoDyn","TPitManS1")] = {'vals':[self.TStart], 'group':0}
case_inputs_i[("ServoDyn","TPitManS2")] = {'vals':[self.TStart], 'group':0}
case_inputs_i[("ServoDyn","TPitManS3")] = {'vals':[self.TStart], 'group':0}
case_inputs_i[("ServoDyn","PitManRat1")] = {'vals':[self.PC_MaxRat], 'group':0}
case_inputs_i[("ServoDyn","PitManRat2")] = {'vals':[self.PC_MaxRat], 'group':0}
case_inputs_i[("ServoDyn","PitManRat3")] = {'vals':[self.PC_MaxRat], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF1")] = {'vals':[90.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF2")] = {'vals':[90.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF3")] = {'vals':[90.], 'group':0}
case_inputs_i[("ServoDyn","PitManRat(1)")] = {'vals':[self.PC_MaxRat], 'group':0}
case_inputs_i[("ServoDyn","PitManRat(2)")] = {'vals':[self.PC_MaxRat], 'group':0}
case_inputs_i[("ServoDyn","PitManRat(3)")] = {'vals':[self.PC_MaxRat], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF(1)")] = {'vals':[90.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF(2)")] = {'vals':[90.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF(3)")] = {'vals':[90.], 'group':0}
case_inputs_i[("ServoDyn","GenTiStp")] = {'vals':["True"], 'group':0}
case_inputs_i[("ServoDyn","TimGenOf")] = {'vals':[self.TStart], 'group':0}
else:
case_inputs_i[("ServoDyn","TPitManS1")] = {'vals':[9999.9], 'group':0}
case_inputs_i[("ServoDyn","TPitManS2")] = {'vals':[9999.9], 'group':0}
case_inputs_i[("ServoDyn","TPitManS3")] = {'vals':[9999.9], 'group':0}
case_inputs_i[("ServoDyn","PitManRat1")] = {'vals':[2.], 'group':0}
case_inputs_i[("ServoDyn","PitManRat2")] = {'vals':[2.], 'group':0}
case_inputs_i[("ServoDyn","PitManRat3")] = {'vals':[2.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF1")] = {'vals':[0.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF2")] = {'vals':[0.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF3")] = {'vals':[0.], 'group':0}
case_inputs_i[("ServoDyn","PitManRat(1)")] = {'vals':[2.], 'group':0}
case_inputs_i[("ServoDyn","PitManRat(2)")] = {'vals':[2.], 'group':0}
case_inputs_i[("ServoDyn","PitManRat(3)")] = {'vals':[2.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF(1)")] = {'vals':[0.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF(2)")] = {'vals':[0.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF(3)")] = {'vals':[0.], 'group':0}
case_inputs_i[("ServoDyn","GenTiStp")] = {'vals':["True"], 'group':0}
case_inputs_i[("ServoDyn","TimGenOf")] = {'vals':[9999.9], 'group':0}

Expand Down Expand Up @@ -192,7 +204,6 @@ def execute(self, case_inputs={}):
case_inputs_i[("ServoDyn","PCMode")] = {'vals':[5], 'group':0}
case_inputs_i[("AeroDyn15","AFAeroMod")]= {'vals':[2], 'group':0}
case_inputs_i[("ElastoDyn","GenDOF")] = {'vals':["True"], 'group':0}
case_inputs_i[("ElastoDyn","YawDOF")] = {'vals':["True"], 'group':0}


# Matrix combining N dlc variables that affect wind file generation
Expand Down Expand Up @@ -283,7 +294,9 @@ def execute(self, case_inputs={}):
if ("Fst","TMax") not in case_inputs_i:
case_inputs_i[("Fst","TMax")] = {'vals':[TMax], 'group':0}
case_inputs_i[("InflowWind","WindType")] = {'vals':WindFile_type_out, 'group':1}
case_inputs_i[("InflowWind","Filename")] = {'vals':WindFile_out, 'group':1}
case_inputs_i[("InflowWind","Filename_Uni")] = {'vals':WindFile_out, 'group':1}
case_inputs_i[("InflowWind","FileName_BTS")] = {'vals':WindFile_out, 'group':1}
case_inputs_i[("InflowWind","RefLength")] = {'vals':[self.D], 'group':0}

if len(self.dlc_inputs['Yaw'][i]) > 0:
case_inputs_i[("ElastoDyn","NacYaw")] = {'vals':self.dlc_inputs['Yaw'][i], 'group':2}
Expand All @@ -298,7 +311,7 @@ def execute(self, case_inputs={}):
# make unique wave seeds
if self.uniqueWaveSeeds:
seed_base = int(float(dlc) * 10000) # set wave seed based on dlc so no repeats
num_in_dlc = len(case_inputs_i[("InflowWind","Filename")]['vals']) # sims in each DLC
num_in_dlc = len(case_inputs_i[("InflowWind","FileName_BTS")]['vals']) # sims in each DLC
wave_seeds = (seed_base + np.arange(0,num_in_dlc)).tolist()

case_inputs_i[("HydroDyn","WaveSeed1")] = {'vals':wave_seeds, 'group':1}
Expand Down
96 changes: 77 additions & 19 deletions ofTools/fast_io/FAST_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@ def read_MainInput(self):
self.fst_vt['Fst']['SubFile_path'] = os.path.split(self.fst_vt['Fst']['SubFile'])[0]
self.fst_vt['Fst']['MooringFile_path'] = os.path.split(self.fst_vt['Fst']['MooringFile'])[0]
self.fst_vt['Fst']['IceFile_path'] = os.path.split(self.fst_vt['Fst']['IceFile'])[0]

def read_ElastoDyn(self):
# ElastoDyn v1.03 Input File
# Currently no differences between FASTv8.16 and OpenFAST.
Expand Down Expand Up @@ -781,7 +782,6 @@ def read_BeamDyn(self):

self.read_BeamDynBlade()


def read_BeamDynBlade(self):
# BeamDyn Blade

Expand Down Expand Up @@ -836,6 +836,7 @@ def read_InflowWind(self):
self.fst_vt['InflowWind']['Echo'] = bool_read(f.readline().split()[0])
self.fst_vt['InflowWind']['WindType'] = int(f.readline().split()[0])
self.fst_vt['InflowWind']['PropogationDir'] = float_read(f.readline().split()[0])
self.fst_vt['InflowWind']['VFlowAng'] = float_read(f.readline().split()[0])
self.fst_vt['InflowWind']['NWindVel'] = int(f.readline().split()[0])
self.fst_vt['InflowWind']['WindVxiList'] = float_read(f.readline().split()[0])
self.fst_vt['InflowWind']['WindVyiList'] = float_read(f.readline().split()[0])
Expand All @@ -849,14 +850,13 @@ def read_InflowWind(self):

# Parameters for Uniform wind file [used only for WindType = 2] (uniform_wind_params)
f.readline()
self.fst_vt['InflowWind']['Filename'] = os.path.join(os.path.split(inflow_file)[0], f.readline().split()[0][1:-1])
self.fst_vt['InflowWind']['RefHt'] = float_read(f.readline().split()[0])
self.fst_vt['InflowWind']['Filename_Uni'] = os.path.join(os.path.split(inflow_file)[0], f.readline().split()[0][1:-1])
self.fst_vt['InflowWind']['RefHt_Uni'] = float_read(f.readline().split()[0])
self.fst_vt['InflowWind']['RefLength'] = float_read(f.readline().split()[0])

# Parameters for Binary TurbSim Full-Field files [used only for WindType = 3] (turbsim_wind_params)
f.readline()
self.fst_vt['InflowWind']['Filename'] = os.path.join(os.path.split(inflow_file)[0], f.readline().split()[0][1:-1])

self.fst_vt['InflowWind']['FileName_BTS'] = os.path.join(os.path.split(inflow_file)[0], f.readline().split()[0][1:-1])
# Parameters for Binary Bladed-style Full-Field files [used only for WindType = 4] (bladed_wind_params)
f.readline()
self.fst_vt['InflowWind']['FilenameRoot'] = f.readline().split()[0][1:-1]
Expand All @@ -873,7 +873,7 @@ def read_InflowWind(self):
self.fst_vt['InflowWind']['dx'] = float_read(f.readline().split()[0])
self.fst_vt['InflowWind']['dy'] = float_read(f.readline().split()[0])
self.fst_vt['InflowWind']['dz'] = float_read(f.readline().split()[0])
self.fst_vt['InflowWind']['RefHt'] = float_read(f.readline().split()[0])
self.fst_vt['InflowWind']['RefHt_Hawc'] = float_read(f.readline().split()[0])

# Scaling parameters for turbulence (still hawc_wind_params)
f.readline()
Expand All @@ -889,8 +889,9 @@ def read_InflowWind(self):
f.readline()
self.fst_vt['InflowWind']['URef'] = float_read(f.readline().split()[0])
self.fst_vt['InflowWind']['WindProfile'] = int(f.readline().split()[0])
self.fst_vt['InflowWind']['PLExp'] = float_read(f.readline().split()[0])
self.fst_vt['InflowWind']['PLExp_Hawc'] = float_read(f.readline().split()[0])
self.fst_vt['InflowWind']['Z0'] = float_read(f.readline().split()[0])
self.fst_vt['InflowWind']['XOffset'] = float_read(f.readline().split()[0])

# Inflow Wind Output Parameters (inflow_out_params)
f.readline()
Expand Down Expand Up @@ -1002,7 +1003,6 @@ def read_AeroDyn14Tower(self):
self.fst_vt['AeroDynTower']['TwrRe'][i] = data[0]
self.fst_vt['AeroDynTower']['TwrCD'][i,:] = data[1:]


def read_AeroDyn15(self):
# AeroDyn v15.03

Expand Down Expand Up @@ -1052,7 +1052,7 @@ def read_AeroDyn15(self):
# Dynamic Blade-Element/Momentum Theory Options
f.readline()
self.fst_vt['AeroDyn15']['DBEMT_Mod'] = int(f.readline().split()[0])
self.fst_vt['AeroDyn15']['tau1_const'] = int(f.readline().split()[0])
self.fst_vt['AeroDyn15']['tau1_const'] = float_read(f.readline().split()[0])

# Olaf -- cOnvecting LAgrangian Filaments (Free Vortex Wake) Theory Options
f.readline()
Expand Down Expand Up @@ -1120,6 +1120,10 @@ def read_AeroDyn15(self):
self.read_AeroDyn15Blade()
self.read_AeroDyn15Polar()
self.read_AeroDyn15Coord()
if self.fst_vt['AeroDyn15']['WakeMod'] == 3:
if self.fst_vt['AeroDyn15']['AFAeroMod'] == 2:
raise Exception('OLAF is called with unsteady airfoil aerodynamics, but OLAF currently only supports AFAeroMod == 1')
self.read_AeroDyn15OLAF()

def read_AeroDyn15Blade(self):
# AeroDyn v5.00 Blade Definition File
Expand Down Expand Up @@ -1264,6 +1268,56 @@ def read_AeroDyn15Coord(self):

f.close()

def read_AeroDyn15OLAF(self):

self.fst_vt['AeroDyn15']['OLAF'] = {}
olaf_filename = os.path.join(self.FAST_directory, self.fst_vt['AeroDyn15']['OLAFInputFileName'])
f = open(olaf_filename)
f.readline()
f.readline()
f.readline()
self.fst_vt['AeroDyn15']['OLAF']['IntMethod'] = int_read(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['DTfvw'] = float_read(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['FreeWakeStart'] = float_read(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['FullCircStart'] = float_read(f.readline().split()[0])
f.readline()
self.fst_vt['AeroDyn15']['OLAF']['CircSolvingMethod'] = int_read(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['CircSolvConvCrit'] = float_read(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['CircSolvRelaxation'] = float_read(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['CircSolvMaxIter'] = int_read(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['PrescribedCircFile'] = f.readline().split()[0]
f.readline()
f.readline()
f.readline()
self.fst_vt['AeroDyn15']['OLAF']['nNWPanel'] = int(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['WakeLength'] = int(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['FreeWakeLength'] = int_read(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['FWShedVorticity'] = float_read(f.readline().split()[0])
f.readline()
self.fst_vt['AeroDyn15']['OLAF']['DiffusionMethod'] = int_read(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['RegDeterMethod'] = int_read(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['RegFunction'] = int_read(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['WakeRegMethod'] = int_read(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['WakeRegFactor'] = float(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['WingRegFactor'] = float(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['CoreSpreadEddyVisc'] = int(f.readline().split()[0])
f.readline()
self.fst_vt['AeroDyn15']['OLAF']['TwrShadowOnWake'] = bool_read(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['ShearModel'] = int_read(f.readline().split()[0])
f.readline()
self.fst_vt['AeroDyn15']['OLAF']['VelocityMethod'] = int_read(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['TreeBranchFactor']= float_read(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['PartPerSegment'] = int(f.readline().split()[0])
f.readline()
f.readline()
self.fst_vt['AeroDyn15']['OLAF']['WrVTk'] = int(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['nVTKBlades'] = int(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['VTKCoord'] = int_read(f.readline().split()[0])
self.fst_vt['AeroDyn15']['OLAF']['VTK_fps'] = float_read(f.readline().split()[0])
f.readline()
f.close()


def read_ServoDyn(self):
# ServoDyn v1.05 Input File
# Currently no differences between FASTv8.16 and OpenFAST.
Expand All @@ -1287,12 +1341,12 @@ def read_ServoDyn(self):
self.fst_vt['ServoDyn']['TPitManS1'] = float_read(f.readline().split()[0])
self.fst_vt['ServoDyn']['TPitManS2'] = float_read(f.readline().split()[0])
self.fst_vt['ServoDyn']['TPitManS3'] = float_read(f.readline().split()[0])
self.fst_vt['ServoDyn']['PitManRat1'] = float_read(f.readline().split()[0])
self.fst_vt['ServoDyn']['PitManRat2'] = float_read(f.readline().split()[0])
self.fst_vt['ServoDyn']['PitManRat3'] = float_read(f.readline().split()[0])
self.fst_vt['ServoDyn']['BlPitchF1'] = float_read(f.readline().split()[0])
self.fst_vt['ServoDyn']['BlPitchF2'] = float_read(f.readline().split()[0])
self.fst_vt['ServoDyn']['BlPitchF3'] = float_read(f.readline().split()[0])
self.fst_vt['ServoDyn']['PitManRat(1)'] = float_read(f.readline().split()[0])
self.fst_vt['ServoDyn']['PitManRat(2)'] = float_read(f.readline().split()[0])
self.fst_vt['ServoDyn']['PitManRat(3)'] = float_read(f.readline().split()[0])
self.fst_vt['ServoDyn']['BlPitchF(1)'] = float_read(f.readline().split()[0])
self.fst_vt['ServoDyn']['BlPitchF(2)'] = float_read(f.readline().split()[0])
self.fst_vt['ServoDyn']['BlPitchF(3)'] = float_read(f.readline().split()[0])

# Geneartor and Torque Control (gen_torq_ctrl)
f.readline()
Expand Down Expand Up @@ -1447,15 +1501,14 @@ def read_DISCON_in(self):
self.fst_vt['DISCON_in']['Ct_table'] = Ct_table
self.fst_vt['DISCON_in']['Cq_table'] = Cq_table
except:
pass
print('WARNING: Cp table not loaded!')

# Add some DISCON entries that might be needed within WISDEM
self.fst_vt['DISCON_in']['v_rated'] = 1.

else:
del self.fst_vt['DISCON_in']


def read_HydroDyn(self):
# AeroDyn v2.03

Expand Down Expand Up @@ -2150,7 +2203,8 @@ def read_MoorDyn(self):
self.fst_vt['MoorDyn']['NumSegs'] = []
self.fst_vt['MoorDyn']['NodeAnch'] = []
self.fst_vt['MoorDyn']['NodeFair'] = []
self.fst_vt['MoorDyn']['Flags_Outputs'] = []
self.fst_vt['MoorDyn']['Outputs'] = []
self.fst_vt['MoorDyn']['CtrlChan'] = []
for i in range(self.fst_vt['MoorDyn']['NLines']):
data_line = f.readline().strip().split()
self.fst_vt['MoorDyn']['Line'].append(int(data_line[0]))
Expand All @@ -2159,7 +2213,11 @@ def read_MoorDyn(self):
self.fst_vt['MoorDyn']['NumSegs'].append(int(data_line[3]))
self.fst_vt['MoorDyn']['NodeAnch'].append(int(data_line[4]))
self.fst_vt['MoorDyn']['NodeFair'].append(int(data_line[5]))
self.fst_vt['MoorDyn']['Flags_Outputs'].append(str(data_line[6]))
self.fst_vt['MoorDyn']['Outputs'].append(str(data_line[6]))
if len(data_line) > 7:
self.fst_vt['MoorDyn']['CtrlChan'].append(int(data_line[7]))
else:
self.fst_vt['MoorDyn']['CtrlChan'].append(0)
f.readline()
self.fst_vt['MoorDyn']['dtM'] = float_read(f.readline().split()[0])
self.fst_vt['MoorDyn']['kbot'] = float_read(f.readline().split()[0])
Expand Down
Loading

0 comments on commit 639a23f

Please sign in to comment.