From 44c1549ac638f04bb5fce907000f80c796442fa1 Mon Sep 17 00:00:00 2001 From: dzalkind Date: Wed, 10 Jan 2024 14:50:19 -0700 Subject: [PATCH] Update OpenFAST reader for v4.0 --- ROSCO_toolbox/ofTools/fast_io/FAST_reader.py | 805 ++++++++++++------ .../ofTools/fast_io/FAST_vars_out.py | 100 +++ ROSCO_toolbox/ofTools/fast_io/FAST_writer.py | 324 +++++-- 3 files changed, 888 insertions(+), 341 deletions(-) diff --git a/ROSCO_toolbox/ofTools/fast_io/FAST_reader.py b/ROSCO_toolbox/ofTools/fast_io/FAST_reader.py index 24bc6ed4..68aa594d 100644 --- a/ROSCO_toolbox/ofTools/fast_io/FAST_reader.py +++ b/ROSCO_toolbox/ofTools/fast_io/FAST_reader.py @@ -18,6 +18,26 @@ def readline_filterComments(f): read = False return line +def read_array(f,len,array_type=str): + strings = re.split(',| ',f.readline().strip()) + while '' in strings: # remove empties + strings.remove('') + + arr = strings[:len] # select len strings + + if array_type==str: + arr = [ar.replace('"','') for ar in arr] # remove quotes and commas + elif array_type==float: + arr = [float_read(ar) for ar in arr] + elif array_type==int: + arr = [int_read(ar) for ar in arr] + elif array_type==bool: + arr = [bool_read(ar) for ar in arr] + else: + raise Exception(f"read_array with type {str(array_type)} not currently supported") + + return arr + def fix_path(name): """ split a path, then reconstruct it using os.path.join """ name = re.split("\\\|/", name) @@ -99,6 +119,7 @@ def __init__(self): self.fst_vt['ServoDyn'] = {} self.fst_vt['DISCON_in'] = {} self.fst_vt['HydroDyn'] = {} + self.fst_vt['SeaState'] = {} self.fst_vt['MoorDyn'] = {} self.fst_vt['SubDyn'] = {} self.fst_vt['MAP'] = {} @@ -130,6 +151,24 @@ def loop_dict(vartree, search_var, branch): var = var.replace(' ', '') loop_dict(vartree_head, var, []) + def read_outlist(self,f,module): + ''' + Replacement for set_outlist that doesn't care about whether the channel is in the outlist vartree + Easier, but riskier because OpenFAST can crash + + Inputs: f - file handle + module - of OpenFAST, e.g. SubDyn, SeaState (these modules use this) + ''' + data = f.readline() + while data.split()[0] != 'END': + pattern = r'"(.*?)"' # grab only the text between quotes + data = re.findall(pattern, data)[0] + channels = data.split(',') # split on commas + channels = [c.strip() for c in channels] # strip whitespace + for c in channels: + self.fst_vt['outlist'][module][c] = True + data = f.readline() + def read_MainInput(self): # Main FAST v8.16-v8.17 Input File # Currently no differences between FASTv8.16 and OpenFAST. @@ -157,6 +196,7 @@ def read_MainInput(self): self.fst_vt['Fst']['CompInflow'] = int(f.readline().split()[0]) self.fst_vt['Fst']['CompAero'] = int(f.readline().split()[0]) self.fst_vt['Fst']['CompServo'] = int(f.readline().split()[0]) + self.fst_vt['Fst']['CompSeaState'] = int(f.readline().split()[0]) self.fst_vt['Fst']['CompHydro'] = int(f.readline().split()[0]) self.fst_vt['Fst']['CompSub'] = int(f.readline().split()[0]) self.fst_vt['Fst']['CompMooring'] = int(f.readline().split()[0]) @@ -184,6 +224,7 @@ def read_MainInput(self): self.fst_vt['Fst']['InflowFile'] = f.readline().split()[0][1:-1] self.fst_vt['Fst']['AeroFile'] = f.readline().split()[0][1:-1] self.fst_vt['Fst']['ServoFile'] = f.readline().split()[0][1:-1] + self.fst_vt['Fst']['SeaState'] = f.readline().split()[0][1:-1] self.fst_vt['Fst']['HydroFile'] = f.readline().split()[0][1:-1] self.fst_vt['Fst']['SubFile'] = f.readline().split()[0][1:-1] self.fst_vt['Fst']['MooringFile'] = f.readline().split()[0][1:-1] @@ -209,8 +250,8 @@ def read_MainInput(self): self.fst_vt['Fst']['TrimGain'] = f.readline().split()[0] self.fst_vt['Fst']['Twr_Kdmp'] = f.readline().split()[0] self.fst_vt['Fst']['Bld_Kdmp'] = f.readline().split()[0] - self.fst_vt['Fst']['NLinTimes'] = int_read(f.readline().split()[0]) - self.fst_vt['Fst']['LinTimes'] = read_array(f,max(1,self.fst_vt['Fst']['NLinTimes']),int) # read at least 1 + self.fst_vt['Fst']['NLinTimes'] = int(f.readline().split()[0]) + self.fst_vt['Fst']['LinTimes'] = read_array(f, self.fst_vt['Fst']['NLinTimes'], float) self.fst_vt['Fst']['LinInputs'] = f.readline().split()[0] self.fst_vt['Fst']['LinOutputs'] = f.readline().split()[0] self.fst_vt['Fst']['LinOutJac'] = f.readline().split()[0] @@ -384,17 +425,13 @@ def read_ElastoDyn(self, ed_file): self.fst_vt['ElastoDyn']['DecFact'] = int(f.readline().split()[0]) self.fst_vt['ElastoDyn']['NTwGages'] = int(f.readline().split()[0]) if self.fst_vt['ElastoDyn']['NTwGages'] != 0: #loop over elements if there are gauges to be added, otherwise assign directly - self.fst_vt['ElastoDyn']['TwrGagNd'] = f.readline().strip().split()[:self.fst_vt['ElastoDyn']['NTwGages']] - for i, bldgag in enumerate(self.fst_vt['ElastoDyn']['TwrGagNd']): - self.fst_vt['ElastoDyn']['TwrGagNd'][i] = int(bldgag.strip(',')) + self.fst_vt['ElastoDyn']['TwrGagNd'] = read_array(f,self.fst_vt['ElastoDyn']['NTwGages'],int) else: self.fst_vt['ElastoDyn']['TwrGagNd'] = 0 f.readline() self.fst_vt['ElastoDyn']['NBlGages'] = int(f.readline().split()[0]) if self.fst_vt['ElastoDyn']['NBlGages'] != 0: - self.fst_vt['ElastoDyn']['BldGagNd'] = f.readline().strip().split()[:self.fst_vt['ElastoDyn']['NBlGages']] - for i, bldgag in enumerate(self.fst_vt['ElastoDyn']['BldGagNd']): - self.fst_vt['ElastoDyn']['BldGagNd'][i] = int(bldgag.strip(',')) + self.fst_vt['ElastoDyn']['BldGagNd'] = read_array(f,self.fst_vt['ElastoDyn']['NBlGages'],int) else: self.fst_vt['ElastoDyn']['BldGagNd'] = 0 f.readline() @@ -1653,7 +1690,8 @@ def read_DISCON_in(self): self.fst_vt['DISCON_in'] = read_DISCON(discon_in_file) # Some additional filename parsing - self.fst_vt['DISCON_in']['PerfFileName'] = os.path.abspath(os.path.join(self.FAST_directory, self.fst_vt['DISCON_in']['PerfFileName'])) + discon_dir = os.path.dirname(discon_in_file) + self.fst_vt['DISCON_in']['PerfFileName'] = os.path.abspath(os.path.join(discon_dir, self.fst_vt['DISCON_in']['PerfFileName'])) # Try to read rotor performance data if it is available try: @@ -1689,74 +1727,31 @@ def read_HydroDyn(self, hd_file): f.readline() self.fst_vt['HydroDyn']['Echo'] = bool_read(f.readline().split()[0]) - # ENVIRONMENTAL CONDITIONS - f.readline() - self.fst_vt['HydroDyn']['WtrDens'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WtrDpth'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['MSL2SWL'] = float_read(f.readline().split()[0]) - - # WAVES - f.readline() - self.fst_vt['HydroDyn']['WaveMod'] = int_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WaveStMod'] = int_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WaveTMax'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WaveDT'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WaveHs'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WaveTp'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WavePkShp'] = float_read(f.readline().split()[0]) # default - self.fst_vt['HydroDyn']['WvLowCOff'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WvHiCOff'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WaveDir'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WaveDirMod'] = int_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WaveDirSpread'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WaveNDir'] = int_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WaveDirRange'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WaveSeed1'] = int_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WaveSeed2'] = int_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WaveNDAmp'] = bool_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WvKinFile'] = f.readline().split()[0][1:-1] - self.fst_vt['HydroDyn']['NWaveElev'] = int_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WaveElevxi'] = [idx.strip() for idx in f.readline().split('WaveElevxi')[0].split(',')] - self.fst_vt['HydroDyn']['WaveElevyi'] = [idx.strip() for idx in f.readline().split('WaveElevyi')[0].split(',')] - - # 2ND-ORDER WAVES - f.readline() - self.fst_vt['HydroDyn']['WvDiffQTF'] = bool_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WvSumQTF'] = bool_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WvLowCOffD'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WvHiCOffD'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WvLowCOffS'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['WvHiCOffS'] = float_read(f.readline().split()[0]) - - # CURRENT - f.readline() - self.fst_vt['HydroDyn']['CurrMod'] = int_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['CurrSSV0'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['CurrSSDir'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['CurrNSRef'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['CurrNSV0'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['CurrNSDir'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['CurrDIV'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['CurrDIDir'] = float_read(f.readline().split()[0]) # FLOATING PLATFORM f.readline() self.fst_vt['HydroDyn']['PotMod'] = int_read(f.readline().split()[0]) self.fst_vt['HydroDyn']['ExctnMod'] = int_read(f.readline().split()[0]) + self.fst_vt['HydroDyn']['ExctnDisp'] = int_read(f.readline().split()[0]) + self.fst_vt['HydroDyn']['ExctnCutOff'] = int_read(f.readline().split()[0]) self.fst_vt['HydroDyn']['RdtnMod'] = int_read(f.readline().split()[0]) self.fst_vt['HydroDyn']['RdtnTMax'] = float_read(f.readline().split()[0]) self.fst_vt['HydroDyn']['RdtnDT'] = float_read(f.readline().split()[0]) self.fst_vt['HydroDyn']['NBody'] = int_read(f.readline().split()[0]) self.fst_vt['HydroDyn']['NBodyMod'] = int_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['PotFile'] = os.path.normpath(os.path.join(os.path.split(hd_file)[0], f.readline().split()[0][1:-1])) - self.fst_vt['HydroDyn']['WAMITULEN'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['PtfmRefxt'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['PtfmRefyt'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['PtfmRefzt'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['PtfmRefztRot'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['PtfmVol0'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['PtfmCOBxt'] = float_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['PtfmCOByt'] = float_read(f.readline().split()[0]) + + # Get multiple potential files + pot_strings = read_array(f,self.fst_vt['HydroDyn']['NBody'],str) #re.split(',| ',f.readline().strip()) + pot_strings = [os.path.normpath(os.path.join(os.path.split(hd_file)[0],ps)) for ps in pot_strings] # make relative to hd_file + self.fst_vt['HydroDyn']['PotFile'] = pot_strings + self.fst_vt['HydroDyn']['WAMITULEN'] = read_array(f,self.fst_vt['HydroDyn']['NBody'],float) + self.fst_vt['HydroDyn']['PtfmRefxt'] = read_array(f,self.fst_vt['HydroDyn']['NBody'],float) + self.fst_vt['HydroDyn']['PtfmRefyt'] = read_array(f,self.fst_vt['HydroDyn']['NBody'],float) + self.fst_vt['HydroDyn']['PtfmRefzt'] = read_array(f,self.fst_vt['HydroDyn']['NBody'],float) + self.fst_vt['HydroDyn']['PtfmRefztRot'] = read_array(f,self.fst_vt['HydroDyn']['NBody'],float) + self.fst_vt['HydroDyn']['PtfmVol0'] = read_array(f,self.fst_vt['HydroDyn']['NBody'],float) + self.fst_vt['HydroDyn']['PtfmCOBxt'] = read_array(f,self.fst_vt['HydroDyn']['NBody'],float) + self.fst_vt['HydroDyn']['PtfmCOByt'] = read_array(f,self.fst_vt['HydroDyn']['NBody'],float) # 2ND-ORDER FLOATING PLATFORM FORCES f.readline() @@ -1776,9 +1771,14 @@ def read_HydroDyn(self, hd_file): else: raise Exception("Invalid value for fst_vt['HydroDyn']['NBodyMod']") - self.fst_vt['HydroDyn']['AddCLin'] = np.array([[float(idx) for idx in f.readline().strip().split()[:6]] for i in range(6)]) - self.fst_vt['HydroDyn']['AddBLin'] = np.array([[float(idx) for idx in f.readline().strip().split()[:6]] for i in range(6)]) - self.fst_vt['HydroDyn']['AddBQuad'] = np.array([[float(idx) for idx in f.readline().strip().split()[:6]] for i in range(6)]) + self.fst_vt['HydroDyn']['AddCLin'] = np.array([[float(idx) for idx in f.readline().strip().split()[:6*NBody]] for i in range(6)]) + self.fst_vt['HydroDyn']['AddBLin'] = np.array([[float(idx) for idx in f.readline().strip().split()[:6*NBody]] for i in range(6)]) + self.fst_vt['HydroDyn']['AddBQuad'] = np.array([[float(idx) for idx in f.readline().strip().split()[:6*NBody]] for i in range(6)]) + + #STRIP THEORY OPTIONS + f.readline() + self.fst_vt['HydroDyn']['WaveDisp'] = int_read(f.readline().split()[0]) + self.fst_vt['HydroDyn']['AMMod'] = int_read(f.readline().split()[0]) #AXIAL COEFFICIENTS f.readline() @@ -1787,14 +1787,20 @@ def read_HydroDyn(self, hd_file): self.fst_vt['HydroDyn']['AxCd'] = [None]*self.fst_vt['HydroDyn']['NAxCoef'] self.fst_vt['HydroDyn']['AxCa'] = [None]*self.fst_vt['HydroDyn']['NAxCoef'] self.fst_vt['HydroDyn']['AxCp'] = [None]*self.fst_vt['HydroDyn']['NAxCoef'] + self.fst_vt['HydroDyn']['AxFDMod'] = [None]*self.fst_vt['HydroDyn']['NAxCoef'] + self.fst_vt['HydroDyn']['AxVnCOff'] = [None]*self.fst_vt['HydroDyn']['NAxCoef'] + self.fst_vt['HydroDyn']['AxFDLoFSc'] = [None]*self.fst_vt['HydroDyn']['NAxCoef'] ln = f.readline().split() ln = f.readline().split() for i in range(self.fst_vt['HydroDyn']['NAxCoef']): ln = f.readline().split() - self.fst_vt['HydroDyn']['AxCoefID'][i] = int(ln[0]) - self.fst_vt['HydroDyn']['AxCd'][i] = float(ln[1]) - self.fst_vt['HydroDyn']['AxCa'][i] = float(ln[2]) - self.fst_vt['HydroDyn']['AxCp'][i] = float(ln[3]) + self.fst_vt['HydroDyn']['AxCoefID'][i] = int(ln[0]) + self.fst_vt['HydroDyn']['AxCd'][i] = float_read(ln[1]) + self.fst_vt['HydroDyn']['AxCa'][i] = float_read(ln[2]) + self.fst_vt['HydroDyn']['AxCp'][i] = float_read(ln[3]) + self.fst_vt['HydroDyn']['AxFDMod'][i] = float_read(ln[4]) + self.fst_vt['HydroDyn']['AxVnCOff'][i] = float_read(ln[5]) + self.fst_vt['HydroDyn']['AxFDLoFSc'][i] = float_read(ln[6]) #MEMBER JOINTS f.readline() @@ -1835,18 +1841,20 @@ def read_HydroDyn(self, hd_file): f.readline() f.readline() ln = f.readline().split() - self.fst_vt['HydroDyn']['SimplCd'] = float(ln[0]) - self.fst_vt['HydroDyn']['SimplCdMG'] = float(ln[1]) - self.fst_vt['HydroDyn']['SimplCa'] = float(ln[2]) - self.fst_vt['HydroDyn']['SimplCaMG'] = float(ln[3]) - self.fst_vt['HydroDyn']['SimplCp'] = float(ln[4]) - self.fst_vt['HydroDyn']['SimplCpMG'] = float(ln[5]) - self.fst_vt['HydroDyn']['SimplAxCd'] = float(ln[6]) - self.fst_vt['HydroDyn']['SimplAxCdMG'] = float(ln[7]) - self.fst_vt['HydroDyn']['SimplAxCa'] = float(ln[8]) - self.fst_vt['HydroDyn']['SimplAxCaMG'] = float(ln[9]) - self.fst_vt['HydroDyn']['SimplAxCp'] = float(ln[10]) - self.fst_vt['HydroDyn']['SimplAxCpMG'] = float(ln[11]) + self.fst_vt['HydroDyn']['SimplCd'] = float_read(ln[0]) + self.fst_vt['HydroDyn']['SimplCdMG'] = float_read(ln[1]) + self.fst_vt['HydroDyn']['SimplCa'] = float_read(ln[2]) + self.fst_vt['HydroDyn']['SimplCaMG'] = float_read(ln[3]) + self.fst_vt['HydroDyn']['SimplCp'] = float_read(ln[4]) + self.fst_vt['HydroDyn']['SimplCpMG'] = float_read(ln[5]) + self.fst_vt['HydroDyn']['SimplAxCd'] = float_read(ln[6]) + self.fst_vt['HydroDyn']['SimplAxCdMG'] = float_read(ln[7]) + self.fst_vt['HydroDyn']['SimplAxCa'] = float_read(ln[8]) + self.fst_vt['HydroDyn']['SimplAxCaMG'] = float_read(ln[9]) + self.fst_vt['HydroDyn']['SimplAxCp'] = float_read(ln[10]) + self.fst_vt['HydroDyn']['SimplAxCpMG'] = float_read(ln[11]) + self.fst_vt['HydroDyn']['SimplCb'] = float_read(ln[12]) + self.fst_vt['HydroDyn']['SimplCbMG'] = float_read(ln[13]) #DEPTH-BASED HYDRODYNAMIC COEFFICIENTS f.readline() @@ -1864,23 +1872,27 @@ def read_HydroDyn(self, hd_file): self.fst_vt['HydroDyn']['DpthAxCaMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] self.fst_vt['HydroDyn']['DpthAxCp'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] self.fst_vt['HydroDyn']['DpthAxCpMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] + self.fst_vt['HydroDyn']['DpthCb'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] + self.fst_vt['HydroDyn']['DpthCbMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] ln = f.readline().split() ln = f.readline().split() for i in range(self.fst_vt['HydroDyn']['NCoefDpth']): ln = f.readline().split() - self.fst_vt['HydroDyn']['Dpth'][i] = float(ln[0]) - self.fst_vt['HydroDyn']['DpthCd'][i] = float(ln[1]) - self.fst_vt['HydroDyn']['DpthCdMG'][i] = float(ln[2]) - self.fst_vt['HydroDyn']['DpthCa'][i] = float(ln[3]) - self.fst_vt['HydroDyn']['DpthCaMG'][i] = float(ln[4]) - self.fst_vt['HydroDyn']['DpthCp'][i] = float(ln[5]) - self.fst_vt['HydroDyn']['DpthCpMG'][i] = float(ln[6]) - self.fst_vt['HydroDyn']['DpthAxCd'][i] = float(ln[7]) - self.fst_vt['HydroDyn']['DpthAxCdMG'][i] = float(ln[8]) - self.fst_vt['HydroDyn']['DpthAxCa'][i] = float(ln[9]) - self.fst_vt['HydroDyn']['DpthAxCaMG'][i] = float(ln[10]) - self.fst_vt['HydroDyn']['DpthAxCp'][i] = float(ln[11]) - self.fst_vt['HydroDyn']['DpthAxCpMG'][i] = float(ln[12]) + self.fst_vt['HydroDyn']['Dpth'][i] = float_read(ln[0]) + self.fst_vt['HydroDyn']['DpthCd'][i] = float_read(ln[1]) + self.fst_vt['HydroDyn']['DpthCdMG'][i] = float_read(ln[2]) + self.fst_vt['HydroDyn']['DpthCa'][i] = float_read(ln[3]) + self.fst_vt['HydroDyn']['DpthCaMG'][i] = float_read(ln[4]) + self.fst_vt['HydroDyn']['DpthCp'][i] = float_read(ln[5]) + self.fst_vt['HydroDyn']['DpthCpMG'][i] = float_read(ln[6]) + self.fst_vt['HydroDyn']['DpthAxCd'][i] = float_read(ln[7]) + self.fst_vt['HydroDyn']['DpthAxCdMG'][i] = float_read(ln[8]) + self.fst_vt['HydroDyn']['DpthAxCa'][i] = float_read(ln[9]) + self.fst_vt['HydroDyn']['DpthAxCaMG'][i] = float_read(ln[10]) + self.fst_vt['HydroDyn']['DpthAxCp'][i] = float_read(ln[11]) + self.fst_vt['HydroDyn']['DpthAxCpMG'][i] = float_read(ln[12]) + self.fst_vt['HydroDyn']['DpthCb'][i] = float_read(ln[13]) + self.fst_vt['HydroDyn']['DpthCbMG'][i] = float_read(ln[14]) #MEMBER-BASED HYDRODYNAMIC COEFFICIENTS f.readline() @@ -1910,36 +1922,44 @@ def read_HydroDyn(self, hd_file): self.fst_vt['HydroDyn']['MemberAxCp2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] self.fst_vt['HydroDyn']['MemberAxCpMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] self.fst_vt['HydroDyn']['MemberAxCpMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] + self.fst_vt['HydroDyn']['MemberCb1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] + self.fst_vt['HydroDyn']['MemberCb2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] + self.fst_vt['HydroDyn']['MemberCbMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] + self.fst_vt['HydroDyn']['MemberCbMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] f.readline() f.readline() for i in range(self.fst_vt['HydroDyn']['NCoefMembers']): ln = f.readline().split() self.fst_vt['HydroDyn']['MemberID_HydC'][i] = int(ln[0]) - self.fst_vt['HydroDyn']['MemberCd1'][i] = float(ln[1]) - self.fst_vt['HydroDyn']['MemberCd2'][i] = float(ln[2]) - self.fst_vt['HydroDyn']['MemberCdMG1'][i] = float(ln[3]) - self.fst_vt['HydroDyn']['MemberCdMG2'][i] = float(ln[4]) - self.fst_vt['HydroDyn']['MemberCa1'][i] = float(ln[5]) - self.fst_vt['HydroDyn']['MemberCa2'][i] = float(ln[6]) - self.fst_vt['HydroDyn']['MemberCaMG1'][i] = float(ln[7]) - self.fst_vt['HydroDyn']['MemberCaMG2'][i] = float(ln[8]) - self.fst_vt['HydroDyn']['MemberCp1'][i] = float(ln[9]) - self.fst_vt['HydroDyn']['MemberCp2'][i] = float(ln[10]) - self.fst_vt['HydroDyn']['MemberCpMG1'][i] = float(ln[11]) - self.fst_vt['HydroDyn']['MemberCpMG2'][i] = float(ln[12]) - self.fst_vt['HydroDyn']['MemberAxCd1'][i] = float(ln[13]) - self.fst_vt['HydroDyn']['MemberAxCd2'][i] = float(ln[14]) - self.fst_vt['HydroDyn']['MemberAxCdMG1'][i] = float(ln[15]) - self.fst_vt['HydroDyn']['MemberAxCdMG2'][i] = float(ln[16]) - self.fst_vt['HydroDyn']['MemberAxCa1'][i] = float(ln[17]) - self.fst_vt['HydroDyn']['MemberAxCa2'][i] = float(ln[18]) - self.fst_vt['HydroDyn']['MemberAxCaMG1'][i] = float(ln[19]) - self.fst_vt['HydroDyn']['MemberAxCaMG2'][i] = float(ln[20]) - self.fst_vt['HydroDyn']['MemberAxCp1'][i] = float(ln[21]) - self.fst_vt['HydroDyn']['MemberAxCp2'][i] = float(ln[22]) - self.fst_vt['HydroDyn']['MemberAxCpMG1'][i] = float(ln[23]) - self.fst_vt['HydroDyn']['MemberAxCpMG2'][i] = float(ln[24]) + self.fst_vt['HydroDyn']['MemberCd1'][i] = float_read(ln[1]) + self.fst_vt['HydroDyn']['MemberCd2'][i] = float_read(ln[2]) + self.fst_vt['HydroDyn']['MemberCdMG1'][i] = float_read(ln[3]) + self.fst_vt['HydroDyn']['MemberCdMG2'][i] = float_read(ln[4]) + self.fst_vt['HydroDyn']['MemberCa1'][i] = float_read(ln[5]) + self.fst_vt['HydroDyn']['MemberCa2'][i] = float_read(ln[6]) + self.fst_vt['HydroDyn']['MemberCaMG1'][i] = float_read(ln[7]) + self.fst_vt['HydroDyn']['MemberCaMG2'][i] = float_read(ln[8]) + self.fst_vt['HydroDyn']['MemberCp1'][i] = float_read(ln[9]) + self.fst_vt['HydroDyn']['MemberCp2'][i] = float_read(ln[10]) + self.fst_vt['HydroDyn']['MemberCpMG1'][i] = float_read(ln[11]) + self.fst_vt['HydroDyn']['MemberCpMG2'][i] = float_read(ln[12]) + self.fst_vt['HydroDyn']['MemberAxCd1'][i] = float_read(ln[13]) + self.fst_vt['HydroDyn']['MemberAxCd2'][i] = float_read(ln[14]) + self.fst_vt['HydroDyn']['MemberAxCdMG1'][i] = float_read(ln[15]) + self.fst_vt['HydroDyn']['MemberAxCdMG2'][i] = float_read(ln[16]) + self.fst_vt['HydroDyn']['MemberAxCa1'][i] = float_read(ln[17]) + self.fst_vt['HydroDyn']['MemberAxCa2'][i] = float_read(ln[18]) + self.fst_vt['HydroDyn']['MemberAxCaMG1'][i] = float_read(ln[19]) + self.fst_vt['HydroDyn']['MemberAxCaMG2'][i] = float_read(ln[20]) + self.fst_vt['HydroDyn']['MemberAxCp1'][i] = float_read(ln[21]) + self.fst_vt['HydroDyn']['MemberAxCp2'][i] = float_read(ln[22]) + self.fst_vt['HydroDyn']['MemberAxCpMG1'][i] = float_read(ln[23]) + self.fst_vt['HydroDyn']['MemberAxCpMG2'][i] = float_read(ln[24]) + self.fst_vt['HydroDyn']['MemberCb1'][i] = float_read(ln[25]) + self.fst_vt['HydroDyn']['MemberCb2'][i] = float_read(ln[26]) + self.fst_vt['HydroDyn']['MemberCbMG1'][i] = float_read(ln[27]) + self.fst_vt['HydroDyn']['MemberCbMG2'][i] = float_read(ln[28]) #MEMBERS f.readline() @@ -1951,6 +1971,7 @@ def read_HydroDyn(self, hd_file): self.fst_vt['HydroDyn']['MPropSetID2'] = [None]*self.fst_vt['HydroDyn']['NMembers'] self.fst_vt['HydroDyn']['MDivSize'] = [None]*self.fst_vt['HydroDyn']['NMembers'] self.fst_vt['HydroDyn']['MCoefMod'] = [None]*self.fst_vt['HydroDyn']['NMembers'] + self.fst_vt['HydroDyn']['MHstLMod'] = [None]*self.fst_vt['HydroDyn']['NMembers'] self.fst_vt['HydroDyn']['PropPot'] = [None]*self.fst_vt['HydroDyn']['NMembers'] ln = f.readline().split() ln = f.readline().split() @@ -1963,7 +1984,8 @@ def read_HydroDyn(self, hd_file): self.fst_vt['HydroDyn']['MPropSetID2'][i] = int(ln[4]) self.fst_vt['HydroDyn']['MDivSize'][i] = float(ln[5]) self.fst_vt['HydroDyn']['MCoefMod'][i] = int(ln[6]) - self.fst_vt['HydroDyn']['PropPot'][i] = bool_read(ln[7]) + self.fst_vt['HydroDyn']['MHstLMod'][i] = int(ln[7]) + self.fst_vt['HydroDyn']['PropPot'][i] = bool_read(ln[8]) #FILLED MEMBERS f.readline() @@ -1976,13 +1998,14 @@ def read_HydroDyn(self, hd_file): ln = f.readline().split() for i in range(self.fst_vt['HydroDyn']['NFillGroups']): ln = f.readline().split() - self.fst_vt['HydroDyn']['FillNumM'][i] = int(ln[0]) - self.fst_vt['HydroDyn']['FillMList'][i] = [int(j) for j in ln[1:-2]] - self.fst_vt['HydroDyn']['FillFSLoc'][i] = float(ln[-2]) - if ln[-1] == 'DEFAULT': + n_fill = int(ln[0]) + self.fst_vt['HydroDyn']['FillNumM'][i] = n_fill + self.fst_vt['HydroDyn']['FillMList'][i] = [int(j) for j in ln[1:1+n_fill]] + self.fst_vt['HydroDyn']['FillFSLoc'][i] = float(ln[n_fill+1]) + if ln[n_fill+2] == 'DEFAULT': self.fst_vt['HydroDyn']['FillDens'][i] = 'DEFAULT' else: - self.fst_vt['HydroDyn']['FillDens'][i] = float(ln[-1]) + self.fst_vt['HydroDyn']['FillDens'][i] = float(ln[n_fill+2]) #MARINE GROWTH f.readline() @@ -2046,6 +2069,112 @@ def read_HydroDyn(self, hd_file): f.close() + def read_SeaState(self, ss_file): + + f = open(ss_file) + + f.readline() + f.readline() + + self.fst_vt['SeaState']['Echo'] = bool_read(f.readline().split()[0]) + # ENVIRONMENTAL CONDITIONS + f.readline() + self.fst_vt['SeaState']['WtrDens'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WtrDpth'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['MSL2SWL'] = float_read(f.readline().split()[0]) + + # SPATIAL DISCRETIZATION + f.readline() + self.fst_vt['SeaState']['X_HalfWidth'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['Y_HalfWidth'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['Z_Depth'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['NX'] = int_read(f.readline().split()[0]) + self.fst_vt['SeaState']['NY'] = int_read(f.readline().split()[0]) + self.fst_vt['SeaState']['NZ'] = int_read(f.readline().split()[0]) + + # WAVES + f.readline() + self.fst_vt['SeaState']['WaveMod'] = int_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WaveStMod'] = int_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WaveTMax'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WaveDT'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WaveHs'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WaveTp'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WavePkShp'] = float_read(f.readline().split()[0]) # default + self.fst_vt['SeaState']['WvLowCOff'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WvHiCOff'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WaveDir'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WaveDirMod'] = int_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WaveDirSpread'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WaveNDir'] = int_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WaveDirRange'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WaveSeed1'] = int_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WaveSeed2'] = int_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WaveNDAmp'] = bool_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WvKinFile'] = f.readline().split()[0][1:-1] + + # 2ND-ORDER WAVES + f.readline() + self.fst_vt['SeaState']['WvDiffQTF'] = bool_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WvSumQTF'] = bool_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WvLowCOffD'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WvHiCOffD'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WvLowCOffS'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WvHiCOffS'] = float_read(f.readline().split()[0]) + + # CONSTRAINED WAVE + f.readline() + self.fst_vt['SeaState']['ConstWaveMod'] = int_read(f.readline().split()[0]) + self.fst_vt['SeaState']['CrestHmax'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['CrestTime'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['CrestXi'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['CrestYi'] = float_read(f.readline().split()[0]) + + # CURRENT + f.readline() + self.fst_vt['SeaState']['CurrMod'] = int_read(f.readline().split()[0]) + self.fst_vt['SeaState']['CurrSSV0'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['CurrSSDir'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['CurrNSRef'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['CurrNSV0'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['CurrNSDir'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['CurrDIV'] = float_read(f.readline().split()[0]) + self.fst_vt['SeaState']['CurrDIDir'] = float_read(f.readline().split()[0]) + + # MacCamy-Fuchs Diffraction Model + f.readline() + self.fst_vt['SeaState']['MCFD'] = float_read(f.readline().split()[0]) + + # OUTPUT + f.readline() + self.fst_vt['SeaState']['SeaStSum'] = bool_read(f.readline().split()[0]) + self.fst_vt['SeaState']['OutSwtch'] = int_read(f.readline().split()[0]) + self.fst_vt['SeaState']['OutFmt'] = str(f.readline().split()[0]) + self.fst_vt['SeaState']['OutSFmt'] = str(f.readline().split()[0]) + self.fst_vt['SeaState']['NWaveElev'] = int_read(f.readline().split()[0]) + self.fst_vt['SeaState']['WaveElevxi'] = [float_read(idx.strip()) for idx in f.readline().split('WaveElevxi')[0].replace(',',' ').split()] + self.fst_vt['SeaState']['WaveElevyi'] = [float_read(idx.strip()) for idx in f.readline().split('WaveElevyi')[0].replace(',',' ').split()] + self.fst_vt['SeaState']['NWaveKin'] = int_read(f.readline().split()[0]) + NWaveKin = self.fst_vt['SeaState']['NWaveKin'] + if NWaveKin: + self.fst_vt['SeaState']['WaveKinxi'] = [float_read(idx.strip()) for idx in f.readline().split('WaveKinxi')[0].replace(',',' ').split()] + self.fst_vt['SeaState']['WaveKinyi'] = [float_read(idx.strip()) for idx in f.readline().split('WaveKinyi')[0].replace(',',' ').split()] + self.fst_vt['SeaState']['WaveKinzi'] = [float_read(idx.strip()) for idx in f.readline().split('WaveKinzi')[0].replace(',',' ').split()] + else: + [f.readline() for i in range(3)] + # Unused, filled with dummy location + self.fst_vt['SeaState']['WaveKinxi'] = [0] + self.fst_vt['SeaState']['WaveKinyi'] = [0] + self.fst_vt['SeaState']['WaveKinzi'] = [0] + + + # SeaState Outlist + f.readline() + self.read_outlist(f,'SeaState') + + f.close() + + def read_SubDyn(self, sd_file): f = open(sd_file) @@ -2066,7 +2195,7 @@ def read_SubDyn(self, sd_file): self.fst_vt['SubDyn']['Nmodes'] = int_read(f.readline().split()[0]) self.fst_vt['SubDyn']['JDampings'] = float_read(f.readline().split()[0]) self.fst_vt['SubDyn']['GuyanDampMod'] = int_read(f.readline().split()[0]) - self.fst_vt['SubDyn']['RayleighDamp'] = [float(m.replace(',','')) for m in f.readline().split()[:2]] + self.fst_vt['SubDyn']['RayleighDamp'] = read_array(f,2,float) self.fst_vt['SubDyn']['GuyanDampSize'] = int_read(f.readline().split()[0]) self.fst_vt['SubDyn']['GuyanDamp'] = np.array([[float(idx) for idx in f.readline().strip().split()[:6]] for i in range(self.fst_vt['SubDyn']['GuyanDampSize'])]) f.readline() @@ -2222,8 +2351,8 @@ def read_SubDyn(self, sd_file): ln = f.readline().split() self.fst_vt['SubDyn']['CablePropSetID'][i] = int(ln[0]) self.fst_vt['SubDyn']['CableEA'][i] = float(ln[1]) - self.fst_vt['SubDyn']['CableMatDens'][i] = float(ln[1]) - self.fst_vt['SubDyn']['CableT0'][i] = float(ln[1]) + self.fst_vt['SubDyn']['CableMatDens'][i] = float(ln[2]) + self.fst_vt['SubDyn']['CableT0'][i] = float(ln[3]) # RIGID LINK PROPERTIES f.readline() self.fst_vt['SubDyn']['NRigidPropSets'] = int_read(f.readline().split()[0]) @@ -2235,6 +2364,26 @@ def read_SubDyn(self, sd_file): ln = f.readline().split() self.fst_vt['SubDyn']['RigidPropSetID'][i] = int(ln[0]) self.fst_vt['SubDyn']['RigidMatDens'][i] = float(ln[1]) + # SPRING ELEMENT PROPERTIES + f.readline() + self.fst_vt['SubDyn']['NSpringPropSets'] = int_read(f.readline().split()[0]) + self.fst_vt['SubDyn']['SpringPropSetID'] = [None]*self.fst_vt['SubDyn']['NSpringPropSets'] + spring_list = ['k11','k12','k13','k14','k15','k16', + 'k22','k23','k24','k25','k26', + 'k33','k34','k35','k36', + 'k44','k45','k46', + 'k55','k56', + 'k66'] + for sl in spring_list: # init list + self.fst_vt['SubDyn'][sl] = [None]*self.fst_vt['SubDyn']['NSpringPropSets'] + f.readline() + f.readline() + for i in range(self.fst_vt['SubDyn']['NSpringPropSets']): + ln = f.readline().split() + self.fst_vt['SubDyn']['PropSetID'] = int(ln[0]) + for j, sl in enumerate(spring_list): + self.fst_vt['SubDyn'][sl][i] = ln[j+1] + # MEMBER COSINE MATRICES f.readline() self.fst_vt['SubDyn']['NCOSMs'] = int_read(f.readline().split()[0]) @@ -2294,6 +2443,8 @@ def read_SubDyn(self, sd_file): f.readline() # OUTPUT self.fst_vt['SubDyn']['SumPrint'] = bool_read(f.readline().split()[0]) + self.fst_vt['SubDyn']['OutCBModes'] = int_read(f.readline().split()[0]) + self.fst_vt['SubDyn']['OutFEMModes'] = int_read(f.readline().split()[0]) self.fst_vt['SubDyn']['OutCOSM'] = bool_read(f.readline().split()[0]) self.fst_vt['SubDyn']['OutAll'] = bool_read(f.readline().split()[0]) self.fst_vt['SubDyn']['OutSwtch'] = int_read(f.readline().split()[0]) @@ -2306,22 +2457,17 @@ def read_SubDyn(self, sd_file): self.fst_vt['SubDyn']['NMOutputs'] = int_read(f.readline().split()[0]) self.fst_vt['SubDyn']['MemberID_out'] = [None]*self.fst_vt['SubDyn']['NMOutputs'] self.fst_vt['SubDyn']['NOutCnt'] = [None]*self.fst_vt['SubDyn']['NMOutputs'] - self.fst_vt['SubDyn']['NodeCnt'] = [None]*self.fst_vt['SubDyn']['NMOutputs'] + self.fst_vt['SubDyn']['NodeCnt'] = [[None]]*self.fst_vt['SubDyn']['NMOutputs'] ln = f.readline().split() ln = f.readline().split() for i in range(self.fst_vt['SubDyn']['NMOutputs']): ln = f.readline().split() self.fst_vt['SubDyn']['MemberID_out'][i] = int(ln[0]) self.fst_vt['SubDyn']['NOutCnt'][i] = int(ln[1]) - self.fst_vt['SubDyn']['NodeCnt'][i] = int(ln[2]) + self.fst_vt['SubDyn']['NodeCnt'][i] = [int(node) for node in ln[2:]] f.readline() # SSOutList - data = f.readline() - while data.split()[0] != 'END': - channels = data.split('"') - channel_list = channels[1].split(',') - self.set_outlist(self.fst_vt['outlist']['SubDyn'], channel_list) - data = f.readline() + self.read_outlist(f,'SubDyn') f.close() @@ -2338,18 +2484,23 @@ def read_MAP(self, map_file): f.readline() f.readline() data_line = f.readline().strip().split() - self.fst_vt['MAP']['LineType'] = str(data_line[0]) - self.fst_vt['MAP']['Diam'] = float(data_line[1]) - self.fst_vt['MAP']['MassDenInAir'] = float(data_line[2]) - self.fst_vt['MAP']['EA'] = float(data_line[3]) - self.fst_vt['MAP']['CB'] = float(data_line[4]) - self.fst_vt['MAP']['CIntDamp'] = float(data_line[5]) - self.fst_vt['MAP']['Ca'] = float(data_line[6]) - self.fst_vt['MAP']['Cdn'] = float(data_line[7]) - self.fst_vt['MAP']['Cdt'] = float(data_line[8]) + self.fst_vt['MAP']['LineType'] = [str(data_line[0])] + self.fst_vt['MAP']['Diam'] = [float(data_line[1])] + self.fst_vt['MAP']['MassDenInAir'] = [float(data_line[2])] + self.fst_vt['MAP']['EA'] = [float(data_line[3])] + self.fst_vt['MAP']['CB'] = [float(data_line[4])] + self.fst_vt['MAP']['CIntDamp'] = [float(data_line[5])] + self.fst_vt['MAP']['Ca'] = [float(data_line[6])] + self.fst_vt['MAP']['Cdn'] = [float(data_line[7])] + self.fst_vt['MAP']['Cdt'] = [float(data_line[8])] f.readline() f.readline() f.readline() + # Init map nodes + node_types = ['Node','Type','X','Y','Z','M','B','FX','FY','FZ'] + for nt in node_types: + self.fst_vt['MAP'][nt] = [] + for i in range(2): data_node = f.readline().strip().split() self.fst_vt['MAP']['Node'].append(int(data_node[0])) @@ -2366,12 +2517,12 @@ def read_MAP(self, map_file): f.readline() f.readline() data_line_prop = f.readline().strip().split() - self.fst_vt['MAP']['Line'] = int(data_line_prop[0]) - self.fst_vt['MAP']['LineType'] = str(data_line_prop[1]) - self.fst_vt['MAP']['UnstrLen'] = float(data_line_prop[2]) - self.fst_vt['MAP']['NodeAnch'] = int(data_line_prop[3]) - self.fst_vt['MAP']['NodeFair'] = int(data_line_prop[4]) - self.fst_vt['MAP']['Flags'] = [str(val) for val in data_line_prop[5:]] + self.fst_vt['MAP']['Line'] = [int(data_line_prop[0])] + self.fst_vt['MAP']['LineType'] = [str(data_line_prop[1])] + self.fst_vt['MAP']['UnstrLen'] = [float(data_line_prop[2])] + self.fst_vt['MAP']['NodeAnch'] = [int(data_line_prop[3])] + self.fst_vt['MAP']['NodeFair'] = [int(data_line_prop[4])] + self.fst_vt['MAP']['Flags'] = [[str(val) for val in data_line_prop[5:]]] f.readline() f.readline() f.readline() @@ -2382,119 +2533,250 @@ def read_MoorDyn(self, moordyn_file): f = open(moordyn_file) + # Init optional headers so they exist for writer, even if not read + self.fst_vt['MoorDyn']['Rod_Name'] = [] + self.fst_vt['MoorDyn']['Body_ID'] = [] + self.fst_vt['MoorDyn']['Rod_ID'] = [] + self.fst_vt['MoorDyn']['ChannelID'] = [] + + # MoorDyn f.readline() f.readline() self.fst_vt['MoorDyn']['Echo'] = bool_read(f.readline().split()[0]) - f.readline() - f.readline() - f.readline() - self.fst_vt['MoorDyn']['Name'] = [] - self.fst_vt['MoorDyn']['Diam'] = [] - self.fst_vt['MoorDyn']['MassDen'] = [] - self.fst_vt['MoorDyn']['EA'] = [] - self.fst_vt['MoorDyn']['BA_zeta'] = [] - self.fst_vt['MoorDyn']['EI'] = [] - self.fst_vt['MoorDyn']['Cd'] = [] - self.fst_vt['MoorDyn']['Ca'] = [] - self.fst_vt['MoorDyn']['CdAx'] = [] - self.fst_vt['MoorDyn']['CaAx'] = [] - data_line = f.readline().strip().split() - while data_line[0][:3] != '---': # OpenFAST searches for ---, so we'll do the same - self.fst_vt['MoorDyn']['Name'].append(str(data_line[0])) - self.fst_vt['MoorDyn']['Diam'].append(float(data_line[1])) - self.fst_vt['MoorDyn']['MassDen'].append(float(data_line[2])) - self.fst_vt['MoorDyn']['EA'].append(float(data_line[3])) - self.fst_vt['MoorDyn']['BA_zeta'].append(float(data_line[4])) - self.fst_vt['MoorDyn']['EI'].append(float(data_line[5])) - self.fst_vt['MoorDyn']['Cd'].append(float(data_line[6])) - self.fst_vt['MoorDyn']['Ca'].append(float(data_line[7])) - self.fst_vt['MoorDyn']['CdAx'].append(float(data_line[8])) - self.fst_vt['MoorDyn']['CaAx'].append(float(data_line[9])) - data_line = f.readline().strip().split() - f.readline() - f.readline() - self.fst_vt['MoorDyn']['Point_ID'] = [] - self.fst_vt['MoorDyn']['Attachment'] = [] - self.fst_vt['MoorDyn']['X'] = [] - self.fst_vt['MoorDyn']['Y'] = [] - self.fst_vt['MoorDyn']['Z'] = [] - self.fst_vt['MoorDyn']['M'] = [] - self.fst_vt['MoorDyn']['V'] = [] - self.fst_vt['MoorDyn']['CdA'] = [] - self.fst_vt['MoorDyn']['CA'] = [] - data_line = f.readline().strip().split() - while data_line[0][:3] != '---': # OpenFAST searches for ---, so we'll do the same - self.fst_vt['MoorDyn']['Point_ID'].append(int(data_line[0])) - self.fst_vt['MoorDyn']['Attachment'].append(str(data_line[1])) - self.fst_vt['MoorDyn']['X'].append(float(data_line[2])) - self.fst_vt['MoorDyn']['Y'].append(float(data_line[3])) - self.fst_vt['MoorDyn']['Z'].append(float(data_line[4])) - self.fst_vt['MoorDyn']['M'].append(float(data_line[5])) - self.fst_vt['MoorDyn']['V'].append(float(data_line[6])) - self.fst_vt['MoorDyn']['CdA'].append(float(data_line[7])) - self.fst_vt['MoorDyn']['CA'].append(float(data_line[8])) - data_line = f.readline().strip().split() - f.readline() - f.readline() - self.fst_vt['MoorDyn']['Line_ID'] = [] - self.fst_vt['MoorDyn']['LineType'] = [] - self.fst_vt['MoorDyn']['AttachA'] = [] - self.fst_vt['MoorDyn']['AttachB'] = [] - self.fst_vt['MoorDyn']['UnstrLen'] = [] - self.fst_vt['MoorDyn']['NumSegs'] = [] - self.fst_vt['MoorDyn']['Outputs'] = [] - data_line = f.readline().strip().split() - while data_line[0][:3] != '---': # OpenFAST searches for ---, so we'll do the same - self.fst_vt['MoorDyn']['Line_ID'].append(int(data_line[0])) - self.fst_vt['MoorDyn']['LineType'].append(str(data_line[1])) - self.fst_vt['MoorDyn']['AttachA'].append(int(data_line[2])) - self.fst_vt['MoorDyn']['AttachB'].append(int(data_line[3])) - self.fst_vt['MoorDyn']['UnstrLen'].append(float(data_line[4])) - self.fst_vt['MoorDyn']['NumSegs'].append(int(data_line[5])) - self.fst_vt['MoorDyn']['Outputs'].append(str(data_line[6])) - data_line = f.readline().strip().split() - - # read optional control inputs, there are other optional MoorDyn sections/inputs - self.fst_vt['MoorDyn']['ChannelID'] = [] - self.fst_vt['MoorDyn']['Lines_Control'] = [] - if 'CONTROL' in [dl.upper() for dl in data_line]: - f.readline() - f.readline() - data_line = f.readline().strip().split() - while data_line[0][:3] != '---': # OpenFAST searches for ---, so we'll do the same - self.fst_vt['MoorDyn']['ChannelID'].append(int(data_line[0])) - # Line(s) is a list of mooring lines, spaces are allowed between commas - control_lines = [] - for lines in data_line[1:]: - for line in lines.split(','): - control_lines.append(line.strip(',')) - - # Spaces show up in control_lines as '', remove them all - while '' in control_lines: - control_lines.remove('') - - self.fst_vt['MoorDyn']['Lines_Control'].append(control_lines) + data_line = f.readline() + while data_line: + + # Split and join so all headers are same when detecting next section + data_line = data_line.strip().split() + data_line = ''.join(data_line).lower() + + # Line Types + if 'linetypes' in data_line or 'linedictionary' in data_line: + f.readline() + f.readline() + + # Line types + self.fst_vt['MoorDyn']['Name'] = [] + self.fst_vt['MoorDyn']['Diam'] = [] + self.fst_vt['MoorDyn']['MassDen'] = [] + self.fst_vt['MoorDyn']['EA'] = [] + self.fst_vt['MoorDyn']['BA_zeta'] = [] + self.fst_vt['MoorDyn']['EI'] = [] + self.fst_vt['MoorDyn']['Cd'] = [] + self.fst_vt['MoorDyn']['Ca'] = [] + self.fst_vt['MoorDyn']['CdAx'] = [] + self.fst_vt['MoorDyn']['CaAx'] = [] data_line = f.readline().strip().split() + while data_line[0] and data_line[0][:3] != '---': # OpenFAST searches for ---, so we'll do the same + self.fst_vt['MoorDyn']['Name'].append(str(data_line[0])) + self.fst_vt['MoorDyn']['Diam'].append(float(data_line[1])) + self.fst_vt['MoorDyn']['MassDen'].append(float(data_line[2])) + self.fst_vt['MoorDyn']['EA'].append(float(data_line[3])) + self.fst_vt['MoorDyn']['BA_zeta'].append(float(data_line[4])) + self.fst_vt['MoorDyn']['EI'].append(float(data_line[5])) + self.fst_vt['MoorDyn']['Cd'].append(float(data_line[6])) + self.fst_vt['MoorDyn']['Ca'].append(float(data_line[7])) + self.fst_vt['MoorDyn']['CdAx'].append(float(data_line[8])) + self.fst_vt['MoorDyn']['CaAx'].append(float(data_line[9])) + data_line = f.readline().strip().split() + data_line = ''.join(data_line) # re-join + + elif 'rodtypes' in data_line or 'roddictionary' in data_line: + data_line = f.readline() + data_line = f.readline() + + self.fst_vt['MoorDyn']['Rod_Diam'] = [] + self.fst_vt['MoorDyn']['Rod_MassDen'] = [] + self.fst_vt['MoorDyn']['Rod_Cd'] = [] + self.fst_vt['MoorDyn']['Rod_Ca'] = [] + self.fst_vt['MoorDyn']['Rod_CdEnd'] = [] + self.fst_vt['MoorDyn']['Rod_CaEnd'] = [] - # Solver options, there are a few more optional MoorDyn inputs that can be added line 'CONTROL' - self.fst_vt['MoorDyn']['dtM'] = float_read(f.readline().split()[0]) - self.fst_vt['MoorDyn']['kbot'] = float_read(f.readline().split()[0]) - self.fst_vt['MoorDyn']['cbot'] = float_read(f.readline().split()[0]) - self.fst_vt['MoorDyn']['dtIC'] = float_read(f.readline().split()[0]) - self.fst_vt['MoorDyn']['TmaxIC'] = float_read(f.readline().split()[0]) - self.fst_vt['MoorDyn']['CdScaleIC'] = float_read(f.readline().split()[0]) - self.fst_vt['MoorDyn']['threshIC'] = float_read(f.readline().split()[0]) - f.readline() + data_line = f.readline().strip().split() + while data_line[0] and data_line[0][:3] != '---': # OpenFAST searches for ---, so we'll do the same + self.fst_vt['MoorDyn']['Rod_Name'].append(data_line[0]) + self.fst_vt['MoorDyn']['Rod_Diam'].append(float(data_line[1])) + self.fst_vt['MoorDyn']['Rod_MassDen'].append(float(data_line[2])) + self.fst_vt['MoorDyn']['Rod_Cd'].append(float(data_line[3])) + self.fst_vt['MoorDyn']['Rod_Ca'].append(float(data_line[4])) + self.fst_vt['MoorDyn']['Rod_CdEnd'].append(float(data_line[5])) + self.fst_vt['MoorDyn']['Rod_CaEnd'].append(float(data_line[6])) + data_line = f.readline().strip().split() + data_line = ''.join(data_line) # re-join for reading next section uniformly - data = f.readline() - while data.split()[0] != 'END': - channels = data.strip().strip('"').strip("'") - channel_list = channels.split(',') - self.set_outlist(self.fst_vt['outlist']['MoorDyn'], channel_list) - data = f.readline() + + elif 'bodies' in data_line or 'bodylist' in data_line or 'bodyproperties' in data_line: + + f.readline() + f.readline() + self.fst_vt['MoorDyn']['Body_ID'] = [] + self.fst_vt['MoorDyn']['Body_Attachment'] = [] + self.fst_vt['MoorDyn']['X0'] = [] + self.fst_vt['MoorDyn']['Y0'] = [] + self.fst_vt['MoorDyn']['Z0'] = [] + self.fst_vt['MoorDyn']['r0'] = [] + self.fst_vt['MoorDyn']['p0'] = [] + self.fst_vt['MoorDyn']['y0'] = [] + self.fst_vt['MoorDyn']['Body_Mass'] = [] + self.fst_vt['MoorDyn']['Body_CG'] = [] + self.fst_vt['MoorDyn']['Body_I'] = [] + self.fst_vt['MoorDyn']['Body_Volume'] = [] + self.fst_vt['MoorDyn']['Body_CdA'] = [] + self.fst_vt['MoorDyn']['Body_Ca'] = [] - f.close() + data_line = f.readline().strip().split() + while data_line[0] and data_line[0][:3] != '---': # OpenFAST searches for ---, so we'll do the same + self.fst_vt['MoorDyn']['Body_ID'].append(int(data_line[0])) + self.fst_vt['MoorDyn']['Body_Attachment'].append(data_line[1]) + self.fst_vt['MoorDyn']['X0'].append(float(data_line[2])) + self.fst_vt['MoorDyn']['Y0'].append(float(data_line[3])) + self.fst_vt['MoorDyn']['Z0'].append(float(data_line[4])) + self.fst_vt['MoorDyn']['r0'].append(float(data_line[5])) + self.fst_vt['MoorDyn']['p0'].append(float(data_line[6])) + self.fst_vt['MoorDyn']['y0'].append(float(data_line[7])) + self.fst_vt['MoorDyn']['Body_Mass'].append(float(data_line[8])) + self.fst_vt['MoorDyn']['Body_CG'].append([float(dl) for dl in data_line[9].split('|')]) + self.fst_vt['MoorDyn']['Body_I'].append([float(dl) for dl in data_line[10].split('|')]) + self.fst_vt['MoorDyn']['Body_Volume'].append(float(data_line[11])) + self.fst_vt['MoorDyn']['Body_CdA'].append([float(dl) for dl in data_line[12].split('|')]) + self.fst_vt['MoorDyn']['Body_Ca'].append([float(dl) for dl in data_line[13].split('|')]) + data_line = f.readline().strip().split() + data_line = ''.join(data_line) # re-join for reading next section uniformly + + + elif 'rods' in data_line or 'rodlist' in data_line or 'rodproperties' in data_line: + f.readline() + f.readline() + self.fst_vt['MoorDyn']['Rod_ID'] = [] + self.fst_vt['MoorDyn']['Rod_Type'] = [] + self.fst_vt['MoorDyn']['Rod_Attachment'] = [] + self.fst_vt['MoorDyn']['Xa'] = [] + self.fst_vt['MoorDyn']['Ya'] = [] + self.fst_vt['MoorDyn']['Za'] = [] + self.fst_vt['MoorDyn']['Xb'] = [] + self.fst_vt['MoorDyn']['Yb'] = [] + self.fst_vt['MoorDyn']['Zb'] = [] + self.fst_vt['MoorDyn']['Rod_NumSegs'] = [] + self.fst_vt['MoorDyn']['RodOutputs'] = [] + + data_line = f.readline().strip().split() + while data_line[0] and data_line[0][:3] != '---': # OpenFAST searches for ---, so we'll do the same + self.fst_vt['MoorDyn']['Rod_ID'].append(data_line[0]) + self.fst_vt['MoorDyn']['Rod_Type'].append(data_line[1]) + self.fst_vt['MoorDyn']['Rod_Attachment'].append(data_line[2]) + self.fst_vt['MoorDyn']['Xa'].append(float(data_line[3])) + self.fst_vt['MoorDyn']['Ya'].append(float(data_line[4])) + self.fst_vt['MoorDyn']['Za'].append(float(data_line[5])) + self.fst_vt['MoorDyn']['Xb'].append(float(data_line[6])) + self.fst_vt['MoorDyn']['Yb'].append(float(data_line[7])) + self.fst_vt['MoorDyn']['Zb'].append(float(data_line[8])) + self.fst_vt['MoorDyn']['Rod_NumSegs'].append(int(data_line[9])) + self.fst_vt['MoorDyn']['RodOutputs'].append(data_line[10]) + data_line = f.readline().strip().split() + data_line = ''.join(data_line) # re-join for reading next section uniformly + + elif 'points' in data_line or 'connectionproperties' in data_line or \ + 'nodeproperties' in data_line or 'pointproperties' in data_line or \ + 'pointlist' in data_line: + + f.readline() + f.readline() + self.fst_vt['MoorDyn']['Point_ID'] = [] + self.fst_vt['MoorDyn']['Attachment'] = [] + self.fst_vt['MoorDyn']['X'] = [] + self.fst_vt['MoorDyn']['Y'] = [] + self.fst_vt['MoorDyn']['Z'] = [] + self.fst_vt['MoorDyn']['M'] = [] + self.fst_vt['MoorDyn']['V'] = [] + self.fst_vt['MoorDyn']['CdA'] = [] + self.fst_vt['MoorDyn']['CA'] = [] + data_line = f.readline().strip().split() + while data_line[0] and data_line[0][:3] != '---': # OpenFAST searches for ---, so we'll do the same + self.fst_vt['MoorDyn']['Point_ID'].append(int(data_line[0])) + self.fst_vt['MoorDyn']['Attachment'].append(str(data_line[1])) + self.fst_vt['MoorDyn']['X'].append(float(data_line[2])) + self.fst_vt['MoorDyn']['Y'].append(float(data_line[3])) + self.fst_vt['MoorDyn']['Z'].append(float(data_line[4])) + self.fst_vt['MoorDyn']['M'].append(float(data_line[5])) + self.fst_vt['MoorDyn']['V'].append(float(data_line[6])) + self.fst_vt['MoorDyn']['CdA'].append(float(data_line[7])) + self.fst_vt['MoorDyn']['CA'].append(float(data_line[8])) + data_line = f.readline().strip().split() + data_line = ''.join(data_line) # re-join for reading next section uniformly + + elif 'lines' in data_line or 'lineproperties' in data_line or 'linelist' in data_line: + f.readline() + f.readline() + + # Lines + self.fst_vt['MoorDyn']['Line_ID'] = [] + self.fst_vt['MoorDyn']['LineType'] = [] + self.fst_vt['MoorDyn']['AttachA'] = [] + self.fst_vt['MoorDyn']['AttachB'] = [] + self.fst_vt['MoorDyn']['UnstrLen'] = [] + self.fst_vt['MoorDyn']['NumSegs'] = [] + self.fst_vt['MoorDyn']['Outputs'] = [] + data_line = f.readline().strip().split() + while data_line[0] and data_line[0][:3] != '---': # OpenFAST searches for ---, so we'll do the same + self.fst_vt['MoorDyn']['Line_ID'].append(int(data_line[0])) + self.fst_vt['MoorDyn']['LineType'].append(str(data_line[1])) + self.fst_vt['MoorDyn']['AttachA'].append(int(data_line[2])) + self.fst_vt['MoorDyn']['AttachB'].append(int(data_line[3])) + self.fst_vt['MoorDyn']['UnstrLen'].append(float(data_line[4])) + self.fst_vt['MoorDyn']['NumSegs'].append(int(data_line[5])) + self.fst_vt['MoorDyn']['Outputs'].append(str(data_line[6])) + data_line = f.readline().strip().split() + data_line = ''.join(data_line) # re-join for reading next section uniformly + + elif 'control' in data_line.lower(): + f.readline() + f.readline() + + # read optional control inputs, there are other optional MoorDyn sections/inputs + self.fst_vt['MoorDyn']['ChannelID'] = [] + self.fst_vt['MoorDyn']['Lines_Control'] = [] + + data_line = f.readline().strip().split() + while data_line[0] and data_line[0][:3] != '---': # OpenFAST searches for ---, so we'll do the same + self.fst_vt['MoorDyn']['ChannelID'].append(int(data_line[0])) + # Line(s) is a list of mooring lines, spaces are allowed between commas + control_lines = [] + for lines in data_line[1:]: + for line in lines.split(','): + control_lines.append(line.strip(',')) + + # Spaces show up in control_lines as '', remove them all + while '' in control_lines: + control_lines.remove('') + + self.fst_vt['MoorDyn']['Lines_Control'].append(control_lines) + data_line = f.readline().strip().split() + data_line = ''.join(data_line) # re-join for reading next section uniformly + + + elif 'options' in data_line: + + # Solver options + self.fst_vt['MoorDyn']['dtM'] = float_read(f.readline().split()[0]) + self.fst_vt['MoorDyn']['kbot'] = float_read(f.readline().split()[0]) + self.fst_vt['MoorDyn']['cbot'] = float_read(f.readline().split()[0]) + self.fst_vt['MoorDyn']['dtIC'] = float_read(f.readline().split()[0]) + self.fst_vt['MoorDyn']['TmaxIC'] = float_read(f.readline().split()[0]) + self.fst_vt['MoorDyn']['CdScaleIC'] = float_read(f.readline().split()[0]) + self.fst_vt['MoorDyn']['threshIC'] = float_read(f.readline().split()[0]) + self.fst_vt['MoorDyn']['WaterKin'] = f.readline().split()[0] + f.readline() + + data = f.readline() + while data.split()[0] != 'END': + channels = data.strip().strip('"').strip("'") + channel_list = channels.split(',') + self.set_outlist(self.fst_vt['outlist']['MoorDyn'], channel_list) + data = f.readline() + + f.close() + break def execute(self): @@ -2530,6 +2812,9 @@ def execute(self): hd_file = os.path.normpath(os.path.join(self.FAST_directory, self.fst_vt['Fst']['HydroFile'])) if os.path.isfile(hd_file): self.read_HydroDyn(hd_file) + ss_file = os.path.normpath(os.path.join(self.FAST_directory, self.fst_vt['Fst']['SeaState'])) + if os.path.isfile(ss_file): + self.read_SeaState(ss_file) sd_file = os.path.normpath(os.path.join(self.FAST_directory, self.fst_vt['Fst']['SubFile'])) if os.path.isfile(sd_file): self.read_SubDyn(sd_file) diff --git a/ROSCO_toolbox/ofTools/fast_io/FAST_vars_out.py b/ROSCO_toolbox/ofTools/fast_io/FAST_vars_out.py index 91d1b4b3..377204d1 100644 --- a/ROSCO_toolbox/ofTools/fast_io/FAST_vars_out.py +++ b/ROSCO_toolbox/ofTools/fast_io/FAST_vars_out.py @@ -8195,6 +8195,105 @@ Morison['J8FAMzi'] = False # (N); ; Morison['J9FAMzi'] = False # (N); ; +""" SeaState """ +SeaState = {} + +# Wave Elevations +SeaState['Wave1Elev'] = False # (m); Total (first-order plus second-order) wave elevation (global Z height) at the 1st user-requested location (location is specified in the global coordinate system); +SeaState['Wave2Elev'] = False # (m); Total (first-order plus second-order) wave elevation (global Z height) at the 2nd user-requested location (location is specified in the global coordinate system); +SeaState['Wave3Elev'] = False # (m); Total (first-order plus second-order) wave elevation (global Z height) at the 3rd user-requested location (location is specified in the global coordinate system); +SeaState['Wave4Elev'] = False # (m); Total (first-order plus second-order) wave elevation (global Z height) at the 4th user-requested location (location is specified in the global coordinate system); +SeaState['Wave5Elev'] = False # (m); Total (first-order plus second-order) wave elevation (global Z height) at the 5th user-requested location (location is specified in the global coordinate system); +SeaState['Wave6Elev'] = False # (m); Total (first-order plus second-order) wave elevation (global Z height) at the 6th user-requested location (location is specified in the global coordinate system); +SeaState['Wave7Elev'] = False # (m); Total (first-order plus second-order) wave elevation (global Z height) at the 7th user-requested location (location is specified in the global coordinate system); +SeaState['Wave8Elev'] = False # (m); Total (first-order plus second-order) wave elevation (global Z height) at the 8th user-requested location (location is specified in the global coordinate system); +SeaState['Wave9Elev'] = False # (m); Total (first-order plus second-order) wave elevation (global Z height) at the 9th user-requested location (location is specified in the global coordinate system); +SeaState['Wave1Elv1'] = False # (m); First-order wave elevation (global Z height) at the 1st user-requested location (location is specified in the global coordinate system); +SeaState['Wave2Elv1'] = False # (m); First-order wave elevation (global Z height) at the 2nd user-requested location (location is specified in the global coordinate system); +SeaState['Wave3Elv1'] = False # (m); First-order wave elevation (global Z height) at the 3rd user-requested location (location is specified in the global coordinate system); +SeaState['Wave4Elv1'] = False # (m); First-order wave elevation (global Z height) at the 4th user-requested location (location is specified in the global coordinate system); +SeaState['Wave5Elv1'] = False # (m); First-order wave elevation (global Z height) at the 5th user-requested location (location is specified in the global coordinate system); +SeaState['Wave6Elv1'] = False # (m); First-order wave elevation (global Z height) at the 6th user-requested location (location is specified in the global coordinate system); +SeaState['Wave7Elv1'] = False # (m); First-order wave elevation (global Z height) at the 7th user-requested location (location is specified in the global coordinate system); +SeaState['Wave8Elv1'] = False # (m); First-order wave elevation (global Z height) at the 8th user-requested location (location is specified in the global coordinate system); +SeaState['Wave9Elv1'] = False # (m); First-order wave elevation (global Z height) at the 9th user-requested location (location is specified in the global coordinate system); +SeaState['Wave1Elv2'] = False # (m); Second-order wave elevation (global Z height) at the 1st user-requested location (location is specified in the global coordinate system); +SeaState['Wave2Elv2'] = False # (m); Second-order wave elevation (global Z height) at the 2nd user-requested location (location is specified in the global coordinate system); +SeaState['Wave3Elv2'] = False # (m); Second-order wave elevation (global Z height) at the 3rd user-requested location (location is specified in the global coordinate system); +SeaState['Wave4Elv2'] = False # (m); Second-order wave elevation (global Z height) at the 4th user-requested location (location is specified in the global coordinate system); +SeaState['Wave5Elv2'] = False # (m); Second-order wave elevation (global Z height) at the 5th user-requested location (location is specified in the global coordinate system); +SeaState['Wave6Elv2'] = False # (m); Second-order wave elevation (global Z height) at the 6th user-requested location (location is specified in the global coordinate system); +SeaState['Wave7Elv2'] = False # (m); Second-order wave elevation (global Z height) at the 7th user-requested location (location is specified in the global coordinate system); +SeaState['Wave8Elv2'] = False # (m); Second-order wave elevation (global Z height) at the 8th user-requested location (location is specified in the global coordinate system); +SeaState['Wave9Elv2'] = False # (m); Second-order wave elevation (global Z height) at the 9th user-requested location (location is specified in the global coordinate system); + +# Wave Kinematics +SeaState['FVel1xi'] = False # (m/s); fluid velocity along the global x-direction at the 1st user-requested location (location is specified in the global coordinate system); +SeaState['FVel2xi'] = False # (m/s); fluid velocity along the global x-direction at the 2nd user-requested location (location is specified in the global coordinate system); +SeaState['FVel3xi'] = False # (m/s); fluid velocity along the global x-direction at the 3rd user-requested location (location is specified in the global coordinate system); +SeaState['FVel4xi'] = False # (m/s); fluid velocity along the global x-direction at the 4th user-requested location (location is specified in the global coordinate system); +SeaState['FVel5xi'] = False # (m/s); fluid velocity along the global x-direction at the 5th user-requested location (location is specified in the global coordinate system); +SeaState['FVel6xi'] = False # (m/s); fluid velocity along the global x-direction at the 6th user-requested location (location is specified in the global coordinate system); +SeaState['FVel7xi'] = False # (m/s); fluid velocity along the global x-direction at the 7th user-requested location (location is specified in the global coordinate system); +SeaState['FVel8xi'] = False # (m/s); fluid velocity along the global x-direction at the 8th user-requested location (location is specified in the global coordinate system); +SeaState['FVel9xi'] = False # (m/s); fluid velocity along the global x-direction at the 9th user-requested location (location is specified in the global coordinate system); +SeaState['FVel1yi'] = False # (m/s); fluid velocity along the global y-direction at the 1st user-requested location (location is specified in the global coordinate system); +SeaState['FVel2yi'] = False # (m/s); fluid velocity along the global y-direction at the 2nd user-requested location (location is specified in the global coordinate system); +SeaState['FVel3yi'] = False # (m/s); fluid velocity along the global y-direction at the 3rd user-requested location (location is specified in the global coordinate system); +SeaState['FVel4yi'] = False # (m/s); fluid velocity along the global y-direction at the 4th user-requested location (location is specified in the global coordinate system); +SeaState['FVel5yi'] = False # (m/s); fluid velocity along the global y-direction at the 5th user-requested location (location is specified in the global coordinate system); +SeaState['FVel6yi'] = False # (m/s); fluid velocity along the global y-direction at the 6th user-requested location (location is specified in the global coordinate system); +SeaState['FVel7yi'] = False # (m/s); fluid velocity along the global y-direction at the 7th user-requested location (location is specified in the global coordinate system); +SeaState['FVel8yi'] = False # (m/s); fluid velocity along the global y-direction at the 8th user-requested location (location is specified in the global coordinate system); +SeaState['FVel9yi'] = False # (m/s); fluid velocity along the global y-direction at the 9th user-requested location (location is specified in the global coordinate system); +SeaState['FVel1zi'] = False # (m/s); fluid velocity along the global z-direction at the 1st user-requested location (location is specified in the global coordinate system); +SeaState['FVel2zi'] = False # (m/s); fluid velocity along the global z-direction at the 2nd user-requested location (location is specified in the global coordinate system); +SeaState['FVel3zi'] = False # (m/s); fluid velocity along the global z-direction at the 3rd user-requested location (location is specified in the global coordinate system); +SeaState['FVel4zi'] = False # (m/s); fluid velocity along the global z-direction at the 4th user-requested location (location is specified in the global coordinate system); +SeaState['FVel5zi'] = False # (m/s); fluid velocity along the global z-direction at the 5th user-requested location (location is specified in the global coordinate system); +SeaState['FVel6zi'] = False # (m/s); fluid velocity along the global z-direction at the 6th user-requested location (location is specified in the global coordinate system); +SeaState['FVel7zi'] = False # (m/s); fluid velocity along the global z-direction at the 7th user-requested location (location is specified in the global coordinate system); +SeaState['FVel8zi'] = False # (m/s); fluid velocity along the global z-direction at the 8th user-requested location (location is specified in the global coordinate system); +SeaState['FVel9zi'] = False # (m/s); fluid velocity along the global z-direction at the 9th user-requested location (location is specified in the global coordinate system); +SeaState['FAcc1xi'] = False # (m/s^2); fluid acceleration along the global x-direction at the 1st user-requested location (location is specified in the global coordinate system); +SeaState['FAcc2xi'] = False # (m/s^2); fluid acceleration along the global x-direction at the 2nd user-requested location (location is specified in the global coordinate system); +SeaState['FAcc3xi'] = False # (m/s^2); fluid acceleration along the global x-direction at the 3rd user-requested location (location is specified in the global coordinate system); +SeaState['FAcc4xi'] = False # (m/s^2); fluid acceleration along the global x-direction at the 4th user-requested location (location is specified in the global coordinate system); +SeaState['FAcc5xi'] = False # (m/s^2); fluid acceleration along the global x-direction at the 5th user-requested location (location is specified in the global coordinate system); +SeaState['FAcc6xi'] = False # (m/s^2); fluid acceleration along the global x-direction at the 6th user-requested location (location is specified in the global coordinate system); +SeaState['FAcc7xi'] = False # (m/s^2); fluid acceleration along the global x-direction at the 7th user-requested location (location is specified in the global coordinate system); +SeaState['FAcc8xi'] = False # (m/s^2); fluid acceleration along the global x-direction at the 8th user-requested location (location is specified in the global coordinate system); +SeaState['FAcc9xi'] = False # (m/s^2); fluid acceleration along the global x-direction at the 9th user-requested location (location is specified in the global coordinate system); +SeaState['FAcc1yi'] = False # (m/s^2); fluid acceleration along the global y-direction at the 1st user-requested location (location is specified in the global coordinate system); +SeaState['FAcc2yi'] = False # (m/s^2); fluid acceleration along the global y-direction at the 2nd user-requested location (location is specified in the global coordinate system); +SeaState['FAcc3yi'] = False # (m/s^2); fluid acceleration along the global y-direction at the 3rd user-requested location (location is specified in the global coordinate system); +SeaState['FAcc4yi'] = False # (m/s^2); fluid acceleration along the global y-direction at the 4th user-requested location (location is specified in the global coordinate system); +SeaState['FAcc5yi'] = False # (m/s^2); fluid acceleration along the global y-direction at the 5th user-requested location (location is specified in the global coordinate system); +SeaState['FAcc6yi'] = False # (m/s^2); fluid acceleration along the global y-direction at the 6th user-requested location (location is specified in the global coordinate system); +SeaState['FAcc7yi'] = False # (m/s^2); fluid acceleration along the global y-direction at the 7th user-requested location (location is specified in the global coordinate system); +SeaState['FAcc8yi'] = False # (m/s^2); fluid acceleration along the global y-direction at the 8th user-requested location (location is specified in the global coordinate system); +SeaState['FAcc9yi'] = False # (m/s^2); fluid acceleration along the global y-direction at the 9th user-requested location (location is specified in the global coordinate system); +SeaState['FAcc1zi'] = False # (m/s^2); fluid acceleration along the global z-direction at the 1st user-requested location (location is specified in the global coordinate system); +SeaState['FAcc2zi'] = False # (m/s^2); fluid acceleration along the global z-direction at the 2nd user-requested location (location is specified in the global coordinate system); +SeaState['FAcc3zi'] = False # (m/s^2); fluid acceleration along the global z-direction at the 3rd user-requested location (location is specified in the global coordinate system); +SeaState['FAcc4zi'] = False # (m/s^2); fluid acceleration along the global z-direction at the 4th user-requested location (location is specified in the global coordinate system); +SeaState['FAcc5zi'] = False # (m/s^2); fluid acceleration along the global z-direction at the 5th user-requested location (location is specified in the global coordinate system); +SeaState['FAcc6zi'] = False # (m/s^2); fluid acceleration along the global z-direction at the 6th user-requested location (location is specified in the global coordinate system); +SeaState['FAcc7zi'] = False # (m/s^2); fluid acceleration along the global z-direction at the 7th user-requested location (location is specified in the global coordinate system); +SeaState['FAcc8zi'] = False # (m/s^2); fluid acceleration along the global z-direction at the 8th user-requested location (location is specified in the global coordinate system); +SeaState['FAcc9zi'] = False # (m/s^2); fluid acceleration along the global z-direction at the 9th user-requested location (location is specified in the global coordinate system); +SeaState['FDynP1'] = False # (Pa); fluid dynamic pressure at the 1st user-requested location (location is specified in the global coordinate system); +SeaState['FDynP2'] = False # (Pa); fluid dynamic pressure at the 2nd user-requested location (location is specified in the global coordinate system); +SeaState['FDynP3'] = False # (Pa); fluid dynamic pressure at the 3rd user-requested location (location is specified in the global coordinate system); +SeaState['FDynP4'] = False # (Pa); fluid dynamic pressure at the 4th user-requested location (location is specified in the global coordinate system); +SeaState['FDynP5'] = False # (Pa); fluid dynamic pressure at the 5th user-requested location (location is specified in the global coordinate system); +SeaState['FDynP6'] = False # (Pa); fluid dynamic pressure at the 6th user-requested location (location is specified in the global coordinate system); +SeaState['FDynP7'] = False # (Pa); fluid dynamic pressure at the 7th user-requested location (location is specified in the global coordinate system); +SeaState['FDynP8'] = False # (Pa); fluid dynamic pressure at the 8th user-requested location (location is specified in the global coordinate system); +SeaState['FDynP9'] = False # (Pa); fluid dynamic pressure at the 9th user-requested location (location is specified in the global coordinate system); + + + """ SubDyn """ SubDyn = {} @@ -10882,6 +10981,7 @@ FstOutput['HydroDyn'] = HydroDyn FstOutput['Morison'] = Morison FstOutput['SubDyn'] = SubDyn +FstOutput['SeaState'] = SeaState FstOutput['BeamDyn'] = BeamDyn FstOutput['MoorDyn'] = MoorDyn FstOutput['AeroDyn_Nodes'] = AeroDyn_Nodes diff --git a/ROSCO_toolbox/ofTools/fast_io/FAST_writer.py b/ROSCO_toolbox/ofTools/fast_io/FAST_writer.py index 7fcad436..28e63321 100644 --- a/ROSCO_toolbox/ofTools/fast_io/FAST_writer.py +++ b/ROSCO_toolbox/ofTools/fast_io/FAST_writer.py @@ -1,12 +1,14 @@ -import os, sys, copy, random, time +import os +import copy +import random +import time import operator -import yaml import numpy as np from functools import reduce from ROSCO_toolbox.ofTools.fast_io.FAST_reader import InputReader_OpenFAST -from ROSCO_toolbox.utilities import write_rotor_performance, write_DISCON +from ROSCO_toolbox import utilities as ROSCO_utilities ROSCO = True @@ -171,6 +173,8 @@ def execute(self): if self.fst_vt['Fst']['CompHydro'] == 1: self.write_HydroDyn() + if self.fst_vt['Fst']['CompSeaState'] == 1: + self.write_SeaState() if self.fst_vt['Fst']['CompSub'] == 1: self.write_SubDyn() if self.fst_vt['Fst']['CompMooring'] == 1: @@ -210,6 +214,7 @@ def write_MainInput(self): f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['CompInflow'], 'CompInflow', '- Compute inflow wind velocities (switch) {0=still air; 1=InflowWind; 2=external from OpenFOAM}\n')) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['CompAero'], 'CompAero', '- Compute aerodynamic loads (switch) {0=None; 1=AeroDyn v14; 2=AeroDyn v15}\n')) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['CompServo'], 'CompServo', '- Compute control and electrical-drive dynamics (switch) {0=None; 1=ServoDyn}\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['CompSeaState'], 'CompSeaState', '- Compute sea state information (switch) {0=None; 1=SeaState}\n')) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['CompHydro'], 'CompHydro', '- Compute hydrodynamic loads (switch) {0=None; 1=HydroDyn}\n')) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['CompSub'], 'CompSub', '- Compute sub-structural dynamics (switch) {0=None; 1=SubDyn; 2=External Platform MCKF}\n')) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['CompMooring'], 'CompMooring', '- Compute mooring system (switch) {0=None; 1=MAP++; 2=FEAMooring; 3=MoorDyn; 4=OrcaFlex}\n')) @@ -233,6 +238,7 @@ def write_MainInput(self): f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['InflowFile']+'"', 'InflowFile', '- Name of file containing inflow wind input parameters (quoted string)\n')) f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['AeroFile']+'"', 'AeroFile', '- Name of file containing aerodynamic input parameters (quoted string)\n')) f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['ServoFile']+'"', 'ServoFile', '- Name of file containing control and electrical-drive input parameters (quoted string)\n')) + f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['SeaState']+'"', 'SeaState', '- Name of file containing sea state input parameters (quoted string)\n')) f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['HydroFile']+'"', 'HydroFile', '- Name of file containing hydrodynamic input parameters (quoted string)\n')) f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['SubFile']+'"', 'SubFile', '- Name of file containing sub-structural input parameters (quoted string)\n')) f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['MooringFile']+'"', 'MooringFile', '- Name of file containing mooring system input parameters (quoted string)\n')) @@ -799,6 +805,10 @@ def write_AeroDyn15(self): f.write('====== Beddoes-Leishman Unsteady Airfoil Aerodynamics Options ===================================== [used only when AFAeroMod=2]\n') f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['UAMod'], 'UAMod', "- Unsteady Aero Model Switch (switch) {1=Baseline model (Original), 2=Gonzalez's variant (changes in Cn,Cc,Cm), 3=Minnema/Pierce variant (changes in Cc and Cm)} [used only when AFAeroMod=2]\n")) f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['FLookup'], 'FLookup', "- Flag to indicate whether a lookup for f' will be calculated (TRUE) or whether best-fit exponential equations will be used (FALSE); if FALSE S1-S4 must be provided in airfoil input files (flag) [used only when AFAeroMod=2]\n")) + if 'UAStartRad' in self.fst_vt['AeroDyn15']: + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['UAStartRad'], 'UAStartRad', '- Starting radius for dynamic stall (fraction of rotor radius) [used only when AFAeroMod=2; if line is missing UAStartRad=0]\n')) + if 'UAEndRad' in self.fst_vt['AeroDyn15']: + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['UAEndRad'], 'UAEndRad', '- nding radius for dynamic stall (fraction of rotor radius) [used only when AFAeroMod=2; if line is missing UAEndRad=1]\n')) f.write('====== Airfoil Information =========================================================================\n') f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['AFTabMod'], 'AFTabMod', '- Interpolation method for multiple airfoil tables {1=1D interpolation on AoA (first table only); 2=2D interpolation on AoA and Re; 3=2D interpolation on AoA and UserProp} (-)\n')) f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['InCol_Alfa'], 'InCol_Alfa', '- The column in the airfoil tables that contains the angle of attack (-)\n')) @@ -1401,12 +1411,12 @@ def write_DISCON_in(self): self.fst_vt['DISCON_in']['PerfFileName'] = self.FAST_namingOut + '_Cp_Ct_Cq.txt' # Write DISCON input files - write_rotor_performance( + ROSCO_utilities.write_rotor_performance( turbine, txt_filename=os.path.join(self.FAST_runDirectory, self.fst_vt['DISCON_in']['PerfFileName']) ) - write_DISCON( + ROSCO_utilities.write_DISCON( turbine, controller, param_file=discon_in_file, @@ -1424,78 +1434,25 @@ def write_HydroDyn(self): f.write('------- HydroDyn v2.03.* Input File --------------------------------------------\n') f.write('Generated with AeroElasticSE FAST driver\n') f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['Echo'], 'Echo', '- Echo the input file data (flag)\n')) - f.write('---------------------- ENVIRONMENTAL CONDITIONS --------------------------------\n') - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WtrDens'], 'WtrDens', '- Water density (kg/m^3)\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WtrDpth'], 'WtrDpth', '- Water depth (meters)\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['MSL2SWL'], 'MSL2SWL', '- Offset between still-water level and mean sea level (meters) [positive upward; unused when WaveMod = 6; must be zero if PotMod=1 or 2]\n')) - f.write('---------------------- WAVES ---------------------------------------------------\n') - f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WaveMod'], 'WaveMod', '- Incident wave kinematics model {0: none=still water, 1: regular (periodic), 1P#: regular with user-specified phase, 2: JONSWAP/Pierson-Moskowitz spectrum (irregular), 3: White noise spectrum (irregular), 4: user-defined spectrum from routine UserWaveSpctrm (irregular), 5: Externally generated wave-elevation time series, 6: Externally generated full wave-kinematics time series [option 6 is invalid for PotMod/=0]} (switch)\n')) - f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WaveStMod'], 'WaveStMod', '- Model for stretching incident wave kinematics to instantaneous free surface {0: none=no stretching, 1: vertical stretching, 2: extrapolation stretching, 3: Wheeler stretching} (switch) [unused when WaveMod=0 or when PotMod/=0]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WaveTMax'], 'WaveTMax', '- Analysis time for incident wave calculations (sec) [unused when WaveMod=0; determines WaveDOmega=2Pi/WaveTMax in the IFFT]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WaveDT'], 'WaveDT', '- Time step for incident wave calculations (sec) [unused when WaveMod=0; 0.1<=WaveDT<=1.0 recommended; determines WaveOmegaMax=Pi/WaveDT in the IFFT]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WaveHs'], 'WaveHs', '- Significant wave height of incident waves (meters) [used only when WaveMod=1, 2, or 3]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WaveTp'], 'WaveTp', '- Peak-spectral period of incident waves (sec) [used only when WaveMod=1 or 2]\n')) - if isinstance(self.fst_vt['HydroDyn']['WavePkShp'], float): - if self.fst_vt['HydroDyn']['WavePkShp'] == 0.: - WavePkShp = 'Default' - else: - WavePkShp = self.fst_vt['HydroDyn']['WavePkShp'] - else: - WavePkShp = self.fst_vt['HydroDyn']['WavePkShp'] - f.write('{:<22} {:<11} {:}'.format(WavePkShp, 'WavePkShp', '- Peak-shape parameter of incident wave spectrum (-) or DEFAULT (string) [used only when WaveMod=2; use 1.0 for Pierson-Moskowitz]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WvLowCOff'], 'WvLowCOff', '- Low cut-off frequency or lower frequency limit of the wave spectrum beyond which the wave spectrum is zeroed (rad/s) [unused when WaveMod=0, 1, or 6]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WvHiCOff'], 'WvHiCOff', '- High cut-off frequency or upper frequency limit of the wave spectrum beyond which the wave spectrum is zeroed (rad/s) [unused when WaveMod=0, 1, or 6]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WaveDir'], 'WaveDir', '- Incident wave propagation heading direction (degrees) [unused when WaveMod=0 or 6]\n')) - f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WaveDirMod'], 'WaveDirMod', '- Directional spreading function {0: none, 1: COS2S} (-) [only used when WaveMod=2,3, or 4]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WaveDirSpread'], 'WaveDirSpread', '- Wave direction spreading coefficient ( > 0 ) (-) [only used when WaveMod=2,3, or 4 and WaveDirMod=1]\n')) - f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WaveNDir'], 'WaveNDir', '- Number of wave directions (-) [only used when WaveMod=2,3, or 4 and WaveDirMod=1; odd number only]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WaveDirRange'], 'WaveDirRange', '- Range of wave directions (full range: WaveDir +/- 1/2*WaveDirRange) (degrees) [only used when WaveMod=2,3,or 4 and WaveDirMod=1]\n')) - f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WaveSeed1'], 'WaveSeed(1)', '- First random seed of incident waves [-2147483648 to 2147483647] (-) [unused when WaveMod=0, 5, or 6]\n')) - - try: - seed2 = int(self.fst_vt['HydroDyn']['WaveSeed2']) - f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WaveSeed2'], 'WaveSeed(2)', '- Second random seed of incident waves [-2147483648 to 2147483647] (-) [unused when WaveMod=0, 5, or 6]\n')) - except ValueError: - f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WaveSeed2'], 'WaveSeed(2)', '- Second random seed of incident waves [-2147483648 to 2147483647] (-) [unused when WaveMod=0, 5, or 6] for intrinsic pRNG, or an alternative pRNG: "RanLux"\n')) - - f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WaveNDAmp'], 'WaveNDAmp', '- Flag for normally distributed amplitudes (flag) [only used when WaveMod=2, 3, or 4]\n')) - f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['HydroDyn']['WvKinFile']+'"', 'WvKinFile', '- Root name of externally generated wave data file(s) (quoted string) [used only when WaveMod=5 or 6]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NWaveElev'], 'NWaveElev', '- Number of points where the incident wave elevations can be computed (-) [maximum of 9 output locations]\n')) - f.write('{:<22} {:<11} {:}'.format(", ".join(self.fst_vt['HydroDyn']['WaveElevxi']), 'WaveElevxi', '- List of xi-coordinates for points where the incident wave elevations can be output (meters) [NWaveElev points, separated by commas or white space; usused if NWaveElev = 0]\n')) - f.write('{:<22} {:<11} {:}'.format(", ".join(self.fst_vt['HydroDyn']['WaveElevyi']), 'WaveElevyi', '- List of yi-coordinates for points where the incident wave elevations can be output (meters) [NWaveElev points, separated by commas or white space; usused if NWaveElev = 0]\n')) - f.write('---------------------- 2ND-ORDER WAVES ----------------------------------------- [unused with WaveMod=0 or 6]\n') - f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WvDiffQTF'], 'WvDiffQTF', '- Full difference-frequency 2nd-order wave kinematics (flag)\n')) - f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WvSumQTF'], 'WvSumQTF', '- Full summation-frequency 2nd-order wave kinematics (flag)\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WvLowCOffD'], 'WvLowCOffD', '- Low frequency cutoff used in the difference-frequencies (rad/s) [Only used with a difference-frequency method]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WvHiCOffD'], 'WvHiCOffD', '- High frequency cutoff used in the difference-frequencies (rad/s) [Only used with a difference-frequency method]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WvLowCOffS'], 'WvLowCOffS', '- Low frequency cutoff used in the summation-frequencies (rad/s) [Only used with a summation-frequency method]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WvHiCOffS'], 'WvHiCOffS', '- High frequency cutoff used in the summation-frequencies (rad/s) [Only used with a summation-frequency method]\n')) - f.write('---------------------- CURRENT ------------------------------------------------- [unused with WaveMod=6]\n') - f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['CurrMod'], 'CurrMod', '- Current profile model {0: none=no current, 1: standard, 2: user-defined from routine UserCurrent} (switch)\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['CurrSSV0'], 'CurrSSV0', '- Sub-surface current velocity at still water level (m/s) [used only when CurrMod=1]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['CurrSSDir'], 'CurrSSDir', '- Sub-surface current heading direction (degrees) or DEFAULT (string) [used only when CurrMod=1]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['CurrNSRef'], 'CurrNSRef', '- Near-surface current reference depth (meters) [used only when CurrMod=1]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['CurrNSV0'], 'CurrNSV0', '- Near-surface current velocity at still water level (m/s) [used only when CurrMod=1]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['CurrNSDir'], 'CurrNSDir', '- Near-surface current heading direction (degrees) [used only when CurrMod=1]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['CurrDIV'], 'CurrDIV', '- Depth-independent current velocity (m/s) [used only when CurrMod=1]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['CurrDIDir'], 'CurrDIDir', '- Depth-independent current heading direction (degrees) [used only when CurrMod=1]\n')) f.write('---------------------- FLOATING PLATFORM --------------------------------------- [unused with WaveMod=6]\n') f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['PotMod'], 'PotMod', '- Potential-flow model {0: none=no potential flow, 1: frequency-to-time-domain transforms based on WAMIT output, 2: fluid-impulse theory (FIT)} (switch)\n')) f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['ExctnMod'], 'ExctnMod', '- Wave Excitation model {0: None, 1: DFT, 2: state-space} (switch) [only used when PotMod=1; STATE-SPACE REQUIRES *.ssexctn INPUT FILE]\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['ExctnDisp'], 'ExctnDisp','- Method of computing Wave Excitation {0: use undisplaced position, 1: use displaced position, 2: use low-pass filtered displaced position) [only used when PotMod=1 and ExctnMod>0 and SeaState\'s WaveMod>0]} (switch)\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['ExctnCutOff'], 'ExctnCutOff','- Method of computing Wave Excitation {0: use undisplaced position, 1: use displaced position, 2: use low-pass filtered displaced position) [only used when PotMod=1 and ExctnMod>0 and SeaState\'s WaveMod>0]} (switch)\n')) f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['RdtnMod'], 'RdtnMod', '- Radiation memory-effect model {0: no memory-effect calculation, 1: convolution, 2: state-space} (switch) [only used when PotMod=1; STATE-SPACE REQUIRES *.ss INPUT FILE]\n')) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['RdtnTMax'], 'RdtnTMax', '- Analysis time for wave radiation kernel calculations (sec) [only used when PotMod=1; determines RdtnDOmega=Pi/RdtnTMax in the cosine transform; MAKE SURE THIS IS LONG ENOUGH FOR THE RADIATION IMPULSE RESPONSE FUNCTIONS TO DECAY TO NEAR-ZERO FOR THE GIVEN PLATFORM!]\n')) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['RdtnDT'], 'RdtnDT', '- Time step for wave radiation kernel calculations (sec) [only used when PotMod=1; DT<=RdtnDT<=0.1 recommended; determines RdtnOmegaMax=Pi/RdtnDT in the cosine transform]\n')) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NBody'], 'NBody', '- Number of WAMIT bodies to be used (-) [>=1; only used when PotMod=1. If NBodyMod=1, the WAMIT data contains a vector of size 6*NBody x 1 and matrices of size 6*NBody x 6*NBody; if NBodyMod>1, there are NBody sets of WAMIT data each with a vector of size 6 x 1 and matrices of size 6 x 6]\n')) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NBodyMod'], 'NBodyMod', '- Body coupling model {1: include coupling terms between each body and NBody in HydroDyn equals NBODY in WAMIT, 2: neglect coupling terms between each body and NBODY=1 with XBODY=0 in WAMIT, 3: Neglect coupling terms between each body and NBODY=1 with XBODY=/0 in WAMIT} (switch) [only used when PotMod=1]\n')) - f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['HydroDyn']['PotFile']+'"', 'PotFile', '- Root name of potential-flow model data; WAMIT output files containing the linear, nondimensionalized, hydrostatic restoring matrix (.hst), frequency-dependent hydrodynamic added mass matrix and damping matrix (.1), and frequency- and direction-dependent wave excitation force vector per unit wave amplitude (.3) (quoted string) [MAKE SURE THE FREQUENCIES INHERENT IN THESE WAMIT FILES SPAN THE PHYSICALLY-SIGNIFICANT RANGE OF FREQUENCIES FOR THE GIVEN PLATFORM; THEY MUST CONTAIN THE ZERO- AND INFINITE-FREQUENCY LIMITS!]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WAMITULEN'], 'WAMITULEN', '- Characteristic body length scale used to redimensionalize WAMIT output (meters) [only used when PotMod=1]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['PtfmRefxt'], 'PtfmRefxt', '- The xt offset of the body reference point(s) from (0,0,0) (meters) [1 to NBody] [only used when PotMod=1]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['PtfmRefyt'], 'PtfmRefyt', '- The yt offset of the body reference point(s) from (0,0,0) (meters) [1 to NBody] [only used when PotMod=1]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['PtfmRefzt'], 'PtfmRefzt', '- The zt offset of the body reference point(s) from (0,0,0) (meters) [1 to NBody] [only used when PotMod=1. If NBodyMod=2,PtfmRefzt=0.0]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['PtfmRefztRot'], 'PtfmRefztRot', '- The rotation about zt of the body reference frame(s) from xt/yt (degrees) [1 to NBody] [only used when PotMod=1]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['PtfmVol0'], 'PtfmVol0', '- Displaced volume of water when the platform is in its undisplaced position (m^3) [only used when PotMod=1; USE THE SAME VALUE COMPUTED BY WAMIT AS OUTPUT IN THE .OUT FILE!]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['PtfmCOBxt'], 'PtfmCOBxt', '- The xt offset of the center of buoyancy (COB) from the platform reference point (meters) [only used when PotMod=1]\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['PtfmCOByt'], 'PtfmCOByt', '- The yt offset of the center of buoyancy (COB) from the platform reference point (meters) [only used when PotMod=1]\n')) + f.write('{:<22} {:<11} {:}'.format(', '.join([f'"{pf}"' for pf in self.fst_vt['HydroDyn']['PotFile']]), 'PotFile', '- Root name of potential-flow model data; WAMIT output files containing the linear, nondimensionalized, hydrostatic restoring matrix (.hst), frequency-dependent hydrodynamic added mass matrix and damping matrix (.1), and frequency- and direction-dependent wave excitation force vector per unit wave amplitude (.3) (quoted string) [MAKE SURE THE FREQUENCIES INHERENT IN THESE WAMIT FILES SPAN THE PHYSICALLY-SIGNIFICANT RANGE OF FREQUENCIES FOR THE GIVEN PLATFORM; THEY MUST CONTAIN THE ZERO- AND INFINITE-FREQUENCY LIMITS!]\n')) + f.write('{:<22} {:<11} {:}'.format(', '.join([f'{val}' for val in self.fst_vt['HydroDyn']['WAMITULEN']]), 'WAMITULEN', '- Characteristic body length scale used to redimensionalize WAMIT output (meters) [only used when PotMod=1]\n')) + f.write('{:<22} {:<11} {:}'.format(', '.join([f'{val}' for val in self.fst_vt['HydroDyn']['PtfmRefxt']]), 'PtfmRefxt', '- The xt offset of the body reference point(s) from (0,0,0) (meters) [1 to NBody] [only used when PotMod=1]\n')) + f.write('{:<22} {:<11} {:}'.format(', '.join([f'{val}' for val in self.fst_vt['HydroDyn']['PtfmRefyt']]), 'PtfmRefyt', '- The yt offset of the body reference point(s) from (0,0,0) (meters) [1 to NBody] [only used when PotMod=1]\n')) + f.write('{:<22} {:<11} {:}'.format(', '.join([f'{val}' for val in self.fst_vt['HydroDyn']['PtfmRefzt']]), 'PtfmRefzt', '- The zt offset of the body reference point(s) from (0,0,0) (meters) [1 to NBody] [only used when PotMod=1. If NBodyMod=2,PtfmRefzt=0.0]\n')) + f.write('{:<22} {:<11} {:}'.format(', '.join([f'{val}' for val in self.fst_vt['HydroDyn']['PtfmRefztRot']]), 'PtfmRefztRot', '- The rotation about zt of the body reference frame(s) from xt/yt (degrees) [1 to NBody] [only used when PotMod=1]\n')) + f.write('{:<22} {:<11} {:}'.format(', '.join([f'{val}' for val in self.fst_vt['HydroDyn']['PtfmVol0']]), 'PtfmVol0', '- Displaced volume of water when the platform is in its undisplaced position (m^3) [only used when PotMod=1; USE THE SAME VALUE COMPUTED BY WAMIT AS OUTPUT IN THE .OUT FILE!]\n')) + f.write('{:<22} {:<11} {:}'.format(', '.join([f'{val}' for val in self.fst_vt['HydroDyn']['PtfmCOBxt']]), 'PtfmCOBxt', '- The xt offset of the center of buoyancy (COB) from the platform reference point (meters) [only used when PotMod=1]\n')) + f.write('{:<22} {:<11} {:}'.format(', '.join([f'{val}' for val in self.fst_vt['HydroDyn']['PtfmCOByt']]), 'PtfmCOByt', '- The yt offset of the center of buoyancy (COB) from the platform reference point (meters) [only used when PotMod=1]\n')) f.write('---------------------- 2ND-ORDER FLOATING PLATFORM FORCES ---------------------- [unused with WaveMod=0 or 6, or PotMod=0 or 2]\n') f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['MnDrift'], 'MnDrift', "- Mean-drift 2nd-order forces computed {0: None; [7, 8, 9, 10, 11, or 12]: WAMIT file to use} [Only one of MnDrift, NewmanApp, or DiffQTF can be non-zero]\n")) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NewmanApp'], 'NewmanApp', "- Mean- and slow-drift 2nd-order forces computed with Newman's approximation {0: None; [7, 8, 9, 10, 11, or 12]: WAMIT file to use} [Only one of MnDrift, NewmanApp, or DiffQTF can be non-zero. Used only when WaveDirMod=0]\n")) @@ -1545,16 +1502,24 @@ def write_HydroDyn(self): else: ln = ln + "\n" f.write(ln) + + f.write('---------------------- STRIP THEORY OPTIONS --------------------------------------\n') + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WaveDisp'], 'WaveDisp', '- Method of computing Wave Kinematics {0- use undisplaced position, 1- use displaced position) } (switch)\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['AMMod'], 'AMMod', '\n')) + f.write('---------------------- AXIAL COEFFICIENTS --------------------------------------\n') f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NAxCoef'], 'NAxCoef', '- Number of axial coefficients (-)\n')) - f.write(" ".join(['{:^11s}'.format(i) for i in ['AxCoefID', 'AxCd', 'AxCa', 'AxCp']])+'\n') - f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)']*4])+'\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['AxCoefID', 'AxCd', 'AxCa', 'AxCp', 'AxFDMod', 'AxVnCOff', 'AxFDLoFSc']])+'\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)']*7])+'\n') for i in range(self.fst_vt['HydroDyn']['NAxCoef']): ln = [] ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['AxCoefID'][i])) ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['AxCd'][i])) ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['AxCa'][i])) ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['AxCp'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['AxFDMod'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['AxVnCOff'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['AxFDLoFSc'][i])) f.write(" ".join(ln) + '\n') f.write('---------------------- MEMBER JOINTS -------------------------------------------\n') f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NJoints'], 'NJoints', '- Number of joints (-) [must be exactly 0 or at least 2]\n')) @@ -1580,7 +1545,7 @@ def write_HydroDyn(self): ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['PropThck'][i])) f.write(" ".join(ln) + '\n') f.write('---------------------- SIMPLE HYDRODYNAMIC COEFFICIENTS (model 1) --------------\n') - f.write(" ".join(['{:^11s}'.format(i) for i in ['SimplCd', 'SimplCdMG', 'SimplCa', 'SimplCaMG', 'SimplCp', 'SimplCpMG', 'SimplAxCd', 'SimplAxCdMG', 'SimplAxCa', 'SimplAxCaMG', 'SimplAxCp', 'SimplAxCpMG']])+'\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['SimplCd', 'SimplCdMG', 'SimplCa', 'SimplCaMG', 'SimplCp', 'SimplCpMG', 'SimplAxCd', 'SimplAxCdMG', 'SimplAxCa', 'SimplAxCaMG', 'SimplAxCp', 'SimplAxCpMG', 'SimplCb', 'SimplCbMG']])+'\n') f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)']*12])+'\n') ln = [] ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplCd'])) @@ -1595,10 +1560,12 @@ def write_HydroDyn(self): ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplAxCaMG'])) ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplAxCp'])) ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplAxCpMG'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplCb'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplCbMG'])) f.write(" ".join(ln) + '\n') f.write('---------------------- DEPTH-BASED HYDRODYNAMIC COEFFICIENTS (model 2) ---------\n') f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NCoefDpth'], 'NCoefDpth', '- Number of depth-dependent coefficients (-)\n')) - f.write(" ".join(['{:^11s}'.format(i) for i in ['Dpth', 'DpthCd', 'DpthCdMG', 'DpthCa', 'DpthCaMG', 'DpthCp', 'DpthCpMG', 'DpthAxCd', 'DpthAxCdMG', 'DpthAxCa', 'DpthAxCaMG', 'DpthAxCp', 'DpthAxCpMG']])+'\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['Dpth', 'DpthCd', 'DpthCdMG', 'DpthCa', 'DpthCaMG', 'DpthCp', 'DpthCpMG', 'DpthAxCd', 'DpthAxCdMG', 'DpthAxCa', 'DpthAxCaMG', 'DpthAxCp', 'DpthAxCpMG', 'DpthCb', 'DpthCbMG']])+'\n') f.write(" ".join(['{:^11s}'.format(i) for i in ['(m)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)']])+'\n') for i in range(self.fst_vt['HydroDyn']['NCoefDpth']): ln = [] @@ -1615,11 +1582,14 @@ def write_HydroDyn(self): ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthAxCaMG'][i])) ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthAxCp'][i])) ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthAxCpMG'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthCb'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthCbMG'][i])) f.write(" ".join(ln) + '\n') f.write('---------------------- MEMBER-BASED HYDRODYNAMIC COEFFICIENTS (model 3) --------\n') f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NCoefMembers'], 'NCoefMembers', '- Number of member-based coefficients (-)\n')) - f.write(" ".join(['{:^11s}'.format(i) for i in ['MemberID_HydC', 'MemberCd1', 'MemberCd2', 'MemberCdMG1', 'MemberCdMG2', 'MemberCa1', 'MemberCa2', 'MemberCaMG1', 'MemberCaMG2', 'MemberCp1', 'MemberCp2', 'MemberCpMG1', 'MemberCpMG2', 'MemberAxCd1', 'MemberAxCd2', 'MemberAxCdMG1', 'MemberAxCdMG2', 'MemberAxCa1', 'MemberAxCa2', 'MemberAxCaMG1', 'MemberAxCaMG2', 'MemberAxCp1', 'MemberAxCp2', 'MemberAxCpMG1', 'MemberAxCpMG2']])+'\n') - f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)']*25])+'\n') + mem_coeff_names = ['MemberID_HydC', 'MemberCd1', 'MemberCd2', 'MemberCdMG1', 'MemberCdMG2', 'MemberCa1', 'MemberCa2', 'MemberCaMG1', 'MemberCaMG2', 'MemberCp1', 'MemberCp2', 'MemberCpMG1', 'MemberCpMG2', 'MemberAxCd1', 'MemberAxCd2', 'MemberAxCdMG1', 'MemberAxCdMG2', 'MemberAxCa1', 'MemberAxCa2', 'MemberAxCaMG1', 'MemberAxCaMG2', 'MemberAxCp1', 'MemberAxCp2', 'MemberAxCpMG1', 'MemberAxCpMG2','MemberCb1','MemberCb2','MemberCbMG1','MemberCbMG2'] + f.write(" ".join(['{:^11s}'.format(i) for i in mem_coeff_names])+'\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)']*len(mem_coeff_names)])+'\n') for i in range(self.fst_vt['HydroDyn']['NCoefMembers']): ln = [] ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MemberID_HydC'][i])) @@ -1647,10 +1617,14 @@ def write_HydroDyn(self): ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCp2'][i])) ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCpMG1'][i])) ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCpMG2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCb1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCb2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCbMG1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCbMG2'][i])) f.write(" ".join(ln) + '\n') f.write('-------------------- MEMBERS -------------------------------------------------\n') f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NMembers'], 'NMembers', '- Number of members (-)\n')) - f.write(" ".join(['{:^11s}'.format(i) for i in ['MemberID', 'MJointID1', 'MJointID2', 'MPropSetID1', 'MPropSetID2', 'MDivSize', 'MCoefMod', 'PropPot']])+' ! [MCoefMod=1: use simple coeff table, 2: use depth-based coeff table, 3: use member-based coeff table] [ PropPot/=0 if member is modeled with potential-flow theory]\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['MemberID', 'MJointID1', 'MJointID2', 'MPropSetID1', 'MPropSetID2', 'MDivSize', 'MCoefMod', 'MHstLMod', 'PropPot']])+' ! [MCoefMod=1: use simple coeff table, 2: use depth-based coeff table, 3: use member-based coeff table] [ PropPot/=0 if member is modeled with potential-flow theory]\n') f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)', '(-)', '(-)', '(-)', '(-)', '(m)', '(switch)', '(flag)']])+'\n') for i in range(self.fst_vt['HydroDyn']['NMembers']): ln = [] @@ -1661,6 +1635,7 @@ def write_HydroDyn(self): ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MPropSetID2'][i])) ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MDivSize'][i])) ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MCoefMod'][i])) + ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MHstLMod'][i])) ln.append('{!s:^11}'.format(self.fst_vt['HydroDyn']['PropPot'][i])) f.write(" ".join(ln) + '\n') f.write("---------------------- FILLED MEMBERS ------------------------------------------\n") @@ -1713,6 +1688,116 @@ def write_HydroDyn(self): f.close() + def write_SeaState(self): + + # Generate HydroDyn v2.03 input file + self.fst_vt['Fst']['SeaState'] = self.FAST_namingOut + '_SeaState.dat' + hd_file = os.path.join(self.FAST_runDirectory, self.fst_vt['Fst']['SeaState']) + f = open(hd_file, 'w') + + f.write('------- SeaState v1.00.* Input File --------------------------------------------\n') + f.write('Generated with AeroElasticSE FAST driver\n') + f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['Echo'], 'Echo', '- Echo the input file data (flag)\n')) + + f.write('---------------------- ENVIRONMENTAL CONDITIONS --------------------------------\n') + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WtrDens'],'WtrDens', '- Water density (kg/m^3)\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WtrDpth'],'WtrDpth', '- Water depth (meters)\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['MSL2SWL'],'MSL2SWL', '- Offset between still-water level and mean sea level (meters) [positive upward; unused when WaveMod = 6; must be zero if PotMod=1 or 2]\n')) + + + f.write('---------------------- SPATIAL DISCRETIZATION ---------------------------------------------------\n') + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['X_HalfWidth'], 'X_HalfWidth', '– Half-width of the domain in the X direction (m) [>0, NOTE: X[nX] = nX*dX, where nX = {-NX+1,-NX+2,…,NX-1} and dX = X_HalfWidth/(NX-1)]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['Y_HalfWidth'], 'Y_HalfWidth', '– Half-width of the domain in the Y direction (m) [>0, NOTE: Y[nY] = nY*dY, where nY = {-NY+1,-NY+2,…,NY-1} and dY = Y_HalfWidth/(NY-1)]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['Z_Depth'], 'Z_Depth', '– Depth of the domain the Z direction (m) relative to SWL [0 < Z_Depth <= WtrDpth+MSL2SWL; "default": Z_Depth = WtrDpth+MSL2SWL; Z[nZ] = ( COS( nZ*dthetaZ ) – 1 )*Z_Depth, where nZ = {0,1,…NZ-1} and dthetaZ = pi/( 2*(NZ-1) )]\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SeaState']['NX'], 'NX', '– Number of nodes in half of the X-direction domain (-) [>=2]\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SeaState']['NY'], 'NY', '– Number of nodes in half of the Y-direction domain (-) [>=2]\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SeaState']['NZ'], 'NZ', '– Number of nodes in the Z direction (-) [>=2]\n')) + + f.write('---------------------- WAVES ---------------------------------------------------\n') + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SeaState']['WaveMod'], 'WaveMod', '- Incident wave kinematics model {0: none=still water, 1: regular (periodic), 1P#: regular with user-specified phase, 2: JONSWAP/Pierson-Moskowitz spectrum (irregular), 3: White noise spectrum (irregular), 4: user-defined spectrum from routine UserWaveSpctrm (irregular), 5: Externally generated wave-elevation time series, 6: Externally generated full wave-kinematics time series [option 6 is invalid for PotMod/=0]} (switch)\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SeaState']['WaveStMod'], 'WaveStMod', '- Model for stretching incident wave kinematics to instantaneous free surface {0: none=no stretching, 1: vertical stretching, 2: extrapolation stretching, 3: Wheeler stretching} (switch) [unused when WaveMod=0 or when PotMod/=0]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WaveTMax'], 'WaveTMax', '- Analysis time for incident wave calculations (sec) [unused when WaveMod=0; determines WaveDOmega=2Pi/WaveTMax in the IFFT]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WaveDT'], 'WaveDT', '- Time step for incident wave calculations (sec) [unused when WaveMod=0; 0.1<=WaveDT<=1.0 recommended; determines WaveOmegaMax=Pi/WaveDT in the IFFT]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WaveHs'], 'WaveHs', '- Significant wave height of incident waves (meters) [used only when WaveMod=1, 2, or 3]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WaveTp'], 'WaveTp', '- Peak-spectral period of incident waves (sec) [used only when WaveMod=1 or 2]\n')) + if isinstance(self.fst_vt['SeaState']['WavePkShp'], float): + if self.fst_vt['SeaState']['WavePkShp'] == 0.: + WavePkShp = 'Default' + else: + WavePkShp = self.fst_vt['SeaState']['WavePkShp'] + else: + WavePkShp = self.fst_vt['SeaState']['WavePkShp'] + f.write('{:<22} {:<11} {:}'.format(WavePkShp, 'WavePkShp', '- Peak-shape parameter of incident wave spectrum (-) or DEFAULT (string) [used only when WaveMod=2; use 1.0 for Pierson-Moskowitz]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WvLowCOff'], 'WvLowCOff', '- Low cut-off frequency or lower frequency limit of the wave spectrum beyond which the wave spectrum is zeroed (rad/s) [unused when WaveMod=0, 1, or 6]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WvHiCOff'], 'WvHiCOff', '- High cut-off frequency or upper frequency limit of the wave spectrum beyond which the wave spectrum is zeroed (rad/s) [unused when WaveMod=0, 1, or 6]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WaveDir'], 'WaveDir', '- Incident wave propagation heading direction (degrees) [unused when WaveMod=0 or 6]\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SeaState']['WaveDirMod'], 'WaveDirMod', '- Directional spreading function {0: none, 1: COS2S} (-) [only used when WaveMod=2,3, or 4]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WaveDirSpread'], 'WaveDirSpread', '- Wave direction spreading coefficient ( > 0 ) (-) [only used when WaveMod=2,3, or 4 and WaveDirMod=1]\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SeaState']['WaveNDir'], 'WaveNDir', '- Number of wave directions (-) [only used when WaveMod=2,3, or 4 and WaveDirMod=1; odd number only]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WaveDirRange'], 'WaveDirRange', '- Range of wave directions (full range: WaveDir +/- 1/2*WaveDirRange) (degrees) [only used when WaveMod=2,3,or 4 and WaveDirMod=1]\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SeaState']['WaveSeed1'], 'WaveSeed(1)', '- First random seed of incident waves [-2147483648 to 2147483647] (-) [unused when WaveMod=0, 5, or 6]\n')) + + try: + seed2 = int(self.fst_vt['SeaState']['WaveSeed2']) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SeaState']['WaveSeed2'], 'WaveSeed(2)', '- Second random seed of incident waves [-2147483648 to 2147483647] (-) [unused when WaveMod=0, 5, or 6]\n')) + except ValueError: + f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WaveSeed2'], 'WaveSeed(2)', '- Second random seed of incident waves [-2147483648 to 2147483647] (-) [unused when WaveMod=0, 5, or 6] for intrinsic pRNG, or an alternative pRNG: "RanLux"\n')) + + f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WaveNDAmp'], 'WaveNDAmp', '- Flag for normally distributed amplitudes (flag) [only used when WaveMod=2, 3, or 4]\n')) + f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['SeaState']['WvKinFile']+'"', 'WvKinFile', '- Root name of externally generated wave data file(s) (quoted string) [used only when WaveMod=5 or 6]\n')) + f.write('---------------------- 2ND-ORDER WAVES ----------------------------------------- [unused with WaveMod=0 or 6]\n') + f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WvDiffQTF'], 'WvDiffQTF', '- Full difference-frequency 2nd-order wave kinematics (flag)\n')) + f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WvSumQTF'], 'WvSumQTF', '- Full summation-frequency 2nd-order wave kinematics (flag)\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WvLowCOffD'], 'WvLowCOffD', '- Low frequency cutoff used in the difference-frequencies (rad/s) [Only used with a difference-frequency method]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WvHiCOffD'], 'WvHiCOffD', '- High frequency cutoff used in the difference-frequencies (rad/s) [Only used with a difference-frequency method]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WvLowCOffS'], 'WvLowCOffS', '- Low frequency cutoff used in the summation-frequencies (rad/s) [Only used with a summation-frequency method]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['WvHiCOffS'], 'WvHiCOffS', '- High frequency cutoff used in the summation-frequencies (rad/s) [Only used with a summation-frequency method]\n')) + f.write('---------------------- CONSTRAINED WAVE ---------------------------------------- [Only used when WaveMod=2]\n') + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['ConstWaveMod'], 'ConstWaveMod', '- Contrained wave model {0: no constrained wave, 1: Specified crest elevation of 0.5*CrestHmax, 2: Specified crest height of CrestHmax}\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['CrestHmax'], 'CrestHmax', '- Twice the crest elevation if ConstWaveMod=1 or the crest height if ConstWaveMod=2. (m) [need CrestHmax > WaveHs; unused when ConstWaveMod=0]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['CrestTime'], 'CrestTime', '- Time of the wave crest. (sec) [unused when ConstWaveMod=0]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['CrestXi'], 'CrestXi', '- X-position of the wave crest. (m) [unused when ConstWaveMod=0]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['CrestYi'], 'CrestYi', '- Y-position of the wave crest. (m) [unused when ConstWaveMod=0]\n')) + f.write('---------------------- CURRENT ------------------------------------------------- [unused with WaveMod=6]\n') + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SeaState']['CurrMod'], 'CurrMod', '- Current profile model {0: none=no current, 1: standard, 2: user-defined from routine UserCurrent} (switch)\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['CurrSSV0'], 'CurrSSV0', '- Sub-surface current velocity at still water level (m/s) [used only when CurrMod=1]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['CurrSSDir'], 'CurrSSDir', '- Sub-surface current heading direction (degrees) or DEFAULT (string) [used only when CurrMod=1]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['CurrNSRef'], 'CurrNSRef', '- Near-surface current reference depth (meters) [used only when CurrMod=1]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['CurrNSV0'], 'CurrNSV0', '- Near-surface current velocity at still water level (m/s) [used only when CurrMod=1]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['CurrNSDir'], 'CurrNSDir', '- Near-surface current heading direction (degrees) [used only when CurrMod=1]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['CurrDIV'], 'CurrDIV', '- Depth-independent current velocity (m/s) [used only when CurrMod=1]\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['CurrDIDir'], 'CurrDIDir', '- Depth-independent current heading direction (degrees) [used only when CurrMod=1]\n')) + f.write('---------------------- MacCamy-Fuchs Diffraction Model ------------------------- [unused with WaveMod=6]\n') + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['MCFD'],'MCFD', '- Diameter of members for which the MacCamy-Fuchs model is to be enable. [used only when MCFD > 0]\n')) + f.write('---------------------- OUTPUT --------------------------------------------------\n') + f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['SeaStSum'], 'SeaStSum', '- Output a summary file [flag]\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SeaState']['OutSwtch'], 'OutSwtch','- Output requested channels to: [1=SeaState.out, 2=GlueCode.out, 3=both files]\n')) + f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['OutFmt'], 'OutFmt','- Output format for numerical results (quoted string) [not checked for validity!]\n')) + f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['SeaState']['OutSFmt'], 'OutSFmt','- Output format for header strings (quoted string) [not checked for validity!]\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SeaState']['NWaveElev'], 'NWaveElev','- Number of points where the incident wave elevations can be computed (-) [maximum of 9 output locations]\n')) + f.write('{:<22} {:<11} {:}'.format(", ".join([f'{val:4.2f}' for val in self.fst_vt['SeaState']['WaveElevxi']]), 'WaveElevxi', '- List of xi-coordinates for points where the incident wave elevations can be output (meters) [NWaveElev points, separated by commas or white space; usused if NWaveElev = 0]\n')) + f.write('{:<22} {:<11} {:}'.format(", ".join([f'{val:4.2f}' for val in self.fst_vt['SeaState']['WaveElevyi']]), 'WaveElevyi', '- List of yi-coordinates for points where the incident wave elevations can be output (meters) [NWaveElev points, separated by commas or white space; usused if NWaveElev = 0]\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SeaState']['NWaveKin'], 'NWaveKin','- Number of points where the incident wave elevations can be computed (-) [maximum of 9 output locations]\n')) + + if self.fst_vt['SeaState']['NWaveKin'] > 0 : + f.write('{:<22} {:<11} {:}'.format(", ".join([f'{val:4.2f}' for val in self.fst_vt['SeaState']['WaveKinxi']]), 'WaveKinxi', '- List of xi-coordinates for points where the wave kinematics can be output (meters) [NWaveKin points, separated by commas or white space; usused if NWaveKin = 0]\n')) + f.write('{:<22} {:<11} {:}'.format(", ".join([f'{val:4.2f}' for val in self.fst_vt['SeaState']['WaveKinyi']]), 'WaveKinyi', '- List of yi-coordinates for points where the wave kinematics can be output (meters) [NWaveKin points, separated by commas or white space; usused if NWaveKin = 0]\n')) + f.write('{:<22} {:<11} {:}'.format(", ".join([f'{val:4.2f}' for val in self.fst_vt['SeaState']['WaveKinzi']]), 'WaveKinzi', '- List of zi-coordinates for points where the wave kinematics can be output (meters) [NWaveKin points, separated by commas or white space; usused if NWaveKin = 0]\n')) + else: + f.write('{:<11} {:}'.format('WaveKinxi', '- List of xi-coordinates for points where the wave kinematics can be output (meters) [NWaveKin points, separated by commas or white space; usused if NWaveKin = 0]\n')) + f.write('{:<11} {:}'.format('WaveKinyi', '- List of yi-coordinates for points where the wave kinematics can be output (meters) [NWaveKin points, separated by commas or white space; usused if NWaveKin = 0]\n')) + f.write('{:<11} {:}'.format('WaveKinzi', '- List of zi-coordinates for points where the wave kinematics can be output (meters) [NWaveKin points, separated by commas or white space; usused if NWaveKin = 0]\n')) + + f.write('---------------------- OUTPUT CHANNELS -----------------------------------------\n') + outlist = self.get_outlist(self.fst_vt['outlist'], ['SeaState']) + for channel_list in outlist: + for i in range(len(channel_list)): + f.write('"' + channel_list[i] + '"\n') + + f.write('END of output channels and end of file. (the word "END" must appear in the first 3 columns of this line)\n') + + f.close() + def write_SubDyn(self): # Generate SubDyn v1.1 input file self.fst_vt['Fst']['SubFile'] = self.FAST_namingOut + '_SubDyn.dat' @@ -1739,7 +1824,7 @@ def write_SubDyn(self): else: # list of floats f.write('{:<22} {:<11} {:}'.format(", ".join([f'{d:f}' for d in self.fst_vt['SubDyn']['JDampings']]), 'JDampings', '- Damping Ratios for each retained mode (% of critical) If Nmodes>0, list Nmodes structural damping ratios for each retained mode (% of critical), or a single damping ratio to be applied to all retained modes. (last entered value will be used for all remaining modes).\n')) f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['GuyanDampMod'], 'GuyanDampMod', '- Guyan damping {0=none, 1=Rayleigh Damping, 2=user specified 6x6 matrix}.\n')) - f.write('{:<10}, {:<10} {:<11} {:}'.format(self.fst_vt['SubDyn']['RayleighDamp'][0], self.fst_vt['SubDyn']['RayleighDamp'][1], 'RayleighDamp', '- Mass and stiffness proportional damping coefficients (Rayleigh Damping) [only if GuyanDampMod=1].\n')) + f.write('{:<10} {:<10} {:<11} {:}'.format(self.fst_vt['SubDyn']['RayleighDamp'][0], self.fst_vt['SubDyn']['RayleighDamp'][1], 'RayleighDamp', '- Mass and stiffness proportional damping coefficients (Rayleigh Damping) [only if GuyanDampMod=1].\n')) f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['GuyanDampSize'], 'GuyanDampSize', '- Guyan damping matrix (6x6) [only if GuyanDampMod=2].\n')) for j in range(self.fst_vt['SubDyn']['GuyanDampSize']): try: @@ -1859,6 +1944,22 @@ def write_SubDyn(self): ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['RigidPropSetID'][i])) ln.append('{:^11}'.format(self.fst_vt['SubDyn']['RigidMatDens'][i])) f.write(" ".join(ln) + '\n') + f.write('----------------------- SPRING ELEMENT PROPERTIES ------------------------------------\n') + spring_list = ['k11','k12','k13','k14','k15','k16', + 'k22','k23','k24','k25','k26', + 'k33','k34','k35','k36', + 'k44','k45','k46', + 'k55','k56', + 'k66'] + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NSpringPropSets'], 'NSpringPropSets', '- Number of spring properties\n')) + f.write("PropSetID k11 k12 k13 k14 k15 k16 k22 k23 k24 k25 k26 k33 k34 k35 k36 k44 k45 k46 k55 k56 k66 \n") + f.write(" (-) (N/m) (N/m) (N/m) (N/rad) (N/rad) (N/rad) (N/m) (N/m) (N/rad) (N/rad) (N/rad) (N/m) (N/rad) (N/rad) (N/rad) (Nm/rad) (Nm/rad) (Nm/rad) (Nm/rad) (Nm/rad) (Nm/rad) \n") + for i in range(self.fst_vt['SubDyn']['NSpringPropSets']): + ln = [] + ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['SpringPropSetID'][i])) + for sl in spring_list: + ln.append('{:^11}'.format(self.fst_vt['SubDyn'][sl][i])) + f.write(" ".join(ln) + '\n') f.write('---------------------- MEMBER COSINE MATRICES COSM(i,j) ------------------------\n') f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NCOSMs'], 'NCOSMs', '- Number of unique cosine matrices (i.e., of unique member alignments including principal axis rotations); ignored if NXPropSets=0 or 9999 in any element below\n')) f.write(" ".join(['{:^11s}'.format(i) for i in ['COSMID', 'COSM11', 'COSM12', 'COSM13', 'COSM21', 'COSM22', 'COSM23', 'COSM31', 'COSM32', 'COSM33']])+'\n') @@ -1896,6 +1997,8 @@ def write_SubDyn(self): f.write(" ".join(ln) + '\n') f.write('---------------------------- OUTPUT: SUMMARY & OUTFILE ------------------------------\n') f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['SubDyn']['SumPrint'], 'SumPrint', '- Output a Summary File (flag).It contains: matrices K,M and C-B reduced M_BB, M-BM, K_BB, K_MM(OMG^2), PHI_R, PHI_L. It can also contain COSMs if requested.\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['OutCBModes'], 'OutCBModes', '- Output Guyan and Craig-Bampton modes (0: No output, 1: JSON output), (flag)\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['OutFEMModes'], 'OutFEMModes', '- Output first 30 FEM modes (0: No output, 1: JSON output) (flag)\n')) f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['SubDyn']['OutCOSM'], 'OutCOSM', '- Output cosine matrices with the selected output member forces (flag)\n')) f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['SubDyn']['OutAll'], 'OutAll', "- [T/F] Output all members' end forces\n")) f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['OutSwtch'], 'OutSwtch', '- [1/2/3] Output requested channels to: 1=.SD.out; 2=.out (generated by FAST); 3=both files.\n')) @@ -1911,7 +2014,7 @@ def write_SubDyn(self): ln = [] ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['MemberID_out'][i])) ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['NOutCnt'][i])) - ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['NodeCnt'][i])) + ln.append(" ".join(['{:^11d}'.format(node) for node in self.fst_vt['SubDyn']['NodeCnt'][i]])) f.write(" ".join(ln) + '\n') f.write('------------------------- SDOutList: The next line(s) contains a list of output parameters that will be output in .SD.out or .out. ------\n') outlist = self.get_outlist(self.fst_vt['outlist'], ['SubDyn']) @@ -1932,11 +2035,11 @@ def write_MAP(self): f.write(" ".join(['{:<11s}'.format(i) for i in ['LineType', 'Diam', 'MassDenInAir', 'EA', 'CB', 'CIntDamp', 'Ca', 'Cdn', 'Cdt']])+'\n') f.write(" ".join(['{:<11s}'.format(i) for i in ['(-)', '(m)', '(kg/m)', '(N)', '(-)', '(Pa-s)', '(-)', '(-)', '(-)']])+'\n') ln =[] - for i in range(self.fst_vt['MAP']['NTypes']): + for i in range(1): ln = [] ln.append('{:^11}'.format(self.fst_vt['MAP']['LineType'][i])) ln.append('{:^11}'.format(self.fst_vt['MAP']['Diam'][i])) - ln.append('{:^11}'.format(self.fst_vt['MAP']['MassDen'][i])) + ln.append('{:^11}'.format(self.fst_vt['MAP']['MassDenInAir'][i])) ln.append('{:^11}'.format(self.fst_vt['MAP']['EA'][i])) ln.append('{:<11}'.format(self.fst_vt['MAP']['CB'][i])) ln.append('{:<11}'.format(self.fst_vt['MAP']['CIntDamp'][i])) @@ -1963,7 +2066,7 @@ def write_MAP(self): f.write('---------------------- LINE PROPERTIES ---------------------------------------\n') f.write(" ".join(['{:<11s}'.format(i) for i in ['Line', 'LineType', 'UnstrLen', 'NodeAnch', 'NodeFair', 'Flags']])+'\n') f.write(" ".join(['{:<11s}'.format(i) for i in ['(-)', '(-)', '(m)', '(-)', '(-)', '(-)']])+'\n') - for i in range(self.fst_vt['MAP']['NLines']): + for i in range(len(self.fst_vt['MAP']['Line'])): ln = [] ln.append('{:^11d}'.format(self.fst_vt['MAP']['Line'][i])) ln.append('{:^11}'.format(self.fst_vt['MAP']['LineType'][i])) @@ -2007,6 +2110,64 @@ def write_MoorDyn(self): ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['CdAx'][i])) ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['CaAx'][i])) f.write(" ".join(ln) + '\n') + if self.fst_vt['MoorDyn']['Rod_Name']: + f.write('----------------------- ROD TYPES ------------------------------------------\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['TypeName', 'Diam', 'Mass/m', 'Cd', 'Ca', 'CdEnd', 'CaEnd']])+'\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['(name)', '(m)', '(kg/m)', '(-)', '(-)', '(-)', '(-)']])+'\n') + for i in range(len(self.fst_vt['MoorDyn']['Rod_Name'])): + ln = [] + ln.append('{:^11}'.format(self.fst_vt['MoorDyn']['Rod_Name'][i])) + ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Rod_Diam'][i])) + ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Rod_MassDen'][i])) + ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Rod_Cd'][i])) + ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Rod_Ca'][i])) + ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Rod_CdEnd'][i])) + ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Rod_CaEnd'][i])) + f.write(" ".join(ln) + '\n') + + + if self.fst_vt['MoorDyn']['Body_ID']: + f.write('----------------------- BODIES ------------------------------------------\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['ID', 'Attachement', 'X0', 'Y0', 'Z0', 'r0', 'p0','y0','Mass','CG*','I*','Volume','CdA*','Ca*']])+'\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['(#)', '(word)', '(m)', '(m)', '(m)', '(deg)', '(deg)','(deg)','(kg)','(m)','(kg-m^2)','(m^3)','m^2','(kg/m^3)']])+'\n') + for i in range(len(self.fst_vt['MoorDyn']['Body_ID'])): + ln = [] + ln.append('{:^11d}'.format(self.fst_vt['MoorDyn']['Body_ID'][i])) + ln.append('{:^11}'.format(self.fst_vt['MoorDyn']['Body_Attachment'][i])) + ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['X0'][i])) + ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Y0'][i])) + ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Z0'][i])) + ln.append('{:^11.4e}'.format(self.fst_vt['MoorDyn']['r0'][i])) + ln.append('{:^11.4e}'.format(self.fst_vt['MoorDyn']['p0'][i])) + ln.append('{:^11.4e}'.format(self.fst_vt['MoorDyn']['y0'][i])) + ln.append('{:^11.4e}'.format(self.fst_vt['MoorDyn']['Body_Mass'][i])) + ln.append('|'.join(['{:^.4f}'.format(a) for a in self.fst_vt['MoorDyn']['Body_CG'][i]])) + ln.append('|'.join(['{:^.4e}'.format(a) for a in self.fst_vt['MoorDyn']['Body_I'][i]])) + ln.append('{:^11.4e}'.format(self.fst_vt['MoorDyn']['Body_Volume'][i])) + ln.append('|'.join(['{:^.4f}'.format(a) for a in self.fst_vt['MoorDyn']['Body_CdA'][i]])) + ln.append('|'.join(['{:^.4f}'.format(a) for a in self.fst_vt['MoorDyn']['Body_Ca'][i]])) + f.write(" ".join(ln) + '\n') + + if self.fst_vt['MoorDyn']['Rod_ID']: + f.write('----------------------- RODS ------------------------------------------\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['ID', 'RodType', 'Attachment', 'Xa', 'Ya', 'Za', 'Xb','Yb','Zb','NumSegs','RodOutputs']])+'\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['(#)', '(name)', '(word/ID)', '(m)', '(m)', '(m)', '(m)','(m)','(m)','(-)','(-)']])+'\n') + for i in range(len(self.fst_vt['MoorDyn']['Rod_ID'])): + ln = [] + ln.append('{:^11}'.format(self.fst_vt['MoorDyn']['Rod_ID'][i])) + ln.append('{:^11}'.format(self.fst_vt['MoorDyn']['Rod_Type'][i])) + ln.append('{:^11}'.format(self.fst_vt['MoorDyn']['Rod_Attachment'][i])) + ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Xa'][i])) + ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Ya'][i])) + ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Za'][i])) + ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Xb'][i])) + ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Yb'][i])) + ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Zb'][i])) + ln.append('{:^11d}'.format(self.fst_vt['MoorDyn']['Rod_NumSegs'][i])) + ln.append('{:^11}'.format(self.fst_vt['MoorDyn']['RodOutputs'][i])) + f.write(" ".join(ln) + '\n') + + f.write('---------------------- POINTS --------------------------------\n') f.write(" ".join(['{:^11s}'.format(i) for i in ['ID', 'Attachment', 'X', 'Y', 'Z', 'M', 'V', 'CdA', 'CA']])+'\n') f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)', '(-)', '(m)', '(m)', '(m)', '(kg)', '(m^3)', '(m^2)', '(-)']])+'\n') @@ -2054,6 +2215,7 @@ def write_MoorDyn(self): f.write('{:<22} {:<11} {:}'.format(self.fst_vt['MoorDyn']['TmaxIC'], 'TmaxIC', '- max time for ic gen (s)\n')) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['MoorDyn']['CdScaleIC'], 'CdScaleIC', '- factor by which to scale drag coefficients during dynamic relaxation (-)\n')) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['MoorDyn']['threshIC'], 'threshIC', '- threshold for IC convergence (-)\n')) + # f.write('{:^11s} {:<11} {:}'.format(self.fst_vt['MoorDyn']['WaterKin'], 'WaterKin', 'Handling of water motion (0=off, 1=on)\n')) f.write('------------------------ OUTPUTS --------------------------------------------\n') outlist = self.get_outlist(self.fst_vt['outlist'], ['MoorDyn']) for channel_list in outlist: