• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

WISDEM / WEIS / 12283078613

11 Dec 2024 06:59PM UTC coverage: 78.249% (-0.6%) from 78.802%
12283078613

Pull #308

github

dzalkind
Merge remote-tracking branch 'origin/DLC_RefactorCaseInputs' into DLC_RefactorCaseInputs
Pull Request #308: DLC Generation - Refactor and New Cases

446 of 665 new or added lines in 9 files covered. (67.07%)

3 existing lines in 3 files now uncovered.

21416 of 27369 relevant lines covered (78.25%)

0.78 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.59
/weis/aeroelasticse/FAST_writer.py
1
import os
1✔
2
import copy
1✔
3
import random
1✔
4
import time
1✔
5
import operator
1✔
6
import numpy as np
1✔
7
from functools import reduce
1✔
8

9
from weis.aeroelasticse.FAST_reader import InputReader_OpenFAST
1✔
10

11
try:
1✔
12
    from rosco.toolbox import utilities as ROSCO_utilities
1✔
13
    ROSCO = True
1✔
14
except ImportError:
×
15
    ROSCO = False
×
16

17

18
def auto_format(f, var):
1✔
19
    # Error handling for variables with 'Default' options
20
    if isinstance(var, str):
×
21
        f.write('{:}\n'.format(var))
×
22
    elif isinstance(var, int):
×
23
        f.write('{:3}\n'.format(var))
×
24
    elif isinstance(var, float):
×
25
        f.write('{: 2.15e}\n'.format(var))
×
26

27
def float_default_out(val):
1✔
28
    # formatted float output when 'default' is an option
29
    if type(val) is float:
1✔
30
        return '{: 22f}'.format(val)
×
31
    else:
32
        return '{:<22}'.format(val)
1✔
33

34
def int_default_out(val):
1✔
35
    # formatted int output when 'default' is an option
36
    if type(val) is float:
×
37
        return '{:<22d}'.format(val)
×
38
    else:
39
        return '{:<22}'.format(val)
×
40

41
# given a list of nested dictionary keys, return the dict at that point
42
def get_dict(vartree, branch):
1✔
43
    return reduce(operator.getitem, branch, vartree)
1✔
44

45
class InputWriter_OpenFAST(object):
1✔
46
    """ Methods to write OpenFAST input files."""
47

48
    def __init__(self):
1✔
49

50
        self.FAST_namingOut = None    #Master FAST file
1✔
51
        self.FAST_runDirectory = None #Output directory
1✔
52
        self.fst_vt = {}
1✔
53
        self.fst_update = {}
1✔
54

55
    def update(self, fst_update={}):
1✔
56
        """ Change fast variables based on the user supplied values """
57
        if fst_update:
1✔
58
            self.fst_update = fst_update
1✔
59

60
        # recursively loop through fast variable levels and set them to their update values
61
        def loop_dict(vartree, branch):
1✔
62
            for var in vartree.keys():
1✔
63
                branch_i = copy.copy(branch)
1✔
64
                branch_i.append(var)
1✔
65
                if type(vartree[var]) is dict:
1✔
66
                    loop_dict(vartree[var], branch_i)
1✔
67
                else:
68
                    # try:
69
                    get_dict(self.fst_vt, branch_i[:-1])[branch_i[-1]] = get_dict(self.fst_update, branch_i[:-1])[branch_i[-1]]
1✔
70
                    # except:
71
                        # pass
72

73
        # make sure update dictionary is not empty
74
        if self.fst_update:
1✔
75
            # if update dictionary uses list keys, convert to nested dictionaries
76
            if type(list(self.fst_update.keys())) in [list, tuple]:
1✔
77
                fst_update = copy.copy(self.fst_update)
1✔
78
                self.fst_update = {}
1✔
79
                for var_list in fst_update.keys():
1✔
80
                    branch = []
1✔
81
                    for i, var in enumerate(var_list[0:-1]):
1✔
82
                        if var not in get_dict(self.fst_update, branch).keys():
1✔
83
                            get_dict(self.fst_update, branch)[var] = {}
1✔
84
                        branch.append(var)
1✔
85

86
                    get_dict(self.fst_update, branch)[var_list[-1]] = fst_update[var_list]
1✔
87
            else:
88
                print('WARNING: OpenFAST user settings not correctly applied. Please check the modeling_options.yaml')
×
89

90
            # set fast variables to update values
91
            loop_dict(self.fst_update, [])
1✔
92

93
    def get_outlist(self, vartree_head, channel_list=[]):
1✔
94
        """ Loop through a list of output channel names, recursively find values set to True in the nested outlist dict """
95

96
        # recursively search nested dictionaries
97
        def loop_dict(vartree, outlist_i):
1✔
98
            for var in vartree.keys():
1✔
99
                if type(vartree[var]) is dict:
1✔
100
                    loop_dict(vartree[var], outlist_i)
×
101
                else:
102
                    if vartree[var]:
1✔
103
                        outlist_i.append(var)
1✔
104
            return outlist_i
1✔
105

106
        # if specific outlist branches are not specified, get all
107
        if not channel_list:
1✔
108
            channel_list = vartree_head.keys()
×
109

110
        # loop through top level of dictionary
111
        outlist = []
1✔
112
        for var in channel_list:
1✔
113
            var = var.replace(' ', '')
1✔
114
            outlist_i = []
1✔
115
            outlist_i = loop_dict(vartree_head[var], outlist_i)
1✔
116
            if outlist_i:
1✔
117
                outlist.append(sorted(outlist_i))
1✔
118

119
        return outlist
1✔
120

121
    def update_outlist(self, channels):
1✔
122
        """ Loop through a list of output channel names, recursively search the nested outlist dict and set to specified value"""
123
        # 'channels' is a dict of channel names as keys with the boolean value they should be set to
124

125
        # given a list of nested dictionary keys, return the dict at that point
126
        def get_dict(vartree, branch):
1✔
127
            return reduce(operator.getitem, branch, self.fst_vt['outlist'])
1✔
128
        # given a list of nested dictionary keys, set the value of the dict at that point
129
        def set_dict(vartree, branch, val):
1✔
130
            get_dict(vartree, branch[:-1])[branch[-1]] = val
1✔
131
        # recursively loop through outlist dictionaries to set output channels
132
        def loop_dict(vartree, search_var, val, branch):
1✔
133
            for var in vartree.keys():
1✔
134
                branch_i = copy.copy(branch)
1✔
135
                branch_i.append(var)
1✔
136
                if type(vartree[var]) is dict:
1✔
137
                    loop_dict(vartree[var], search_var, val, branch_i)
1✔
138
                else:
139
                    if var == search_var:
1✔
140
                        set_dict(self.fst_vt['outlist'], branch_i, val)
1✔
141

142
        # loop through outchannels on this line, loop through outlist dicts to set to True
143
        channel_list = channels.keys()
1✔
144
        for var in channel_list:
1✔
145
            val = channels[var]
1✔
146
            var = var.replace(' ', '')
1✔
147
            loop_dict(self.fst_vt['outlist'], var, val, [])
1✔
148

149
    def execute(self):
1✔
150
        
151
        if not os.path.exists(self.FAST_runDirectory):
1✔
152
            os.makedirs(self.FAST_runDirectory)
1✔
153

154
        self.write_ElastoDynBlade()
1✔
155
        self.write_ElastoDynTower()
1✔
156
        self.write_ElastoDyn()
1✔
157
        # self.write_WindWnd()
158
        self.write_InflowWind()
1✔
159
        if self.fst_vt['Fst']['CompAero'] == 1:
1✔
160
            self.write_AeroDyn14()
×
161
        elif self.fst_vt['Fst']['CompAero'] == 2:
1✔
162
            self.write_AeroDyn15()
1✔
163
        
164
        if self.fst_vt['Fst']['CompServo'] == 1:
1✔
165
                if 'DISCON_in' in self.fst_vt and ROSCO:
1✔
166
                    self.write_DISCON_in()
1✔
167
                self.write_ServoDyn()
1✔
168
                for i_NStC, NStC in enumerate(self.fst_vt['NStC']):
1✔
169
                    self.write_StC(NStC,self.fst_vt['ServoDyn']['NStCfiles'][i_NStC])
×
170
                for i_BStC, BStC in enumerate(self.fst_vt['BStC']):
1✔
171
                    self.write_StC(BStC,self.fst_vt['ServoDyn']['BStCfiles'][i_BStC])
×
172
                for i_TStC, TStC in enumerate(self.fst_vt['TStC']):
1✔
173
                    self.write_StC(TStC,self.fst_vt['ServoDyn']['TStCfiles'][i_TStC])
×
174
                for i_SStC, SStC in enumerate(self.fst_vt['SStC']):
1✔
175
                    self.write_StC(SStC,self.fst_vt['ServoDyn']['SStCfiles'][i_SStC])
1✔
176
        
177
        if self.fst_vt['Fst']['CompHydro'] == 1:
1✔
178
            self.write_HydroDyn()
1✔
179
        if self.fst_vt['Fst']['CompSub'] == 1:
1✔
180
            self.write_SubDyn()
1✔
181
        if self.fst_vt['Fst']['CompMooring'] == 1:
1✔
182
            self.write_MAP()
×
183
        elif self.fst_vt['Fst']['CompMooring'] == 3:
1✔
184
            self.write_MoorDyn()
1✔
185

186
        if self.fst_vt['Fst']['CompElast'] == 2:
1✔
187
            self.write_BeamDyn()
×
188

189
        self.write_MainInput()
1✔
190

191
    def write_MainInput(self):
1✔
192
        # Main FAST v8.16-v8.17 Input File
193
        # Currently no differences between FASTv8.16 and OpenFAST.
194

195
        self.FAST_InputFileOut = os.path.join(self.FAST_runDirectory, self.FAST_namingOut+'.fst')
1✔
196

197
        # Keep simple for now:
198
        f = open(self.FAST_InputFileOut, 'w')
1✔
199

200
        # ===== .fst Input File =====
201

202
        f.write('------- OpenFAST INPUT FILE -------------------------------------------\n')
1✔
203
        f.write('Generated with AeroElasticSE FAST driver\n')
1✔
204
        f.write('---------------------- SIMULATION CONTROL --------------------------------------\n')
1✔
205
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['Fst']['Echo'], 'Echo', '- Echo input data to <RootName>.ech (flag)\n'))
1✔
206
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['AbortLevel']+'"', 'AbortLevel', '- Error level when simulation should abort (string) {"WARNING", "SEVERE", "FATAL"}\n'))
1✔
207
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['TMax'], 'TMax', '- Total run time (s)\n'))
1✔
208
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['DT'], 'DT', '- Recommended module time step (s)\n'))
1✔
209
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['InterpOrder'], 'InterpOrder', '- Interpolation order for input/output time history (-) {1=linear, 2=quadratic}\n'))
1✔
210
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['NumCrctn'], 'NumCrctn', '- Number of correction iterations (-) {0=explicit calculation, i.e., no corrections}\n'))
1✔
211
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['DT_UJac'], 'DT_UJac', '- Time between calls to get Jacobians (s)\n'))
1✔
212
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['UJacSclFact'], 'UJacSclFact', '- Scaling factor used in Jacobians (-)\n'))
1✔
213
        f.write('---------------------- FEATURE SWITCHES AND FLAGS ------------------------------\n')
1✔
214
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['CompElast'], 'CompElast', '- Compute structural dynamics (switch) {1=ElastoDyn; 2=ElastoDyn + BeamDyn for blades}\n'))
1✔
215
        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'))
1✔
216
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['CompAero'], 'CompAero', '- Compute aerodynamic loads (switch) {0=None; 1=AeroDyn v14; 2=AeroDyn v15}\n'))
1✔
217
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['CompServo'], 'CompServo', '- Compute control and electrical-drive dynamics (switch) {0=None; 1=ServoDyn}\n'))
1✔
218
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['CompHydro'], 'CompHydro', '- Compute hydrodynamic loads (switch) {0=None; 1=HydroDyn}\n'))
1✔
219
        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'))
1✔
220
        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'))
1✔
221
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['CompIce'], 'CompIce', '- Compute ice loads (switch) {0=None; 1=IceFloe; 2=IceDyn}\n'))
1✔
222
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['MHK'], 'MHK', '- MHK turbine type (switch) {0=Not an MHK turbine; 1=Fixed MHK turbine; 2=Floating MHK turbine}\n'))
1✔
223
        f.write('---------------------- ENVIRONMENTAL CONDITIONS --------------------------------\n')
1✔
224
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['Gravity'], 'Gravity', '- Gravitational acceleration (m/s^2)\n'))
1✔
225
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['AirDens'], 'AirDens', '- Air density (kg/m^3)\n'))
1✔
226
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['WtrDens'], 'WtrDens', '- Water density (kg/m^3)\n'))
1✔
227
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['KinVisc'], 'KinVisc', '- Kinematic viscosity of working fluid (m^2/s)\n'))
1✔
228
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['SpdSound'], 'SpdSound', '- Speed of sound in working fluid (m/s)\n'))
1✔
229
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['Patm'], 'Patm', '- Atmospheric pressure (Pa) [used only for an MHK turbine cavitation check]\n'))
1✔
230
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['Pvap'], 'Pvap', '- Vapour pressure of working fluid (Pa) [used only for an MHK turbine cavitation check]\n'))
1✔
231
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['WtrDpth'], 'WtrDpth', '- Water depth (m)\n'))
1✔
232
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['MSL2SWL'], 'MSL2SWL', '- Offset between still-water level and mean sea level (m) [positive upward]\n'))        
1✔
233
        f.write('---------------------- INPUT FILES ---------------------------------------------\n')
1✔
234
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['EDFile']+'"', 'EDFile', '- Name of file containing ElastoDyn input parameters (quoted string)\n'))
1✔
235
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['BDBldFile(1)']+'"', 'BDBldFile(1)', '- Name of file containing BeamDyn input parameters for blade 1 (quoted string)\n'))
1✔
236
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['BDBldFile(2)']+'"', 'BDBldFile(2)', '- Name of file containing BeamDyn input parameters for blade 2 (quoted string)\n'))
1✔
237
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['BDBldFile(3)']+'"', 'BDBldFile(3)', '- Name of file containing BeamDyn input parameters for blade 3 (quoted string)\n'))
1✔
238
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['InflowFile']+'"', 'InflowFile', '- Name of file containing inflow wind input parameters (quoted string)\n'))
1✔
239
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['AeroFile']+'"', 'AeroFile', '- Name of file containing aerodynamic input parameters (quoted string)\n'))
1✔
240
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['ServoFile']+'"', 'ServoFile', '- Name of file containing control and electrical-drive input parameters (quoted string)\n'))
1✔
241
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['HydroFile']+'"', 'HydroFile', '- Name of file containing hydrodynamic input parameters (quoted string)\n'))
1✔
242
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['SubFile']+'"', 'SubFile', '- Name of file containing sub-structural input parameters (quoted string)\n'))
1✔
243
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['MooringFile']+'"', 'MooringFile', '- Name of file containing mooring system input parameters (quoted string)\n'))
1✔
244
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['IceFile']+'"', 'IceFile', '- Name of file containing ice input parameters (quoted string)\n'))
1✔
245
        f.write('---------------------- OUTPUT --------------------------------------------------\n')
1✔
246
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['Fst']['SumPrint'], 'SumPrint', '- Print summary data to "<RootName>.sum" (flag)\n'))
1✔
247
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['SttsTime'], 'SttsTime', '- Amount of time between screen status messages (s)\n'))
1✔
248
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['ChkptTime'], 'ChkptTime', '- Amount of time between creating checkpoint files for potential restart (s)\n'))
1✔
249
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['DT_Out'], 'DT_Out', '- Time step for tabular output (s) (or "default")\n'))
1✔
250
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['TStart'], 'TStart', '- Time to begin tabular output (s)\n'))
1✔
251
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['OutFileFmt'], 'OutFileFmt', '- Format for tabular (time-marching) output file (switch) {1: text file [<RootName>.out], 2: binary file [<RootName>.outb], 3: both}\n'))
1✔
252
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['Fst']['TabDelim'], 'TabDelim', '- Use tab delimiters in text tabular output file? (flag) {uses spaces if false}\n'))
1✔
253
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['Fst']['OutFmt']+'"', 'OutFmt', '- Format used for text tabular output, excluding the time channel.  Resulting field should be 10 characters. (quoted string)\n'))
1✔
254
        f.write('---------------------- LINEARIZATION -------------------------------------------\n')
1✔
255
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['Fst']['Linearize'],   'Linearize',    '- Linearization analysis (flag)\n'))
1✔
256
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['Fst']['CalcSteady'],  'CalcSteady',   '- Calculate a steady-state periodic operating point before linearization? [unused if Linearize=False] (flag)\n'))
1✔
257
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['TrimCase'],      'TrimCase',     '- Controller parameter to be trimmed {1:yaw; 2:torque; 3:pitch} [used only if CalcSteady=True] (-)\n'))
1✔
258
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['TrimTol'],       'TrimTol',      '- Tolerance for the rotational speed convergence [used only if CalcSteady=True] (-)\n'))
1✔
259
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['TrimGain'],      'TrimGain',     '- Proportional gain for the rotational speed error (>0) [used only if CalcSteady=True] (rad/(rad/s) for yaw or pitch; Nm/(rad/s) for torque)\n'))
1✔
260
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['Twr_Kdmp'],      'Twr_Kdmp',     '- Damping factor for the tower [used only if CalcSteady=True] (N/(m/s))\n'))
1✔
261
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['Bld_Kdmp'],      'Bld_Kdmp',     '- Damping factor for the blades [used only if CalcSteady=True] (N/(m/s))\n'))
1✔
262
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['NLinTimes'],     'NLinTimes',    '- Number of times to linearize (-) [>=1] [unused if Linearize=False]\n'))
1✔
263
        f.write('{:<22} {:<11} {:}'.format(', '.join(['%f'%i for i in np.array(self.fst_vt['Fst']['LinTimes'], dtype=float)]), 'LinTimes', '- List of times at which to linearize (s) [1 to NLinTimes] [used only when Linearize=True and CalcSteady=False]\n'))
1✔
264
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['LinInputs'],     'LinInputs',    '- Inputs included in linearization (switch) {0=none; 1=standard; 2=all module inputs (debug)} [unused if Linearize=False]\n'))
1✔
265
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['LinOutputs'],    'LinOutputs',   '- Outputs included in linearization (switch) {0=none; 1=from OutList(s); 2=all module outputs (debug)} [unused if Linearize=False]\n'))
1✔
266
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['Fst']['LinOutJac'],   'LinOutJac',    '- Include full Jacobians in linearization output (for debug) (flag) [unused if Linearize=False; used only if LinInputs=LinOutputs=2]\n'))
1✔
267
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['Fst']['LinOutMod'],   'LinOutMod',    '- Write module-level linearization output files in addition to output for full system? (flag) [unused if Linearize=False]\n'))
1✔
268
        f.write('---------------------- VISUALIZATION ------------------------------------------\n')
1✔
269
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['WrVTK'], 'WrVTK', '- VTK visualization data output: (switch) {0=none; 1=initialization data only; 2=animation}\n'))
1✔
270
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['VTK_type'], 'VTK_type', '- Type of VTK visualization data: (switch) {1=surfaces; 2=basic meshes (lines/points); 3=all meshes (debug)} [unused if WrVTK=0]\n'))
1✔
271
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['Fst']['VTK_fields'], 'VTK_fields', '- Write mesh fields to VTK data files? (flag) {true/false} [unused if WrVTK=0]\n'))
1✔
272
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['Fst']['VTK_fps'], 'VTK_fps', '- Frame rate for VTK output (frames per second){will use closest integer multiple of DT} [used only if WrVTK=2]\n'))
1✔
273

274
        f.flush()
1✔
275
        os.fsync(f)
1✔
276
        f.close()
1✔
277

278
    def write_ElastoDyn(self):
1✔
279

280
        self.fst_vt['Fst']['EDFile'] = self.FAST_namingOut + '_ElastoDyn.dat'
1✔
281
        ed_file = os.path.join(self.FAST_runDirectory,self.fst_vt['Fst']['EDFile'])
1✔
282
        f = open(ed_file, 'w')
1✔
283

284
        f.write('------- ELASTODYN v1.03.* INPUT FILE -------------------------------------------\n')
1✔
285
        f.write('Generated with AeroElasticSE FAST driver\n')
1✔
286

287
        # ElastoDyn Simulation Control (ed_sim_ctrl)
288
        f.write('---------------------- SIMULATION CONTROL --------------------------------------\n')
1✔
289
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['Echo'], 'Echo', '- Echo input data to "<RootName>.ech" (flag)\n'))
1✔
290
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['Method'], 'Method', '- Integration method: {1: RK4, 2: AB4, or 3: ABM4} (-)\n'))
1✔
291
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['DT'], 'DT', 'Integration time step (s)\n'))
1✔
292
        f.write('---------------------- DEGREES OF FREEDOM --------------------------------------\n')
1✔
293
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['FlapDOF1'], 'FlapDOF1', '- First flapwise blade mode DOF (flag)\n'))
1✔
294
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['FlapDOF2'], 'FlapDOF2', '- Second flapwise blade mode DOF (flag)\n'))
1✔
295
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['EdgeDOF'], 'EdgeDOF', '- First edgewise blade mode DOF (flag)\n'))
1✔
296
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TeetDOF'], 'TeetDOF', '- Rotor-teeter DOF (flag) [unused for 3 blades]\n'))
1✔
297
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['DrTrDOF'], 'DrTrDOF', '- Drivetrain rotational-flexibility DOF (flag)\n'))
1✔
298
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['GenDOF'], 'GenDOF', '- Generator DOF (flag)\n'))
1✔
299
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['YawDOF'], 'YawDOF', '- Yaw DOF (flag)\n'))
1✔
300
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TwFADOF1'], 'TwFADOF1', '- First fore-aft tower bending-mode DOF (flag)\n'))
1✔
301
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TwFADOF2'], 'TwFADOF2', '- Second fore-aft tower bending-mode DOF (flag)\n'))
1✔
302
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TwSSDOF1'], 'TwSSDOF1', '- First side-to-side tower bending-mode DOF (flag)\n'))
1✔
303
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TwSSDOF2'], 'TwSSDOF2', '- Second side-to-side tower bending-mode DOF (flag)\n'))
1✔
304
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmSgDOF'], 'PtfmSgDOF', '- Platform horizontal surge translation DOF (flag)\n'))
1✔
305
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmSwDOF'], 'PtfmSwDOF', '- Platform horizontal sway translation DOF (flag)\n'))
1✔
306
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmHvDOF'], 'PtfmHvDOF', '- Platform vertical heave translation DOF (flag)\n'))
1✔
307
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmRDOF'], 'PtfmRDOF', '- Platform roll tilt rotation DOF (flag)\n'))
1✔
308
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmPDOF'], 'PtfmPDOF', '- Platform pitch tilt rotation DOF (flag)\n'))
1✔
309
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmYDOF'], 'PtfmYDOF', '- Platform yaw rotation DOF (flag)\n'))
1✔
310
        f.write('---------------------- INITIAL CONDITIONS --------------------------------------\n')
1✔
311
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['OoPDefl'], 'OoPDefl', '- Initial out-of-plane blade-tip displacement (meters)\n'))
1✔
312
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['IPDefl'], 'IPDefl', '- Initial in-plane blade-tip deflection (meters)\n'))
1✔
313
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['BlPitch1'], 'BlPitch(1)', '- Blade 1 initial pitch (degrees)\n'))
1✔
314
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['BlPitch2'], 'BlPitch(2)', '- Blade 2 initial pitch (degrees)\n'))
1✔
315
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['BlPitch3'], 'BlPitch(3)', '- Blade 3 initial pitch (degrees) [unused for 2 blades]\n'))
1✔
316
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TeetDefl'], 'TeetDefl', '- Initial or fixed teeter angle (degrees) [unused for 3 blades]\n'))
1✔
317
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['Azimuth'], 'Azimuth', '- Initial azimuth angle for blade 1 (degrees)\n'))
1✔
318
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['RotSpeed'], 'RotSpeed', '- Initial or fixed rotor speed (rpm)\n'))
1✔
319
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['NacYaw'], 'NacYaw', '- Initial or fixed nacelle-yaw angle (degrees)\n'))
1✔
320
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TTDspFA'], 'TTDspFA', '- Initial fore-aft tower-top displacement (meters)\n'))
1✔
321
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TTDspSS'], 'TTDspSS', '- Initial side-to-side tower-top displacement (meters)\n'))
1✔
322
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmSurge'], 'PtfmSurge', '- Initial or fixed horizontal surge translational displacement of platform (meters)\n'))
1✔
323
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmSway'], 'PtfmSway', '- Initial or fixed horizontal sway translational displacement of platform (meters)\n'))
1✔
324
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmHeave'], 'PtfmHeave', '- Initial or fixed vertical heave translational displacement of platform (meters)\n'))
1✔
325
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmRoll'], 'PtfmRoll', '- Initial or fixed roll tilt rotational displacement of platform (degrees)\n'))
1✔
326
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmPitch'], 'PtfmPitch', '- Initial or fixed pitch tilt rotational displacement of platform (degrees)\n'))
1✔
327
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmYaw'], 'PtfmYaw', '- Initial or fixed yaw rotational displacement of platform (degrees)\n'))
1✔
328
        f.write('---------------------- TURBINE CONFIGURATION -----------------------------------\n')
1✔
329
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['NumBl'], 'NumBl', '- Number of blades (-)\n'))
1✔
330
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TipRad'], 'TipRad', '- The distance from the rotor apex to the blade tip (meters)\n'))
1✔
331
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['HubRad'], 'HubRad', '- The distance from the rotor apex to the blade root (meters)\n'))
1✔
332
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PreCone(1)'], 'PreCone(1)', '- Blade 1 cone angle (degrees)\n'))
1✔
333
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PreCone(2)'], 'PreCone(2)', '- Blade 2 cone angle (degrees)\n'))
1✔
334
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PreCone(3)'], 'PreCone(3)', '- Blade 3 cone angle (degrees) [unused for 2 blades]\n'))
1✔
335
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['HubCM'], 'HubCM', '- Distance from rotor apex to hub mass [positive downwind] (meters)\n'))
1✔
336
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['UndSling'], 'UndSling', '- Undersling length [distance from teeter pin to the rotor apex] (meters) [unused for 3 blades]\n'))
1✔
337
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['Delta3'], 'Delta3', '- Delta-3 angle for teetering rotors (degrees) [unused for 3 blades]\n'))
1✔
338
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['AzimB1Up'], 'AzimB1Up', '- Azimuth value to use for I/O when blade 1 points up (degrees)\n'))
1✔
339
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['OverHang'], 'OverHang', '- Distance from yaw axis to rotor apex [3 blades] or teeter pin [2 blades] (meters)\n'))
1✔
340
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['ShftGagL'], 'ShftGagL', '- Distance from rotor apex [3 blades] or teeter pin [2 blades] to shaft strain gages [positive for upwind rotors] (meters)\n'))
1✔
341
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['ShftTilt'], 'ShftTilt', '- Rotor shaft tilt angle (degrees)\n'))
1✔
342
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['NacCMxn'], 'NacCMxn', '- Downwind distance from the tower-top to the nacelle CM (meters)\n'))
1✔
343
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['NacCMyn'], 'NacCMyn', '- Lateral  distance from the tower-top to the nacelle CM (meters)\n'))
1✔
344
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['NacCMzn'], 'NacCMzn', '- Vertical distance from the tower-top to the nacelle CM (meters)\n'))
1✔
345
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['NcIMUxn'], 'NcIMUxn', '- Downwind distance from the tower-top to the nacelle IMU (meters)\n'))
1✔
346
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['NcIMUyn'], 'NcIMUyn', '- Lateral  distance from the tower-top to the nacelle IMU (meters)\n'))
1✔
347
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['NcIMUzn'], 'NcIMUzn', '- Vertical distance from the tower-top to the nacelle IMU (meters)\n'))
1✔
348
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['Twr2Shft'], 'Twr2Shft', '- Vertical distance from the tower-top to the rotor shaft (meters)\n'))
1✔
349
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TowerHt'], 'TowerHt', '- Height of tower above ground level [onshore] or MSL [offshore] (meters)\n'))
1✔
350
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TowerBsHt'], 'TowerBsHt', '- Height of tower base above ground level [onshore] or MSL [offshore] (meters)\n'))
1✔
351
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmCMxt'], 'PtfmCMxt', '- Downwind distance from the ground level [onshore] or MSL [offshore] to the platform CM (meters)\n'))
1✔
352
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmCMyt'], 'PtfmCMyt', '- Lateral distance from the ground level [onshore] or MSL [offshore] to the platform CM (meters)\n'))
1✔
353
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmCMzt'], 'PtfmCMzt', '- Vertical distance from the ground level [onshore] or MSL [offshore] to the platform CM (meters)\n'))
1✔
354
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmRefzt'], 'PtfmRefzt', '- Vertical distance from the ground level [onshore] or MSL [offshore] to the platform reference point (meters)\n'))
1✔
355
        f.write('---------------------- MASS AND INERTIA ----------------------------------------\n')
1✔
356
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TipMass(1)'], 'TipMass(1)', '- Tip-brake mass, blade 1 (kg)\n'))
1✔
357
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TipMass(2)'], 'TipMass(2)', '- Tip-brake mass, blade 2 (kg)\n'))
1✔
358
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TipMass(3)'], 'TipMass(3)', '- Tip-brake mass, blade 3 (kg) [unused for 2 blades]\n'))
1✔
359
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['HubMass'], 'HubMass', '- Hub mass (kg)\n'))
1✔
360
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['HubIner'], 'HubIner', '- Hub inertia about rotor axis [3 blades] or teeter axis [2 blades] (kg m^2)\n'))
1✔
361
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['GenIner'], 'GenIner', '- Generator inertia about HSS (kg m^2)\n'))
1✔
362
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['NacMass'], 'NacMass', '- Nacelle mass (kg)\n'))
1✔
363
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['NacYIner'], 'NacYIner', '- Nacelle inertia about yaw axis (kg m^2)\n'))
1✔
364
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['YawBrMass'], 'YawBrMass', '- Yaw bearing mass (kg)\n'))
1✔
365
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmMass'], 'PtfmMass', '- Platform mass (kg)\n'))
1✔
366
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmRIner'], 'PtfmRIner', '- Platform inertia for roll tilt rotation about the platform CM (kg m^2)\n'))
1✔
367
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmPIner'], 'PtfmPIner', '- Platform inertia for pitch tilt rotation about the platform CM (kg m^2)\n'))
1✔
368
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['PtfmYIner'], 'PtfmYIner', '- Platform inertia for yaw rotation about the platform CM (kg m^2)\n'))
1✔
369
        f.write('---------------------- BLADE ---------------------------------------------------\n')
1✔
370
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['BldNodes'], 'BldNodes', '- Number of blade nodes (per blade) used for analysis (-)\n'))
1✔
371
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['ElastoDyn']['BldFile1']+'"', 'BldFile1', '- Name of file containing properties for blade 1 (quoted string)\n'))
1✔
372
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['ElastoDyn']['BldFile2']+'"', 'BldFile2', '- Name of file containing properties for blade 2 (quoted string)\n'))
1✔
373
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['ElastoDyn']['BldFile3']+'"', 'BldFile3', '- Name of file containing properties for blade 3 (quoted string) [unused for 2 blades]\n'))
1✔
374
        f.write('---------------------- ROTOR-TEETER --------------------------------------------\n')
1✔
375
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TeetMod'], 'TeetMod', '- Rotor-teeter spring/damper model {0: none, 1: standard, 2: user-defined from routine UserTeet} (switch) [unused for 3 blades]\n'))
1✔
376
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TeetDmpP'], 'TeetDmpP', '- Rotor-teeter damper position (degrees) [used only for 2 blades and when TeetMod=1]\n'))
1✔
377
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TeetDmp'], 'TeetDmp', '- Rotor-teeter damping constant (N-m/(rad/s)) [used only for 2 blades and when TeetMod=1]\n'))
1✔
378
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TeetCDmp'], 'TeetCDmp', '- Rotor-teeter rate-independent Coulomb-damping moment (N-m) [used only for 2 blades and when TeetMod=1]\n'))
1✔
379
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TeetSStP'], 'TeetSStP', '- Rotor-teeter soft-stop position (degrees) [used only for 2 blades and when TeetMod=1]\n'))
1✔
380
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TeetHStP'], 'TeetHStP', '- Rotor-teeter hard-stop position (degrees) [used only for 2 blades and when TeetMod=1]\n'))
1✔
381
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TeetSSSp'], 'TeetSSSp', '- Rotor-teeter soft-stop linear-spring constant (N-m/rad) [used only for 2 blades and when TeetMod=1]\n'))
1✔
382
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TeetHSSp'], 'TeetHSSp', '- Rotor-teeter hard-stop linear-spring constant (N-m/rad) [used only for 2 blades and when TeetMod=1]\n'))
1✔
383
        f.write('---------------------- DRIVETRAIN ----------------------------------------------\n')
1✔
384
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['GBoxEff'], 'GBoxEff', '- Gearbox efficiency (%)\n'))
1✔
385
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['GBRatio'], 'GBRatio', '- Gearbox ratio (-)\n'))
1✔
386
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['DTTorSpr'], 'DTTorSpr', '- Drivetrain torsional spring (N-m/rad)\n'))
1✔
387
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['DTTorDmp'], 'DTTorDmp', '- Drivetrain torsional damper (N-m/(rad/s))\n'))
1✔
388
        f.write('---------------------- FURLING -------------------------------------------------\n')
1✔
389
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['Furling'], 'Furling', '- Read in additional model properties for furling turbine (flag) [must currently be FALSE)\n'))
1✔
390
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['ElastoDyn']['FurlFile']+'"', 'FurlFile', '- Name of file containing furling properties (quoted string) [unused when Furling=False]\n'))
1✔
391
        f.write('---------------------- TOWER ---------------------------------------------------\n')
1✔
392
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TwrNodes'], 'TwrNodes', '- Number of tower nodes used for analysis (-)\n'))
1✔
393
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['ElastoDyn']['TwrFile']+'"', 'TwrFile', '- Name of file containing tower properties (quoted string)\n'))
1✔
394
        f.write('---------------------- OUTPUT --------------------------------------------------\n')
1✔
395
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['SumPrint'], 'SumPrint', '- Print summary data to "<RootName>.sum" (flag)\n'))
1✔
396
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['OutFile'], 'OutFile', '- Switch to determine where output will be placed: {1: in module output file only; 2: in glue code output file only; 3: both} (currently unused)\n'))
1✔
397
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TabDelim'], 'TabDelim', '- Use tab delimiters in text tabular output file? (flag) (currently unused)\n'))
1✔
398
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['ElastoDyn']['OutFmt']+'"', 'OutFmt', '- Format used for text tabular output (except time).  Resulting field should be 10 characters. (quoted string) (currently unused)\n'))
1✔
399
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['TStart'], 'TStart', '- Time to begin tabular output (s) (currently unused)\n'))
1✔
400
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['DecFact'], 'DecFact', '- Decimation factor for tabular output {1: output every time step} (-) (currently unused)\n'))
1✔
401
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['NTwGages'], 'NTwGages', '- Number of tower nodes that have strain gages for output [0 to 9] (-)\n'))  
1✔
402
        if self.fst_vt['ElastoDyn']['TwrGagNd'] != 0:
1✔
403
            f.write('{:<22} {:<11} {:}'.format(', '.join(['%d'%i for i in self.fst_vt['ElastoDyn']['TwrGagNd']]), 'TwrGagNd', '- List of tower nodes that have strain gages [1 to TwrNodes] (-) [unused if NTwGages=0]\n'))
1✔
404
        else:
405
            f.write('{:<22} {:<11} {:}'.format('', 'TwrGagNd', '- List of tower nodes that have strain gages [1 to TwrNodes] (-) [unused if NTwGages=0]\n'))
×
406
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['NBlGages'], 'NBlGages', '- Number of blade nodes that have strain gages for output [0 to 9] (-)\n'))
1✔
407
        if self.fst_vt['ElastoDyn']['BldGagNd'] != 0:
1✔
408
            f.write('{:<22} {:<11} {:}'.format(', '.join(['%d'%i for i in self.fst_vt['ElastoDyn']['BldGagNd']]), 'BldGagNd', '- List of blade nodes that have strain gages [1 to BldNodes] (-) [unused if NBlGages=0]\n'))
1✔
409
        else:
410
            f.write('{:<22} {:<11} {:}'.format('', 'BldGagNd', '- List of blade nodes that have strain gages [1 to BldNodes] (-) [unused if NBlGages=0]\n'))
×
411
        f.write('                   OutList             - The next line(s) contains a list of output parameters.  See OutListParameters.xlsx for a listing of available output channels, (-)\n')
1✔
412

413
        outlist = self.get_outlist(self.fst_vt['outlist'], ['ElastoDyn'])
1✔
414
        
415
        for channel_list in outlist:
1✔
416
            for i in range(len(channel_list)):
1✔
417
                f.write('"' + channel_list[i] + '"\n')
1✔
418
        
419
        f.write('END of input file (the word "END" must appear in the first 3 columns of this last OutList line)\n')
1✔
420
                
421
        # Optional nodal output section
422
        if 'BldNd_BladesOut' in self.fst_vt['ElastoDyn']:
1✔
423
            f.write('====== Outputs for all blade stations (same ending as above for B1N1.... =========================== [optional section]\n')
×
424
            f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['BldNd_BladesOut'], 'BldNd_BladesOut', '- Number of blades to output all node information at.  Up to number of blades on turbine. (-)\n'))
×
425
            f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ElastoDyn']['BldNd_BlOutNd'], 'BldNd_BlOutNd', '- Future feature will allow selecting a portion of the nodes to output.  Not implemented yet. (-)\n'))
×
426
            f.write('                   OutList     - The next line(s) contains a list of output parameters.  See OutListParameters.xlsx, ElastoDyn_Nodes tab for a listing of available output channels, (-)\n')
×
427
            
428
            opt_outlist = self.get_outlist(self.fst_vt['outlist'], ['ElastoDyn_Nodes'])      
×
429
            for opt_channel_list in opt_outlist:
×
430
                for i in range(len(opt_channel_list)):
×
431
                    f.write('"' + opt_channel_list[i] + '"\n')
×
432
            f.write('END of input file (the word "END" must appear in the first 3 columns of this last OutList line)\n')
×
433
        
434
        f.write('---------------------------------------------------------------------------------------\n')
1✔
435
        f.flush()
1✔
436
        os.fsync(f)
1✔
437
        f.close()
1✔
438

439
    def write_ElastoDynBlade(self):
1✔
440

441
        self.fst_vt['ElastoDyn']['BldFile1'] = self.FAST_namingOut + '_ElastoDyn_blade.dat'
1✔
442
        self.fst_vt['ElastoDyn']['BldFile2'] = self.fst_vt['ElastoDyn']['BldFile1']
1✔
443
        self.fst_vt['ElastoDyn']['BldFile3'] = self.fst_vt['ElastoDyn']['BldFile1']
1✔
444
        blade_file = os.path.join(self.FAST_runDirectory,self.fst_vt['ElastoDyn']['BldFile1'])
1✔
445
        f = open(blade_file, 'w')
1✔
446

447
        f.write('------- ELASTODYN V1.00.* INDIVIDUAL BLADE INPUT FILE --------------------------\n')
1✔
448
        f.write('Generated with AeroElasticSE FAST driver\n')
1✔
449
        f.write('---------------------- BLADE PARAMETERS ----------------------------------------\n')
1✔
450
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['NBlInpSt'], 'NBlInpSt', '- Number of blade input stations (-)\n'))
1✔
451
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['BldFlDmp1'], 'BldFlDmp1', '- Blade flap mode #1 structural damping in percent of critical (%)\n'))
1✔
452
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['BldFlDmp2'], 'BldFlDmp2', '- Blade flap mode #2 structural damping in percent of critical (%)\n'))
1✔
453
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['BldEdDmp1'], 'BldEdDmp1', '- Blade edge mode #1 structural damping in percent of critical (%)\n'))
1✔
454
        f.write('---------------------- BLADE ADJUSTMENT FACTORS --------------------------------\n')
1✔
455
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['FlStTunr1'], 'FlStTunr1', '- Blade flapwise modal stiffness tuner, 1st mode (-)\n'))
1✔
456
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['FlStTunr2'], 'FlStTunr2', '- Blade flapwise modal stiffness tuner, 2nd mode (-)\n'))
1✔
457
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['AdjBlMs'], 'AdjBlMs', '- Factor to adjust blade mass density (-)\n'))
1✔
458
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['AdjFlSt'], 'AdjFlSt', '- Factor to adjust blade flap stiffness (-)\n'))
1✔
459
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['AdjEdSt'], 'AdjEdSt', '- Factor to adjust blade edge stiffness (-)\n'))
1✔
460
        f.write('---------------------- DISTRIBUTED BLADE PROPERTIES ----------------------------\n')
1✔
461
        f.write('    BlFract      PitchAxis      StrcTwst       BMassDen        FlpStff        EdgStff\n')
1✔
462
        f.write('      (-)           (-)          (deg)          (kg/m)         (Nm^2)         (Nm^2)\n')
1✔
463
        BlFract   = self.fst_vt['ElastoDynBlade']['BlFract']
1✔
464
        PitchAxis = self.fst_vt['ElastoDynBlade']['PitchAxis']
1✔
465
        StrcTwst  = self.fst_vt['ElastoDynBlade']['StrcTwst']
1✔
466
        BMassDen  = self.fst_vt['ElastoDynBlade']['BMassDen']
1✔
467
        FlpStff   = self.fst_vt['ElastoDynBlade']['FlpStff']
1✔
468
        EdgStff   = self.fst_vt['ElastoDynBlade']['EdgStff']
1✔
469
        for BlFracti, PitchAxisi, StrcTwsti, BMassDeni, FlpStffi, EdgStffi in zip(BlFract, PitchAxis, StrcTwst, BMassDen, FlpStff, EdgStff):
1✔
470
            f.write('{: 2.15e} {: 2.15e} {: 2.15e} {: 2.15e} {: 2.15e} {: 2.15e}\n'.format(BlFracti, PitchAxisi, StrcTwsti, BMassDeni, FlpStffi, EdgStffi))
1✔
471
        f.write('---------------------- BLADE MODE SHAPES ---------------------------------------\n')
1✔
472
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['BldFl1Sh'][0], 'BldFl1Sh(2)', '- Flap mode 1, coeff of x^2\n'))
1✔
473
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['BldFl1Sh'][1], 'BldFl1Sh(3)', '-            , coeff of x^3\n'))
1✔
474
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['BldFl1Sh'][2], 'BldFl1Sh(4)', '-            , coeff of x^4\n'))
1✔
475
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['BldFl1Sh'][3], 'BldFl1Sh(5)', '-            , coeff of x^5\n'))
1✔
476
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['BldFl1Sh'][4], 'BldFl1Sh(6)', '-            , coeff of x^6\n'))
1✔
477
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['BldFl2Sh'][0], 'BldFl2Sh(2)', '- Flap mode 2, coeff of x^2\n'))
1✔
478
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['BldFl2Sh'][1], 'BldFl2Sh(3)', '-            , coeff of x^3\n'))
1✔
479
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['BldFl2Sh'][2], 'BldFl2Sh(4)', '-            , coeff of x^4\n'))
1✔
480
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['BldFl2Sh'][3], 'BldFl2Sh(5)', '-            , coeff of x^5\n'))
1✔
481
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['BldFl2Sh'][4], 'BldFl2Sh(6)', '-            , coeff of x^6\n'))
1✔
482
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['BldEdgSh'][0], 'BldEdgSh(2)', '- Edge mode 1, coeff of x^2\n'))
1✔
483
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['BldEdgSh'][1], 'BldEdgSh(3)', '-            , coeff of x^3\n'))
1✔
484
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['BldEdgSh'][2], 'BldEdgSh(4)', '-            , coeff of x^4\n'))
1✔
485
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['BldEdgSh'][3], 'BldEdgSh(5)', '-            , coeff of x^5\n'))
1✔
486
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynBlade']['BldEdgSh'][4], 'BldEdgSh(6)', '-            , coeff of x^6\n'))      
1✔
487
         
488
        f.flush()
1✔
489
        os.fsync(f)
1✔
490
        f.close()
1✔
491

492
    def write_ElastoDynTower(self):
1✔
493

494
        self.fst_vt['ElastoDyn']['TwrFile'] = self.FAST_namingOut + '_ElastoDyn_tower.dat'
1✔
495
        tower_file = os.path.join(self.FAST_runDirectory,self.fst_vt['ElastoDyn']['TwrFile'])
1✔
496
        f = open(tower_file, 'w')
1✔
497

498
        f.write('------- ELASTODYN V1.00.* TOWER INPUT FILE -------------------------------------\n')
1✔
499
        f.write('Generated with AeroElasticSE FAST driver\n')
1✔
500
        f.write('---------------------- TOWER PARAMETERS ----------------------------------------\n')
1✔
501
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['NTwInpSt'],  'NTwInpSt', '- Number of input stations to specify tower geometry\n'))
1✔
502
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwrFADmp1'], 'TwrFADmp(1)', '- Tower 1st fore-aft mode structural damping ratio (%)\n'))
1✔
503
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwrFADmp2'], 'TwrFADmp(2)', '- Tower 2nd fore-aft mode structural damping ratio (%)\n'))
1✔
504
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwrSSDmp1'], 'TwrSSDmp(1)', '- Tower 1st side-to-side mode structural damping ratio (%)\n'))
1✔
505
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwrSSDmp2'], 'TwrSSDmp(2)', '- Tower 2nd side-to-side mode structural damping ratio (%)\n'))
1✔
506
        f.write('---------------------- TOWER ADJUSTMUNT FACTORS --------------------------------\n')
1✔
507
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['FAStTunr1'], 'FAStTunr(1)', '- Tower fore-aft modal stiffness tuner, 1st mode (-)\n'))
1✔
508
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['FAStTunr2'], 'FAStTunr(2)', '- Tower fore-aft modal stiffness tuner, 2nd mode (-)\n'))
1✔
509
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['SSStTunr1'], 'SSStTunr(1)', '- Tower side-to-side stiffness tuner, 1st mode (-)\n'))
1✔
510
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['SSStTunr2'], 'SSStTunr(2)', '- Tower side-to-side stiffness tuner, 2nd mode (-)\n'))
1✔
511
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['AdjTwMa'], 'AdjTwMa', '- Factor to adjust tower mass density (-)\n'))
1✔
512
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['AdjFASt'], 'AdjFASt', '- Factor to adjust tower fore-aft stiffness (-)\n'))
1✔
513
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['AdjSSSt'], 'AdjSSSt', '- Factor to adjust tower side-to-side stiffness (-)\n'))
1✔
514
        f.write('---------------------- DISTRIBUTED TOWER PROPERTIES ----------------------------\n')
1✔
515
        f.write('  HtFract       TMassDen         TwFAStif       TwSSStif\n')
1✔
516
        f.write('   (-)           (kg/m)           (Nm^2)         (Nm^2)\n')
1✔
517
        HtFract   = self.fst_vt['ElastoDynTower']['HtFract']
1✔
518
        TMassDen  = self.fst_vt['ElastoDynTower']['TMassDen']
1✔
519
        TwFAStif  = self.fst_vt['ElastoDynTower']['TwFAStif']
1✔
520
        TwSSStif  = self.fst_vt['ElastoDynTower']['TwSSStif']
1✔
521
        for HtFracti, TMassDeni, TwFAStifi, TwSSStifi in zip(HtFract, TMassDen, TwFAStif, TwSSStif):
1✔
522
            f.write('{: 2.15e} {: 2.15e} {: 2.15e} {: 2.15e}\n'.format(HtFracti, TMassDeni, TwFAStifi, TwSSStifi))
1✔
523
        f.write('---------------------- TOWER FORE-AFT MODE SHAPES ------------------------------\n')
1✔
524
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwFAM1Sh'][0], 'TwFAM1Sh(2)', '- Mode 1, coefficient of x^2 term\n'))
1✔
525
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwFAM1Sh'][1], 'TwFAM1Sh(3)', '-       , coefficient of x^3 term\n'))
1✔
526
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwFAM1Sh'][2], 'TwFAM1Sh(4)', '-       , coefficient of x^4 term\n'))
1✔
527
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwFAM1Sh'][3], 'TwFAM1Sh(5)', '-       , coefficient of x^5 term\n'))
1✔
528
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwFAM1Sh'][4], 'TwFAM1Sh(6)', '-       , coefficient of x^6 term\n'))
1✔
529
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwFAM2Sh'][0], 'TwFAM2Sh(2)', '- Mode 2, coefficient of x^2 term\n'))
1✔
530
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwFAM2Sh'][1], 'TwFAM2Sh(3)', '-       , coefficient of x^3 term\n'))
1✔
531
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwFAM2Sh'][2], 'TwFAM2Sh(4)', '-       , coefficient of x^4 term\n'))
1✔
532
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwFAM2Sh'][3], 'TwFAM2Sh(5)', '-       , coefficient of x^5 term\n'))
1✔
533
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwFAM2Sh'][4], 'TwFAM2Sh(6)', '-       , coefficient of x^6 term\n'))
1✔
534
        f.write('---------------------- TOWER SIDE-TO-SIDE MODE SHAPES --------------------------\n')
1✔
535
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwSSM1Sh'][0], 'TwSSM1Sh(2)', '- Mode 1, coefficient of x^2 term\n'))
1✔
536
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwSSM1Sh'][1], 'TwSSM1Sh(3)', '-       , coefficient of x^3 term\n'))
1✔
537
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwSSM1Sh'][2], 'TwSSM1Sh(4)', '-       , coefficient of x^4 term\n'))
1✔
538
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwSSM1Sh'][3], 'TwSSM1Sh(5)', '-       , coefficient of x^5 term\n'))
1✔
539
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwSSM1Sh'][4], 'TwSSM1Sh(6)', '-       , coefficient of x^6 term\n'))
1✔
540
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwSSM2Sh'][0], 'TwSSM2Sh(2)', '- Mode 2, coefficient of x^2 term\n'))
1✔
541
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwSSM2Sh'][1], 'TwSSM2Sh(3)', '-       , coefficient of x^3 term\n'))
1✔
542
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwSSM2Sh'][2], 'TwSSM2Sh(4)', '-       , coefficient of x^4 term\n'))
1✔
543
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwSSM2Sh'][3], 'TwSSM2Sh(5)', '-       , coefficient of x^5 term\n'))
1✔
544
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ElastoDynTower']['TwSSM2Sh'][4], 'TwSSM2Sh(6)', '-       , coefficient of x^6 term\n'))
1✔
545
        
546
        f.flush()
1✔
547
        os.fsync(f)
1✔
548
        f.close()
1✔
549

550
    def write_BeamDyn(self):
1✔
551
        self.fst_vt['Fst']['BDBldFile(1)'] = self.FAST_namingOut + '_BeamDyn.dat'
×
552
        self.fst_vt['Fst']['BDBldFile(2)'] = self.fst_vt['Fst']['BDBldFile(1)']
×
553
        self.fst_vt['Fst']['BDBldFile(3)'] = self.fst_vt['Fst']['BDBldFile(1)']
×
554

555
        self.write_BeamDynBlade()
×
556

557
        beamdyn_file = os.path.join(self.FAST_runDirectory,self.fst_vt['Fst']['BDBldFile(1)'])
×
558
        f            = open(beamdyn_file, 'w')
×
559

560
        f.write('--------- BEAMDYN with OpenFAST INPUT FILE -------------------------------------------\n')
×
561
        f.write('Generated with AeroElasticSE FAST driver\n')
×
562
        f.write('---------------------- SIMULATION CONTROL --------------------------------------\n')
×
563
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['BeamDyn']['Echo'], 'Echo', '- Echo input data to "<RootName>.ech" (flag)\n'))
×
564
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['BeamDyn']['QuasiStaticInit'], 'QuasiStaticInit', '- Use quasistatic pre-conditioning with centripetal accelerations in initialization (flag) [dynamic solve only]\n'))
×
565
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['BeamDyn']['rhoinf'], 'rhoinf', '- Numerical damping parameter for generalized-alpha integrator\n'))
×
566
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['BeamDyn']['quadrature'], 'quadrature', '- Quadrature method: 1=Gaussian; 2=Trapezoidal (switch)\n'))
×
567
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['BeamDyn']['refine'], 'refine', '- Refinement factor for trapezoidal quadrature (-). DEFAULT = 1 [used only when quadrature=2]\n'))
×
568
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['BeamDyn']['n_fact'], 'n_fact', '- Factorization frequency (-). DEFAULT = 5\n'))
×
569
        f.write(float_default_out(self.fst_vt['BeamDyn']['DTBeam']) + '   {:<11} {:}'.format('DTBeam', '- Time step size (s).\n'))
×
570
        f.write(int_default_out(self.fst_vt['BeamDyn']['load_retries']) + '   {:<11} {:}'.format('load_retries', '- Number of factored load retries before quitting the aimulation\n'))
×
571
        f.write(int_default_out(self.fst_vt['BeamDyn']['NRMax']) + '   {:<11} {:}'.format('NRMax', '- Max number of iterations in Newton-Ralphson algorithm (-). DEFAULT = 10\n'))
×
572
        f.write(float_default_out(self.fst_vt['BeamDyn']['stop_tol']) + '   {:<11} {:}'.format('stop_tol', '- Tolerance for stopping criterion (-)\n'))
×
573
        print('----------')
×
574
        print(self.fst_vt['BeamDyn']['tngt_stf_fd'], type(self.fst_vt['BeamDyn']['tngt_stf_fd']))
×
575

576
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['BeamDyn']['tngt_stf_fd'], 'tngt_stf_fd', '- Flag to use finite differenced tangent stiffness matrix (-)\n'))
×
577
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['BeamDyn']['tngt_stf_comp'], 'tngt_stf_comp', '- Flag to compare analytical finite differenced tangent stiffness matrix  (-)\n'))
×
578
        f.write(float_default_out(self.fst_vt['BeamDyn']['tngt_stf_pert']) + '   {:<11} {:}'.format('tngt_stf_pert', '- perturbation size for finite differencing (-)\n'))
×
579
        f.write(float_default_out(self.fst_vt['BeamDyn']['tngt_stf_difftol']) + '   {:<11} {:}'.format('tngt_stf_difftol', '- Maximum allowable relative difference between analytical and fd tangent stiffness (-)\n'))
×
580
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['BeamDyn']['RotStates'], 'RotStates', '- Orient states in the rotating frame during linearization? (flag) [used only when linearizing]\n'))
×
581
        f.write('---------------------- GEOMETRY PARAMETER --------------------------------------\n')
×
582
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['BeamDyn']['member_total'], 'member_total', '- Total number of members (-)\n'))
×
583
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['BeamDyn']['kp_total'], 'kp_total', '- Total number of key points (-) [must be at least 3]\n'))
×
584
        for i in range(self.fst_vt['BeamDyn']['member_total']):
×
585
            mem = self.fst_vt['BeamDyn']['members'][i]
×
586
            f.write('{:<22} {:<11} {:}'.format(' '.join(['%d'%(i+1),'%d'%len(mem['kp_xr'])]), '', '- Member number; Number of key points in this member\n'))
×
587
            f.write(" ".join(['{:^21s}'.format(i) for i in ['kp_xr', 'kp_yr', 'kp_zr', 'initial_twist']])+'\n')
×
588
            f.write(" ".join(['{:^21s}'.format(i) for i in ['(m)', '(m)', '(m)', '(deg)']])+'\n')
×
589
            for j in range(len(mem['kp_xr'])):
×
590
                ln = []
×
591
                ln.append('{: 2.14e}'.format(mem['kp_xr'][j]))
×
592
                ln.append('{: 2.14e}'.format(mem['kp_yr'][j]))
×
593
                ln.append('{: 2.14e}'.format(mem['kp_zr'][j]))
×
594
                ln.append('{: 2.14e}'.format(mem['initial_twist'][j]))
×
595
                f.write(" ".join(ln) + '\n')
×
596
        f.write('---------------------- MESH PARAMETER ------------------------------------------\n')
×
597
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['BeamDyn']['order_elem'], 'order_elem', '- Order of interpolation (basis) function (-)\n'))
×
598
        f.write('---------------------- MATERIAL PARAMETER --------------------------------------\n')
×
599
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['BeamDyn']['BldFile']+'"', 'BldFile', '- Name of file containing properties for blade (quoted string)\n'))
×
600
        f.write('---------------------- PITCH ACTUATOR PARAMETERS -------------------------------\n')
×
601
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['BeamDyn']['UsePitchAct'], 'UsePitchAct', '- Whether a pitch actuator should be used (flag)\n'))
×
602
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['BeamDyn']['PitchJ'], 'PitchJ', '- Pitch actuator inertia (kg-m^2) [used only when UsePitchAct is true]\n'))
×
603
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['BeamDyn']['PitchK'], 'PitchK', '- Pitch actuator stiffness (kg-m^2/s^2) [used only when UsePitchAct is true]\n'))
×
604
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['BeamDyn']['PitchC'], 'PitchC', '- Pitch actuator damping (kg-m^2/s) [used only when UsePitchAct is true]\n'))
×
605
        f.write('---------------------- OUTPUTS -------------------------------------------------\n')
×
606
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['BeamDyn']['SumPrint'], 'SumPrint', '- Print summary data to "<RootName>.sum" (flag)\n'))
×
607
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['BeamDyn']['OutFmt']+'"', 'OutFmt', '- Format used for text tabular output, excluding the time channel.\n'))
×
608
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['BeamDyn']['NNodeOuts'], 'NNodeOuts', '- Number of nodes to output to file [0 - 9] (-)\n'))
×
609
        f.write('{:<22} {:<11} {:}'.format(', '.join(self.fst_vt['BeamDyn']['OutNd']), 'OutNd', '- Nodes whose values will be output  (-)\n'))
×
610
        f.write('          OutList            - The next line(s) contains a list of output parameters. See OutListParameters.xlsx for a listing of available output channels, (-)\n')
×
611
        outlist = self.get_outlist(self.fst_vt['outlist'], ['BeamDyn'])
×
612
        for channel_list in outlist:
×
613
            for i in range(len(channel_list)):
×
614
                f.write('"' + channel_list[i] + '"\n')
×
615
        f.write('END of input file (the word "END" must appear in the first 3 columns of this last OutList line)\n')
×
616
                
617
        # Optional nodal output section
618
        if 'BldNd_BlOutNd' in self.fst_vt['BeamDyn']:
×
619
            f.write('====== Outputs for all blade stations (same ending as above for B1N1.... =========================== [optional section]\n')
×
620
            # f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['BeamDyn']['BldNd_BladesOut'], 'BldNd_BladesOut', '- Number of blades to output all node information at.  Up to number of blades on turbine. (-)\n'))
621
            f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['BeamDyn']['BldNd_BlOutNd'], 'BldNd_BlOutNd', '- Future feature will allow selecting a portion of the nodes to output.  Not implemented yet. (-)\n'))
×
622
            f.write('                   OutList     - The next line(s) contains a list of output parameters.  See OutListParameters.xlsx, BeamDyn_Nodes tab for a listing of available output channels, (-)\n')
×
623
            
624
            opt_outlist = self.get_outlist(self.fst_vt['outlist'], ['BeamDyn_Nodes'])      
×
625
            for opt_channel_list in opt_outlist:
×
626
                for i in range(len(opt_channel_list)):
×
627
                    f.write('"' + opt_channel_list[i] + '"\n')
×
628
            f.write('END of input file (the word "END" must appear in the first 3 columns of this last OutList line)\n')
×
629
        
630
        f.write('---------------------------------------------------------------------------------------')
×
631
        f.flush()
×
632
        os.fsync(f)
×
633
        f.close()
×
634

635
        # f.write('{:<22} {:<11} {:}'.format(self.fst_vt['BeamDyn'][''], '', '\n'))
636
        # f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['BeamDyn'][''], '', '\n'))
637
        # f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['BeamDyn'][''], '', '\n'))
638
        # f.write('{: 2.15e} {:<11} {:}'.format(self.fst_vt['BeamDyn'][''], '', '\n'))
639
        # f.write(float_default_out(self.fst_vt['BeamDyn']['']) + '   {:<11} {:}'.format('', '\n'))
640
        # f.write(int_default_out(self.fst_vt['BeamDyn']['']) + '   {:<11} {:}'.format('', '\n'))
641

642
    def write_BeamDynBlade(self):
1✔
643

644
        # bd_blade_file = self.fst_vt['BeamDyn']['BldFile']
645
        self.fst_vt['BeamDyn']['BldFile'] = self.FAST_namingOut + '_BeamDyn_Blade.dat'
×
646
        bd_blade_file = os.path.abspath(os.path.join(self.FAST_runDirectory, self.fst_vt['BeamDyn']['BldFile']))
×
647
        f = open(bd_blade_file, 'w')
×
648

649
        f.write('------- BEAMDYN V1.00.* INDIVIDUAL BLADE INPUT FILE --------------------------\n')
×
650
        f.write('Generated with AeroElasticSE FAST driver\n')
×
651
        f.write('---------------------- BLADE PARAMETERS --------------------------------------\n')
×
652
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['BeamDynBlade']['station_total'], 'station_total', '- Number of blade input stations (-)\n'))
×
653
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['BeamDynBlade']['damp_type'], 'damp_type', '- Damping type: 0: no damping; 1: damped\n'))
×
654
        f.write('---------------------- DAMPING COEFFICIENT------------------------------------\n')
×
655
        f.write(" ".join(['{:^11s}'.format(i) for i in ['mu1','mu2','mu3','mu4','mu5','mu6']])+'\n')
×
656
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)','(-)','(-)','(-)','(-)','(-)']])+'\n')
×
657
        mu = [self.fst_vt['BeamDynBlade']['mu1'], self.fst_vt['BeamDynBlade']['mu2'], self.fst_vt['BeamDynBlade']['mu3'], self.fst_vt['BeamDynBlade']['mu4'], self.fst_vt['BeamDynBlade']['mu5'], self.fst_vt['BeamDynBlade']['mu6']]
×
658
        f.write(" ".join(['{:^11f}'.format(i) for i in mu])+'\n')
×
659
        f.write('---------------------- DISTRIBUTED PROPERTIES---------------------------------\n')
×
660

661
        for i in range(len(self.fst_vt['BeamDynBlade']['radial_stations'])):
×
662
            f.write('{: 2.15e}\n'.format(self.fst_vt['BeamDynBlade']['radial_stations'][i]))
×
663
            for j in range(6):
×
664
                f.write(" ".join(['{: 2.15e}'.format(i) for i in self.fst_vt['BeamDynBlade']['beam_stiff'][i,j,:]])+'\n')
×
665
            f.write('\n')
×
666
            for j in range(6):
×
667
                f.write(" ".join(['{: 2.15e}'.format(i) for i in self.fst_vt['BeamDynBlade']['beam_inertia'][i,j,:]])+'\n')
×
668
            f.write('\n')
×
669

670
        f.write('\n')
×
671

672
    def write_InflowWind(self):
1✔
673
        self.fst_vt['Fst']['InflowFile'] = self.FAST_namingOut + '_InflowFile.dat'
1✔
674
        inflow_file = os.path.join(self.FAST_runDirectory,self.fst_vt['Fst']['InflowFile'])
1✔
675
        f = open(inflow_file, 'w')
1✔
676

677
        f.write('------- InflowWind v3.01.* INPUT FILE -------------------------------------------------------------------------\n')
1✔
678
        f.write('Generated with AeroElasticSE FAST driver\n')
1✔
679
        f.write('---------------------------------------------------------------------------------------------------------------\n')
1✔
680
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['Echo'], 'Echo', '- Echo input data to <RootName>.ech (flag)\n'))
1✔
681
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['WindType'], 'WindType', '- switch for wind file type (1=steady; 2=uniform; 3=binary TurbSim FF; 4=binary Bladed-style FF; 5=HAWC format; 6=User defined; 7=native Bladed FF)\n'))
1✔
682
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['PropagationDir'], 'PropagationDir', '- Direction of wind propagation (meteoroligical rotation from aligned with X (positive rotates towards -Y) -- degrees)\n'))
1✔
683
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['VFlowAng'], 'VFlowAng', '- Upflow angle (degrees) (not used for native Bladed format WindType=7)\n'))
1✔
684
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['VelInterpCubic'], 'VelInterpCubic', '- Use cubic interpolation for velocity in time (false=linear, true=cubic) [Used with WindType=2,3,4,5,7]\n'))
1✔
685
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['NWindVel'], 'NWindVel', '- Number of points to output the wind velocity    (0 to 9)\n'))
1✔
686
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['WindVxiList'], 'WindVxiList', '- List of coordinates in the inertial X direction (m)\n'))
1✔
687
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['WindVyiList'], 'WindVyiList', '- List of coordinates in the inertial Y direction (m)\n'))
1✔
688
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['WindVziList'], 'WindVziList', '- List of coordinates in the inertial Z direction (m)\n'))
1✔
689
        f.write('================== Parameters for Steady Wind Conditions [used only for WindType = 1] =========================\n')
1✔
690
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['HWindSpeed'], 'HWindSpeed', '- Horizontal windspeed                            (m/s)\n'))
1✔
691
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['RefHt'], 'RefHt', '- Reference height for horizontal wind speed      (m)\n'))
1✔
692
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['PLexp'], 'PLexp', '- Power law exponent                              (-)\n'))
1✔
693
        f.write('================== Parameters for Uniform wind file   [used only for WindType = 2] ============================\n')
1✔
694
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['InflowWind']['Filename_Uni']+'"', 'Filename_Uni', '- Filename of time series data for uniform wind field.      (-)\n'))
1✔
695
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['RefHt_Uni'], 'RefHt_Uni', '- Reference height for horizontal wind speed                (m)\n'))
1✔
696
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['RefLength'], 'RefLength', '- Reference length for linear horizontal and vertical sheer (-)\n'))
1✔
697
        f.write('================== Parameters for Binary TurbSim Full-Field files   [used only for WindType = 3] ==============\n')
1✔
698
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['InflowWind']['FileName_BTS']+'"', 'FileName_BTS', '- Name of the Full field wind file to use (.bts)\n'))
1✔
699
        f.write('================== Parameters for Binary Bladed-style Full-Field files   [used only for WindType = 4] =========\n')
1✔
700
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['InflowWind']['FilenameRoot']+'"', 'FilenameRoot', '- Rootname of the full-field wind file to use (.wnd, .sum)\n'))
1✔
701
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['TowerFile'], 'TowerFile', '- Have tower file (.twr) (flag)\n'))
1✔
702
        f.write('================== Parameters for HAWC-format binary files  [Only used with WindType = 5] =====================\n')
1✔
703
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['InflowWind']['FileName_u']+'"', 'FileName_u', '- name of the file containing the u-component fluctuating wind (.bin)\n'))
1✔
704
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['InflowWind']['FileName_v']+'"', 'FileName_v', '- name of the file containing the v-component fluctuating wind (.bin)\n'))
1✔
705
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['InflowWind']['FileName_w']+'"', 'FileName_w', '- name of the file containing the w-component fluctuating wind (.bin)\n'))
1✔
706
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['nx'], 'nx', '- number of grids in the x direction (in the 3 files above) (-)\n'))
1✔
707
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['ny'], 'ny', '- number of grids in the y direction (in the 3 files above) (-)\n'))
1✔
708
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['nz'], 'nz', '- number of grids in the z direction (in the 3 files above) (-)\n'))
1✔
709
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['dx'], 'dx', '- distance (in meters) between points in the x direction    (m)\n'))
1✔
710
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['dy'], 'dy', '- distance (in meters) between points in the y direction    (m)\n'))
1✔
711
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['dz'], 'dz', '- distance (in meters) between points in the z direction    (m)\n'))
1✔
712
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['RefHt_Hawc'], 'RefHt_Hawc', '- reference height; the height (in meters) of the vertical center of the grid (m)\n'))
1✔
713
        f.write('-------------   Scaling parameters for turbulence   ---------------------------------------------------------\n')
1✔
714
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['ScaleMethod'], 'ScaleMethod', '- Turbulence scaling method   [0 = none, 1 = direct scaling, 2 = calculate scaling factor based on a desired standard deviation]\n'))
1✔
715
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['SFx'], 'SFx', '- Turbulence scaling factor for the x direction (-)   [ScaleMethod=1]\n'))
1✔
716
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['SFy'], 'SFy', '- Turbulence scaling factor for the y direction (-)   [ScaleMethod=1]\n'))
1✔
717
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['SFz'], 'SFz', '- Turbulence scaling factor for the z direction (-)   [ScaleMethod=1]\n'))
1✔
718
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['SigmaFx'], 'SigmaFx', '- Turbulence standard deviation to calculate scaling from in x direction (m/s)    [ScaleMethod=2]\n'))
1✔
719
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['SigmaFy'], 'SigmaFy', '- Turbulence standard deviation to calculate scaling from in y direction (m/s)    [ScaleMethod=2]\n'))
1✔
720
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['SigmaFz'], 'SigmaFz', '- Turbulence standard deviation to calculate scaling from in z direction (m/s)    [ScaleMethod=2]\n'))
1✔
721
        f.write('-------------   Mean wind profile parameters (added to HAWC-format files)   ---------------------------------\n')
1✔
722
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['URef'], 'URef', '- Mean u-component wind speed at the reference height (m/s)\n'))
1✔
723
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['WindProfile'], 'WindProfile', '- Wind profile type (0=constant;1=logarithmic,2=power law)\n'))
1✔
724
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['PLExp_Hawc'], 'PLExp_Hawc', '- Power law exponent (-) (used for PL wind profile type only)\n'))
1✔
725
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['Z0'], 'Z0', '- Surface roughness length (m) (used for LG wind profile type only)\n'))
1✔
726
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['XOffset'], 'XOffset', '- Initial offset in +x direction (shift of wind box) (-)\n'))
1✔
727
        f.write('-------------   LIDAR Parameters   --------------------------------------------------------------------------\n')
1✔
728
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['SensorType'], 'SensorType', '- Switch for lidar configuration (0 = None, 1 = Single Point Beam(s), 2 = Continuous, 3 = Pulsed)\n'))
1✔
729
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['NumPulseGate'], 'NumPulseGate', '- Number of lidar measurement gates (used when SensorType = 3)\n'))
1✔
730
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['PulseSpacing'], 'PulseSpacing', '- Distance between range gates (m) (used when SensorType = 3)\n'))
1✔
731
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['NumBeam'], 'NumBeam', '- Number of lidar measurement beams (0-5)(used when SensorType = 1)\n'))
1✔
732
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['FocalDistanceX'], 'FocalDistanceX', '- Focal distance co-ordinates of the lidar beam in the x direction (relative to hub height) (only first coordinate used for SensorType 2 and 3) (m)\n'))
1✔
733
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['FocalDistanceY'], 'FocalDistanceY', '- Focal distance co-ordinates of the lidar beam in the y direction (relative to hub height) (only first coordinate used for SensorType 2 and 3) (m)\n'))
1✔
734
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['FocalDistanceZ'], 'FocalDistanceZ', '- Focal distance co-ordinates of the lidar beam in the z direction (relative to hub height) (only first coordinate used for SensorType 2 and 3) (m)\n'))
1✔
735
        f.write('{:<22} {:<11} {:}'.format(', '.join(np.array(self.fst_vt['InflowWind']['RotorApexOffsetPos'], dtype=str)), 'RotorApexOffsetPos', '- Offset of the lidar from hub height (m)\n'))
1✔
736
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['URefLid'], 'URefLid', '- Reference average wind speed for the lidar[m/s]\n'))
1✔
737
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['MeasurementInterval'], 'MeasurementInterval', '- Time between each measurement [s]\n'))
1✔
738
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['LidRadialVel'], 'LidRadialVel', '- TRUE => return radial component, FALSE => return x direction estimate\n'))
1✔
739
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['ConsiderHubMotion'], 'ConsiderHubMotion', '- Flag whether to consider the hub motions impact on Lidar measurements\n'))
1✔
740
        f.write('====================== OUTPUT ==================================================\n')
1✔
741
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['InflowWind']['SumPrint'], 'SumPrint', '- Print summary data to <RootName>.IfW.sum (flag)\n'))
1✔
742
        f.write('OutList      - The next line(s) contains a list of output parameters.  See OutListParameters.xlsx for a listing of available output channels, (-)\n')
1✔
743
        
744
        outlist = self.get_outlist(self.fst_vt['outlist'], ['InflowWind'])
1✔
745
        for channel_list in outlist:
1✔
746
            for i in range(len(channel_list)):
1✔
747
                f.write('"' + channel_list[i] + '"\n')
1✔
748

749
        f.write('END of input file (the word "END" must appear in the first 3 columns of this last OutList line)\n')
1✔
750
        f.write('---------------------------------------------------------------------------------------\n')
1✔
751

752
        f.flush()
1✔
753
        os.fsync(f)
1✔
754
        f.close()
1✔
755
  
756
    def write_AeroDyn15(self):
1✔
757
        # AeroDyn v15.03
758

759
        # Generate AeroDyn v15 blade input file
760
        self.write_AeroDyn15Blade()
1✔
761

762
        # Generate AeroDyn v15 polars
763
        self.write_AeroDyn15Polar()
1✔
764
        
765
        # Generate AeroDyn v15 airfoil coordinates
766
        if self.fst_vt['AeroDyn15']['af_data'][1][0]['NumCoords'] != '0':
1✔
767
            self.write_AeroDyn15Coord()
1✔
768
        
769
        if self.fst_vt['AeroDyn15']['WakeMod'] == 3:
1✔
770
            if self.fst_vt['AeroDyn15']['AFAeroMod'] == 2:
×
771
                raise Exception('OLAF is called with unsteady airfoil aerodynamics, but OLAF currently only supports AFAeroMod == 1')
×
772
            self.write_OLAF()
×
773

774
        # Generate AeroDyn v15.03 input file
775
        self.fst_vt['Fst']['AeroFile'] = self.FAST_namingOut + '_AeroDyn15.dat'
1✔
776
        ad_file = os.path.join(self.FAST_runDirectory, self.fst_vt['Fst']['AeroFile'])
1✔
777
        f = open(ad_file, 'w')
1✔
778

779
        f.write('------- AERODYN v15.03.* INPUT FILE ------------------------------------------------\n')
1✔
780
        f.write('Generated with AeroElasticSE FAST driver\n')
1✔
781
        f.write('======  General Options  ============================================================================\n')
1✔
782
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['Echo'], 'Echo', '- Echo the input to "<rootname>.AD.ech"?  (flag)\n'))
1✔
783
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['DTAero'], 'DTAero', '- Time interval for aerodynamic calculations {or "default"} (s)\n'))
1✔
784
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['WakeMod'], 'WakeMod', '- Type of wake/induction model (switch) {0=none, 1=BEMT, 2=DBEMT, 3=OLAF} [WakeMod cannot be 2 or 3 when linearizing]\n'))
1✔
785
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['AFAeroMod'], 'AFAeroMod', '- Type of blade airfoil aerodynamics model (switch) {1=steady model, 2=Beddoes-Leishman unsteady model} [AFAeroMod must be 1 when linearizing]\n'))
1✔
786
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['TwrPotent'], 'TwrPotent', '- Type tower influence on wind based on potential flow around the tower (switch) {0=none, 1=baseline potential flow, 2=potential flow with Bak correction}\n'))
1✔
787
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['TwrShadow'], 'TwrShadow', '- Calculate tower influence on wind based on downstream tower shadow (switch) {0=none, 1=Powles model, 2=Eames model}\n'))
1✔
788
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['TwrAero'], 'TwrAero', '- Calculate tower aerodynamic loads? (flag)\n'))
1✔
789
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['FrozenWake'], 'FrozenWake', '- Assume frozen wake during linearization? (flag) [used only when WakeMod=1 and when linearizing]\n'))
1✔
790
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['CavitCheck'], 'CavitCheck', '- Perform cavitation check? (flag) [AFAeroMod must be 1 when CavitCheck=true]\n'))
1✔
791
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['Buoyancy'], 'Buoyancy', '- Include buoyancy effects? (flag)\n'))
1✔
792
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['CompAA'], 'CompAA', '- Flag to compute AeroAcoustics calculation [only used when WakeMod=1 or 2]\n'))
1✔
793
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['AA_InputFile'], 'AA_InputFile', '- AeroAcoustics input file [used only when CompAA=true]\n'))
1✔
794
        f.write('======  Environmental Conditions  ===================================================================\n')
1✔
795
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['AirDens'], 'AirDens', '- Air density (kg/m^3)\n'))
1✔
796
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['KinVisc'], 'KinVisc', '- Kinematic air viscosity (m^2/s)\n'))
1✔
797
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['SpdSound'], 'SpdSound', '- Speed of sound (m/s)\n'))
1✔
798
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['Patm'], 'Patm', '- Atmospheric pressure (Pa) [used only when CavitCheck=True]\n'))
1✔
799
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['Pvap'], 'Pvap', '- Vapour pressure of fluid (Pa) [used only when CavitCheck=True]\n'))
1✔
800
        f.write('======  Blade-Element/Momentum Theory Options  ====================================================== [unused when WakeMod=0 or 3]\n')
1✔
801
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['SkewMod'], 'SkewMod', '- Type of skewed-wake correction model (switch) {1=uncoupled, 2=Pitt/Peters, 3=coupled} [unused when WakeMod=0 or 3]\n'))
1✔
802
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['SkewModFactor'], 'SkewModFactor', '- Constant used in Pitt/Peters skewed wake model {or "default" is 15/32*pi} (-) [used only when SkewMod=2; unused when WakeMod=0 or 3]\n'))
1✔
803
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['TipLoss'], 'TipLoss', '- Use the Prandtl tip-loss model? (flag) [unused when WakeMod=0 or 3]\n'))
1✔
804
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['HubLoss'], 'HubLoss', '- Use the Prandtl hub-loss model? (flag) [unused when WakeMod=0 or 3]\n'))
1✔
805
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['TanInd'], 'TanInd', '- Include tangential induction in BEMT calculations? (flag) [unused when WakeMod=0 or 3]\n'))
1✔
806
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['AIDrag'], 'AIDrag', '- Include the drag term in the axial-induction calculation? (flag) [unused when WakeMod=0 or 3]\n'))
1✔
807
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['TIDrag'], 'TIDrag', '- Include the drag term in the tangential-induction calculation? (flag) [unused when WakeMod=0,3 or TanInd=FALSE]\n'))
1✔
808
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['IndToler'], 'IndToler', '- Convergence tolerance for BEMT nonlinear solve residual equation {or "default"} (-) [unused when WakeMod=0 or 3]\n'))
1✔
809
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['MaxIter'], 'MaxIter', '- Maximum number of iteration steps (-) [unused when WakeMod=0]\n'))
1✔
810
        f.write('======  Dynamic Blade-Element/Momentum Theory Options  ====================================================== [used only when WakeMod=2]\n')
1✔
811
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['DBEMT_Mod'], 'DBEMT_Mod', '- Type of dynamic BEMT (DBEMT) model {1=constant tau1, 2=time-dependent tau1, 3=constant tau1 with continuous formulation} (-) [used only when WakeMod=2]\n'))
1✔
812
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['tau1_const'], 'tau1_const', '- Time constant for DBEMT (s) [used only when WakeMod=2 and DBEMT_Mod=1]\n'))
1✔
813
        f.write('======  OLAF -- cOnvecting LAgrangian Filaments (Free Vortex Wake) Theory Options  ================== [used only when WakeMod=3]\n')
1✔
814
        olaf_file = self.FAST_namingOut + '_OLAF.dat'
1✔
815
        f.write('{!s:<22} {:<11} {:}'.format(olaf_file, 'OLAFInputFileName', '- Input file for OLAF [used only when WakeMod=3]\n'))  
1✔
816
        f.write('======  Beddoes-Leishman Unsteady Airfoil Aerodynamics Options  ===================================== [used only when AFAeroMod=2]\n')
1✔
817
        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"))
1✔
818
        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"))
1✔
819
        if 'UAStartRad' in self.fst_vt['AeroDyn15'] and 'UAEndRad' in self.fst_vt['AeroDyn15']:
1✔
820
            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]\n'))
1✔
821
            f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['UAEndRad'], 'UAEndRad', '- Ending radius for dynamic stall (fraction of rotor radius) [used only when AFAeroMod=2]\n'))
1✔
822
        f.write('======  Airfoil Information =========================================================================\n')
1✔
823
        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'))
1✔
824
        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'))
1✔
825
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['InCol_Cl'], 'InCol_Cl', '- The column in the airfoil tables that contains the lift coefficient (-)\n'))
1✔
826
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['InCol_Cd'], 'InCol_Cd', '- The column in the airfoil tables that contains the drag coefficient (-)\n'))
1✔
827
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['InCol_Cm'], 'InCol_Cm', '- The column in the airfoil tables that contains the pitching-moment coefficient; use zero if there is no Cm column (-)\n'))
1✔
828
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['InCol_Cpmin'], 'InCol_Cpmin', '- The column in the airfoil tables that contains the Cpmin coefficient; use zero if there is no Cpmin column (-)\n'))
1✔
829
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['NumAFfiles'], 'NumAFfiles', '- Number of airfoil files used (-)\n'))
1✔
830
        for i in range(self.fst_vt['AeroDyn15']['NumAFfiles']):
1✔
831
            if i == 0:
1✔
832
                f.write('"' + self.fst_vt['AeroDyn15']['AFNames'][i] + '"    AFNames            - Airfoil file names (NumAFfiles lines) (quoted strings)\n')
1✔
833
            else:
834
                f.write('"' + self.fst_vt['AeroDyn15']['AFNames'][i] + '"\n')
1✔
835
        f.write('======  Rotor/Blade Properties  =====================================================================\n')
1✔
836
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['UseBlCm'], 'UseBlCm', '- Include aerodynamic pitching moment in calculations?  (flag)\n'))
1✔
837
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['AeroDyn15']['ADBlFile1']+'"', 'ADBlFile(1)', '- Name of file containing distributed aerodynamic properties for Blade #1 (-)\n'))
1✔
838
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['AeroDyn15']['ADBlFile2']+'"', 'ADBlFile(2)', '- Name of file containing distributed aerodynamic properties for Blade #2 (-) [unused if NumBl < 2]\n'))
1✔
839
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['AeroDyn15']['ADBlFile3']+'"', 'ADBlFile(3)', '- Name of file containing distributed aerodynamic properties for Blade #3 (-) [unused if NumBl < 3]\n'))
1✔
840
        f.write('======  Hub Properties ============================================================================== [used only when Buoyancy=True]\n')
1✔
841
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['VolHub'], 'VolHub', '- Hub volume (m^3)\n'))
1✔
842
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['HubCenBx'], 'HubCenBx', '- Hub center of buoyancy x direction offset (m)\n'))
1✔
843
        f.write('======  Nacelle Properties ========================================================================== [used only when Buoyancy=True]\n')
1✔
844
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['VolNac'], 'VolNac', '- Nacelle volume (m^3)\n'))
1✔
845
        f.write('{:<22} {:<11} {:}'.format(', '.join(np.array(self.fst_vt['AeroDyn15']['NacCenB'], dtype=str)), 'NacCenB', '- Position of nacelle center of buoyancy from yaw bearing in nacelle coordinates (m)\n'))
1✔
846
        f.write('======  Tail Fin Aerodynamics ========================================================================\n')
1✔
847
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['TFinAero'], 'TFinAero', '- Calculate tail fin aerodynamics model (flag)\n'))
1✔
848
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['AeroDyn15']['TFinFile']+'"', 'TFinFile', '- Input file for tail fin aerodynamics [used only when TFinAero=True]\n'))
1✔
849
        f.write('======  Tower Influence and Aerodynamics ============================================================ [used only when TwrPotent/=0, TwrShadow/=0, TwrAero=True, or Buoyancy=True]\n')
1✔
850
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['NumTwrNds'], 'NumTwrNds', '- Number of tower nodes used in the analysis  (-) [used only when TwrPotent/=0, TwrShadow/=0, TwrAero=True, or Buoyancy=True]\n'))
1✔
851
        f.write('TwrElev        TwrDiam        TwrCd          TwrTI          TwrCb !TwrTI used only with TwrShadow=2, TwrCb used only with Buoyancy=True\n')
1✔
852
        f.write('(m)              (m)           (-)            (-)            (-)\n')
1✔
853
        for TwrElev, TwrDiam, TwrCd, TwrTI, TwrCb in zip(self.fst_vt['AeroDyn15']['TwrElev'], self.fst_vt['AeroDyn15']['TwrDiam'], self.fst_vt['AeroDyn15']['TwrCd'], self.fst_vt['AeroDyn15']['TwrTI'], self.fst_vt['AeroDyn15']['TwrCb']):
1✔
854
            f.write('{: 2.15e} {: 2.15e} {: 2.15e} {: 2.15e} {: 2.15e} \n'.format(TwrElev, TwrDiam, TwrCd, TwrTI, TwrCb))
1✔
855
        f.write('======  Outputs  ====================================================================================\n')
1✔
856
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['SumPrint'], 'SumPrint', '- Generate a summary file listing input options and interpolated properties to "<rootname>.AD.sum"?  (flag)\n'))
1✔
857
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['NBlOuts'], 'NBlOuts', '- Number of blade node outputs [0 - 9] (-)\n'))
1✔
858
        f.write('{:<22} {:<11} {:}'.format(', '.join(self.fst_vt['AeroDyn15']['BlOutNd']), 'BlOutNd', '- Blade nodes whose values will be output  (-)\n'))
1✔
859
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['NTwOuts'], 'NTwOuts', '- Number of tower node outputs [0 - 9]  (-)\n'))
1✔
860
        if self.fst_vt['AeroDyn15']['NTwOuts'] != 0:
1✔
861
            f.write('{:<22} {:<11} {:}'.format(', '.join(self.fst_vt['AeroDyn15']['TwOutNd']), 'TwOutNd', '- Tower nodes whose values will be output  (-)\n'))
×
862
        else:
863
            f.write('{:<22} {:<11} {:}'.format(0, 'TwOutNd', '- Tower nodes whose values will be output  (-)\n'))
1✔
864
        f.write('                   OutList             - The next line(s) contains a list of output parameters.  See OutListParameters.xlsx for a listing of available output channels, (-)\n')
1✔
865

866
        outlist = self.get_outlist(self.fst_vt['outlist'], ['AeroDyn'])      
1✔
867
        for channel_list in outlist:
1✔
868
            for i in range(len(channel_list)):
1✔
869
                f.write('"' + channel_list[i] + '"\n')
1✔
870
        f.write('END of input file (the word "END" must appear in the first 3 columns of this last OutList line)\n')
1✔
871
        
872
        # Optional nodal output section
873
        if 'BldNd_BladesOut' in self.fst_vt['AeroDyn15']:
1✔
874
            f.write('====== Outputs for all blade stations (same ending as above for B1N1.... =========================== [optional section]\n')
×
875
            f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['BldNd_BladesOut'], 'BldNd_BladesOut', '- Number of blades to output all node information at.  Up to number of blades on turbine. (-)\n'))
×
876
            f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['BldNd_BlOutNd'], 'BldNd_BlOutNd', '- Future feature will allow selecting a portion of the nodes to output.  Not implemented yet. (-)\n'))
×
877
            f.write('                   OutList     - The next line(s) contains a list of output parameters.  See OutListParameters.xlsx, AeroDyn_Nodes tab for a listing of available output channels, (-)\n')
×
878
            
879
            opt_outlist = self.get_outlist(self.fst_vt['outlist'], ['AeroDyn_Nodes'])      
×
880
            for opt_channel_list in opt_outlist:
×
881
                for i in range(len(opt_channel_list)):
×
882
                    f.write('"' + opt_channel_list[i] + '"\n')
×
883
            f.write('END of input file (the word "END" must appear in the first 3 columns of this last OutList line)\n')
×
884
        
885
        f.write('---------------------------------------------------------------------------------------\n')
1✔
886
        f.flush()
1✔
887
        os.fsync(f)
1✔
888
        f.close()
1✔
889

890
    def write_AeroDyn15Blade(self):
1✔
891
        # AeroDyn v15.00 Blade
892
        self.fst_vt['AeroDyn15']['ADBlFile1'] = self.FAST_namingOut + '_AeroDyn15_blade.dat'
1✔
893
        self.fst_vt['AeroDyn15']['ADBlFile2'] = self.fst_vt['AeroDyn15']['ADBlFile1']
1✔
894
        self.fst_vt['AeroDyn15']['ADBlFile3'] = self.fst_vt['AeroDyn15']['ADBlFile1']
1✔
895
        filename = os.path.join(self.FAST_runDirectory, self.fst_vt['AeroDyn15']['ADBlFile1'])
1✔
896
        f = open(filename, 'w')
1✔
897

898
        f.write('------- AERODYN v15.00.* BLADE DEFINITION INPUT FILE -------------------------------------\n')
1✔
899
        f.write('Generated with AeroElasticSE FAST driver\n')
1✔
900
        f.write('======  Blade Properties =================================================================\n')
1✔
901
        f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['AeroDynBlade']['NumBlNds'], 'NumBlNds', '- Number of blade nodes used in the analysis (-)\n'))
1✔
902
        f.write('    BlSpn        BlCrvAC        BlSwpAC        BlCrvAng       BlTwist        BlChord          BlAFID\n')
1✔
903
        f.write('     (m)           (m)            (m)            (deg)         (deg)           (m)              (-)\n')
1✔
904
        BlSpn    = self.fst_vt['AeroDynBlade']['BlSpn']
1✔
905
        BlCrvAC  = self.fst_vt['AeroDynBlade']['BlCrvAC']
1✔
906
        BlSwpAC  = self.fst_vt['AeroDynBlade']['BlSwpAC']
1✔
907
        BlCrvAng = self.fst_vt['AeroDynBlade']['BlCrvAng']
1✔
908
        BlTwist  = self.fst_vt['AeroDynBlade']['BlTwist']
1✔
909
        BlChord  = self.fst_vt['AeroDynBlade']['BlChord']
1✔
910
        BlAFID   = self.fst_vt['AeroDynBlade']['BlAFID']
1✔
911
        for Spn, CrvAC, SwpAC, CrvAng, Twist, Chord, AFID in zip(BlSpn, BlCrvAC, BlSwpAC, BlCrvAng, BlTwist, BlChord, BlAFID):
1✔
912
            f.write('{: 2.15e} {: 2.15e} {: 2.15e} {: 2.15e} {: 2.15e} {: 2.15e} {: 8d}\n'.format(Spn, CrvAC, SwpAC, CrvAng, Twist, Chord, int(AFID)))
1✔
913
        
914
        f.flush()
1✔
915
        os.fsync(f)
1✔
916
        f.close()
1✔
917
        
918
    def write_AeroDyn15Polar(self):
1✔
919
        # Airfoil Info v1.01
920

921
        if not os.path.isdir(os.path.join(self.FAST_runDirectory,'Airfoils')):
1✔
922
            try:
1✔
923
                os.makedirs(os.path.join(self.FAST_runDirectory,'Airfoils'))
1✔
924
            except:
×
925
                try:
×
926
                    time.sleep(random.random())
×
927
                    if not os.path.isdir(os.path.join(self.FAST_runDirectory,'Airfoils')):
×
928
                        os.makedirs(os.path.join(self.FAST_runDirectory,'Airfoils'))
×
929
                except:
×
930
                    print("Error tring to make '%s'!"%os.path.join(self.FAST_runDirectory,'Airfoils'))
×
931

932

933
        self.fst_vt['AeroDyn15']['NumAFfiles'] = len(self.fst_vt['AeroDyn15']['af_data'])
1✔
934
        self.fst_vt['AeroDyn15']['AFNames'] = ['']*self.fst_vt['AeroDyn15']['NumAFfiles']
1✔
935

936
        for afi in range(int(self.fst_vt['AeroDyn15']['NumAFfiles'])):
1✔
937

938
            self.fst_vt['AeroDyn15']['AFNames'][afi] = os.path.join('Airfoils', self.FAST_namingOut + '_AeroDyn15_Polar_%02d.dat'%afi)
1✔
939
            af_file = os.path.join(self.FAST_runDirectory, self.fst_vt['AeroDyn15']['AFNames'][afi])
1✔
940
            f = open(af_file, 'w')
1✔
941

942
            f.write('! ------------ AirfoilInfo v1.01.x Input File ----------------------------------\n')
1✔
943
            f.write('! AeroElasticSE FAST driver\n')
1✔
944
            f.write('! line\n')
1✔
945
            f.write('! line\n')
1✔
946
            f.write('! ------------------------------------------------------------------------------\n')
1✔
947
            f.write('{:<22}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][0]['InterpOrd'], 'InterpOrd', '! Interpolation order to use for quasi-steady table lookup {1=linear; 3=cubic spline; "default"} [default=3]\n'))
1✔
948
            f.write('{:<22}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][0]['NonDimArea'], 'NonDimArea', '! The non-dimensional area of the airfoil (area/chord^2) (set to 1.0 if unsure or unneeded)\n'))
1✔
949
            if self.fst_vt['AeroDyn15']['af_data'][afi][0]['NumCoords'] != '0':
1✔
950
                f.write('@"{:}_AF{:02d}_Coords.txt"       {:<11} {:}'.format(self.FAST_namingOut, afi, 'NumCoords', '! The number of coordinates in the airfoil shape file. Set to zero if coordinates not included.\n'))
1✔
951
            else:
952
                f.write('{:<22d}       {:<11} {:}'.format(0, 'NumCoords', '! The number of coordinates in the airfoil shape file. Set to zero if coordinates not included.\n'))
1✔
953
            f.write('AF{:02d}_BL.txt              {:<11} {:}'.format(afi, 'BL_file', '! The file name including the boundary layer characteristics of the profile. Ignored if the aeroacoustic module is not called.\n'))
1✔
954
            # f.write('{:<22d}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][0]['NumTabs'], 'NumTabs', '! Number of airfoil tables in this file.  Each table must have lines for Re and Ctrl.\n'))
955

956

957
            # Check if we have multiple tables per airfoil
958
            # if yes, allocate the number of airfoils to the respective radial stations
959
            if self.fst_vt['AeroDyn15']['AFTabMod'] == 2:
1✔
960
                num_tab = len(self.fst_vt['AeroDyn15']['af_data'][afi])
×
961
            elif self.fst_vt['AeroDyn15']['AFTabMod'] == 3:
1✔
962
                # for tab_orig in range(self.fst_vt['AeroDyn15']['af_data'][afi][0]['NumTabs'] - 1):
963
                if len( self.fst_vt['AeroDyn15']['af_data'][afi]) == 1 or \
×
964
                    self.fst_vt['AeroDyn15']['af_data'][afi][0]['Ctrl'] == self.fst_vt['AeroDyn15']['af_data'][afi][1]['Ctrl']:
965
                    num_tab = 1  # assume that all Ctrl angles of the flaps are identical if the first two are -> no flaps!
×
966
                else:
967
                    num_tab = self.fst_vt['AeroDyn15']['af_data'][afi][0]['NumTabs']
×
968
            else:
969
                num_tab = 1
1✔
970
            # f.write('{:<22d}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][0]['NumTabs'], 'NumTabs','! Number of airfoil tables in this file.  Each table must have lines for Re and Ctrl.\n'))
971
            f.write('{:<22d}   {:<11} {:}'.format(num_tab, 'NumTabs','! Number of airfoil tables in this file.  Each table must have lines for Re and Ctrl.\n'))
1✔
972

973
            # for tab in range(self.fst_vt['AeroDyn15']['af_data'][afi][0]['NumTabs']): # For writing multiple tables (different Re or Ctrl values)
974
            for tab in range(num_tab): # For writing multiple tables (different Re or Ctrl values)
1✔
975
                f.write('! ------------------------------------------------------------------------------\n')
1✔
976
                f.write("! data for table %i \n" % (tab + 1))
1✔
977
                f.write('! ------------------------------------------------------------------------------\n')
1✔
978
                f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['Re']*1.e-6, 'Re', '! Reynolds number in millions\n'))
1✔
979
                f.write('{:<22d}   {:<11} {:}'.format(int(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['Ctrl']), 'Ctrl', '! Control setting (must be 0 for current AirfoilInfo)\n'))
1✔
980
                f.write('{!s:<22}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['InclUAdata'], 'InclUAdata', '! Is unsteady aerodynamics data included in this table? If TRUE, then include 30 UA coefficients below this line\n'))
1✔
981
                f.write('!........................................\n')
1✔
982
                if self.fst_vt['AeroDyn15']['af_data'][afi][tab]['InclUAdata']:
1✔
983
                    f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['alpha0'], 'alpha0', '! 0-lift angle of attack, depends on airfoil.\n'))
1✔
984
                    f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['alpha1'], 'alpha1', '! Angle of attack at f=0.7, (approximately the stall angle) for AOA>alpha0. (deg)\n'))
1✔
985
                    f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['alpha2'], 'alpha2', '! Angle of attack at f=0.7, (approximately the stall angle) for AOA<alpha0. (deg)\n'))
1✔
986
                    f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['eta_e'], 'eta_e', '! Recovery factor in the range [0.85 - 0.95] used only for UAMOD=1, it is set to 1 in the code when flookup=True. (-)\n'))
1✔
987
                    f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['C_nalpha'], 'C_nalpha', '! Slope of the 2D normal force coefficient curve. (1/rad)\n'))
1✔
988
                    f.write(float_default_out(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['T_f0']) + '   {:<11} {:}'.format('T_f0', '! Initial value of the time constant associated with Df in the expression of Df and f''. [default = 3]\n'))
1✔
989
                    f.write(float_default_out(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['T_V0']) + '   {:<11} {:}'.format('T_V0', '! Initial value of the time constant associated with the vortex lift decay process; it is used in the expression of Cvn. It depends on Re,M, and airfoil class. [default = 6]\n'))
1✔
990
                    f.write(float_default_out(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['T_p']) + '   {:<11} {:}'.format('T_p', '! Boundary-layer,leading edge pressure gradient time constant in the expression of Dp. It should be tuned based on airfoil experimental data. [default = 1.7]\n'))
1✔
991
                    f.write(float_default_out(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['T_VL']) + '   {:<11} {:}'.format('T_VL', '! Initial value of the time constant associated with the vortex advection process; it represents the non-dimensional time in semi-chords, needed for a vortex to travel from LE to trailing edge (TE); it is used in the expression of Cvn. It depends on Re, M (weakly), and airfoil. [valid range = 6 - 13, default = 11]\n'))
1✔
992
                    f.write(float_default_out(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['b1']) + '   {:<11} {:}'.format('b1', '! Constant in the expression of phi_alpha^c and phi_q^c.  This value is relatively insensitive for thin airfoils, but may be different for turbine airfoils. [from experimental results, defaults to 0.14]\n'))
1✔
993
                    f.write(float_default_out(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['b2']) + '   {:<11} {:}'.format('b2', '! Constant in the expression of phi_alpha^c and phi_q^c.  This value is relatively insensitive for thin airfoils, but may be different for turbine airfoils. [from experimental results, defaults to 0.53]\n'))
1✔
994
                    f.write(float_default_out(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['b5']) + '   {:<11} {:}'.format('b5', "! Constant in the expression of K'''_q,Cm_q^nc, and k_m,q.  [from  experimental results, defaults to 5]\n"))
1✔
995
                    f.write(float_default_out(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['A1']) + '   {:<11} {:}'.format('A1', '! Constant in the expression of phi_alpha^c and phi_q^c.  This value is relatively insensitive for thin airfoils, but may be different for turbine airfoils. [from experimental results, defaults to 0.3]\n'))
1✔
996
                    f.write(float_default_out(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['A2']) + '   {:<11} {:}'.format('A2', '! Constant in the expression of phi_alpha^c and phi_q^c.  This value is relatively insensitive for thin airfoils, but may be different for turbine airfoils. [from experimental results, defaults to 0.7]\n'))
1✔
997
                    f.write(float_default_out(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['A5']) + '   {:<11} {:}'.format('A5', "! Constant in the expression of K'''_q,Cm_q^nc, and k_m,q. [from experimental results, defaults to 1]\n"))
1✔
998
                    f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['S1'], 'S1', '! Constant in the f curve best-fit for alpha0<=AOA<=alpha1; by definition it depends on the airfoil. [ignored if UAMod<>1]\n'))
1✔
999
                    f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['S2'], 'S2', '! Constant in the f curve best-fit for         AOA> alpha1; by definition it depends on the airfoil. [ignored if UAMod<>1]\n'))
1✔
1000
                    f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['S3'], 'S3', '! Constant in the f curve best-fit for alpha2<=AOA< alpha0; by definition it depends on the airfoil. [ignored if UAMod<>1]\n'))
1✔
1001
                    f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['S4'], 'S4', '! Constant in the f curve best-fit for         AOA< alpha2; by definition it depends on the airfoil. [ignored if UAMod<>1]\n'))
1✔
1002
                    f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['Cn1'], 'Cn1', '! Critical value of C0n at leading edge separation. It should be extracted from airfoil data at a given Mach and Reynolds number. It can be calculated from the static value of Cn at either the break in the pitching moment or the loss of chord force at the onset of stall. It is close to the condition of maximum lift of the airfoil at low Mach numbers.\n'))
1✔
1003
                    f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['Cn2'], 'Cn2', '! As Cn1 for negative AOAs.\n'))
1✔
1004
                    # f.write('{: 22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi]['St_sh'], 'St_sh', "! Strouhal's shedding frequency constant.  [default = 0.19]\n"))
1005
                    f.write(float_default_out(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['St_sh']) + '   {:<11} {:}'.format('St_sh', "! Strouhal's shedding frequency constant.  [default = 0.19]\n"))
1✔
1006
                    f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['Cd0'], 'Cd0', '! 2D drag coefficient value at 0-lift.\n'))
1✔
1007
                    f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['Cm0'], 'Cm0', '! 2D pitching moment coefficient about 1/4-chord location, at 0-lift, positive if nose up. [If the aerodynamics coefficients table does not include a column for Cm, this needs to be set to 0.0]\n'))
1✔
1008
                    f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['k0'], 'k0', '! Constant in the \\hat(x)_cp curve best-fit; = (\\hat(x)_AC-0.25).  [ignored if UAMod<>1]\n'))
1✔
1009
                    f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['k1'], 'k1', '! Constant in the \\hat(x)_cp curve best-fit.  [ignored if UAMod<>1]\n'))
1✔
1010
                    f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['k2'], 'k2', '! Constant in the \\hat(x)_cp curve best-fit.  [ignored if UAMod<>1]\n'))
1✔
1011
                    f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['k3'], 'k3', '! Constant in the \\hat(x)_cp curve best-fit.  [ignored if UAMod<>1]\n'))
1✔
1012
                    f.write('{:<22f}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['k1_hat'], 'k1_hat', '! Constant in the expression of Cc due to leading edge vortex effects.  [ignored if UAMod<>1]\n'))
1✔
1013
                    f.write(float_default_out(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['x_cp_bar']) + '   {:<11} {:}'.format('x_cp_bar', '! Constant in the expression of \\hat(x)_cp^v. [ignored if UAMod<>1, default = 0.2]\n'))
1✔
1014
                    f.write(float_default_out(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['UACutout']) + '   {:<11} {:}'.format('UACutout', '! Angle of attack above which unsteady aerodynamics are disabled (deg). [Specifying the string "Default" sets UACutout to 45 degrees]\n'))
1✔
1015
                    f.write(float_default_out(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['filtCutOff']) + '   {:<11} {:}'.format('filtCutOff', '! Cut-off frequency (-3 dB corner frequency) for low-pass filtering the AoA input to UA, as well as the 1st and 2nd derivatives (Hz) [default = 20]\n'))
1✔
1016

1017
                f.write('!........................................\n')
1✔
1018
                f.write('! Table of aerodynamics coefficients\n')
1✔
1019
                f.write('{:<22d}   {:<11} {:}'.format(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['NumAlf'], 'NumAlf', '! Number of data lines in the following table\n'))
1✔
1020
                f.write('!    Alpha      Cl      Cd        Cm\n')
1✔
1021
                f.write('!    (deg)      (-)     (-)       (-)\n')
1✔
1022

1023
                polar_map = [self.fst_vt['AeroDyn15']['InCol_Alfa'], self.fst_vt['AeroDyn15']['InCol_Cl'], self.fst_vt['AeroDyn15']['InCol_Cd'], self.fst_vt['AeroDyn15']['InCol_Cm'], self.fst_vt['AeroDyn15']['InCol_Cpmin']]
1✔
1024
                polar_map.remove(0)
1✔
1025
                polar_map = [i-1 for i in polar_map]
1✔
1026

1027
                alpha = np.asarray(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['Alpha'])
1✔
1028
                cl = np.asarray(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['Cl'])
1✔
1029
                cd = np.asarray(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['Cd'])
1✔
1030
                cm = np.asarray(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['Cm'])
1✔
1031
                cpmin = np.asarray(self.fst_vt['AeroDyn15']['af_data'][afi][tab]['Cpmin'])
1✔
1032

1033
                if alpha[0] != -180.:
1✔
1034
                    print('Airfoil number ' + str(afi) + ' tab number ' + str(tab) + ' has the min angle of attack different than -180 deg, and equal to ' + str(alpha[0]) + ' deg. This is changed to -180 deg now.')
×
1035
                    alpha[0] = -180.
×
1036
                if alpha[-1] != 180.:
1✔
1037
                    print('Airfoil number ' + str(afi) + ' tab number ' + str(tab) + ' has the max angle of attack different than 180 deg, and equal to ' + str(alpha[0]) + ' deg. This is changed to 180 deg now.')
×
1038
                    alpha[-1] = 180.
×
1039
                if cl[0] != cl[-1]:
1✔
1040
                    print('Airfoil number ' + str(afi) + ' tab number ' + str(tab) + ' has the lift coefficient different between +-180 deg. This is changed to be the same now.')
1✔
1041
                    cl[0] = cl[-1]
1✔
1042
                if cd[0] != cd[-1]:
1✔
1043
                    print('Airfoil number ' + str(afi) + ' tab number ' + str(tab) + ' has the drag coefficient different between +-180 deg. This is changed to be the same now.')
1✔
1044
                    cd[0] = cd[-1]
1✔
1045
                if cm[0] != cm[-1]:
1✔
1046
                    print('Airfoil number ' + str(afi) + ' tab number ' + str(tab) + ' has the moment coefficient different between +-180 deg. This is changed to be the same now.')
1✔
1047
                    cm[0] = cm[-1]
1✔
1048

1049
                if self.fst_vt['AeroDyn15']['InCol_Cm'] == 0:
1✔
1050
                    cm = np.zeros_like(cl)
×
1051
                if self.fst_vt['AeroDyn15']['InCol_Cpmin'] == 0:
1✔
1052
                    cpmin = np.zeros_like(cl)
1✔
1053
                polar = np.column_stack((alpha, cl, cd, cm, cpmin))
1✔
1054
                polar = polar[:,polar_map]
1✔
1055

1056

1057
                for row in polar:
1✔
1058
                    f.write(' '.join(['{: 2.14e}'.format(val) for val in row])+'\n')
1✔
1059
            
1060
            f.flush()
1✔
1061
            os.fsync(f)
1✔
1062
            f.close()
1✔
1063
            
1064
    def write_AeroDyn15Coord(self):
1✔
1065

1066
        self.fst_vt['AeroDyn15']['AFNames_coord'] = ['']*self.fst_vt['AeroDyn15']['NumAFfiles']
1✔
1067
        
1068
        for afi in range(int(self.fst_vt['AeroDyn15']['NumAFfiles'])):
1✔
1069
            self.fst_vt['AeroDyn15']['AFNames_coord'][afi] = os.path.join('Airfoils', self.FAST_namingOut + '_AF%02d_Coords.txt'%afi)
1✔
1070
            
1071
            x     = self.fst_vt['AeroDyn15']['af_coord'][afi]['x']
1✔
1072
            y     = self.fst_vt['AeroDyn15']['af_coord'][afi]['y']
1✔
1073
            coord = np.vstack((x, y)).T
1✔
1074

1075
            af_file = os.path.join(self.FAST_runDirectory, self.fst_vt['AeroDyn15']['AFNames_coord'][afi])
1✔
1076
            f = open(af_file, 'w')
1✔
1077
            
1078
            f.write('{: 22d}   {:<11} {:}'.format(len(x)+1, 'NumCoords', '! The number of coordinates in the airfoil shape file (including an extra coordinate for airfoil reference).  Set to zero if coordinates not included.\n'))
1✔
1079
            f.write('! ......... x-y coordinates are next if NumCoords > 0 .............\n')
1✔
1080
            f.write('! x-y coordinate of airfoil reference\n')
1✔
1081
            f.write('!  x/c        y/c\n')
1✔
1082
            f.write('{: 5f}       0\n'.format(self.fst_vt['AeroDyn15']['ac'][afi]))
1✔
1083
            f.write('! coordinates of airfoil shape\n')
1✔
1084
            f.write('! interpolation to 200 points\n')
1✔
1085
            f.write('!  x/c        y/c\n')
1✔
1086
            for row in coord:
1✔
1087
                f.write(' '.join(['{: 2.14e}'.format(val) for val in row])+'\n')
1✔
1088
            
1089
            f.flush()
1✔
1090
            os.fsync(f)
1✔
1091
            f.close()
1✔
1092

1093
    def write_AeroDyn14(self):
1✔
1094

1095
        # ======= Airfoil Files ========
1096
        # make directory for airfoil files
1097
        if not os.path.isdir(os.path.join(self.FAST_runDirectory,'AeroData')):
×
1098
            try:
×
1099
                os.mkdir(os.path.join(self.FAST_runDirectory,'AeroData'))
×
1100
            except:
×
1101
                try:
×
1102
                    time.sleep(random.random())
×
1103
                    if not os.path.isdir(os.path.join(self.FAST_runDirectory,'AeroData')):
×
1104
                        os.mkdir(os.path.join(self.FAST_runDirectory,'AeroData'))
×
1105
                except:
×
1106
                    print("Error tring to make '%s'!"%os.path.join(self.FAST_runDirectory,'AeroData'))
×
1107

1108
        # create write airfoil objects to files
1109
        for i in range(self.fst_vt['AeroDyn14']['NumFoil']):
×
1110
             af_name = os.path.join(self.FAST_runDirectory, 'AeroData', 'Airfoil' + str(i) + '.dat')
×
1111
             self.fst_vt['AeroDyn14']['FoilNm'][i]  = os.path.join('AeroData', 'Airfoil' + str(i) + '.dat')
×
1112
             self.write_AeroDyn14Polar(af_name, i)
×
1113

1114
        self.fst_vt['Fst']['AeroFile'] = self.FAST_namingOut + '_AeroDyn14.dat'
×
1115
        ad_file = os.path.join(self.FAST_runDirectory,self.fst_vt['Fst']['AeroFile'])
×
1116
        f = open(ad_file,'w')
×
1117

1118
        # create Aerodyn Tower
1119
        if self.fst_vt['AeroDyn14']['TwrShad'] > 0:
×
1120
            self.write_AeroDyn14Tower()
×
1121

1122
        # ======= Aerodyn Input File ========
1123
        f.write('AeroDyn v14.04.* INPUT FILE\n\n')
×
1124
        
1125
        # f.write('{:}\n'.format(self.fst_vt['aerodyn']['SysUnits']))
1126
        f.write('{:}\n'.format(self.fst_vt['AeroDyn14']['StallMod']))        
×
1127
        
1128
        f.write('{:}\n'.format(self.fst_vt['AeroDyn14']['UseCm']))
×
1129
        f.write('{:}\n'.format(self.fst_vt['AeroDyn14']['InfModel']))
×
1130
        f.write('{:}\n'.format(self.fst_vt['AeroDyn14']['IndModel']))
×
1131
        f.write('{: 2.15e}\n'.format(self.fst_vt['AeroDyn14']['AToler']))
×
1132
        f.write('{:}\n'.format(self.fst_vt['AeroDyn14']['TLModel']))
×
1133
        f.write('{:}\n'.format(self.fst_vt['AeroDyn14']['HLModel']))
×
1134
        f.write('{:}\n'.format(self.fst_vt['AeroDyn14']['TwrShad']))  
×
1135
        if self.fst_vt['AeroDyn14']['TwrShad'] > 0:
×
1136
            f.write('{:}\n'.format(self.fst_vt['AeroDyn14']['TwrPotent']))  
×
1137
            f.write('{:}\n'.format(self.fst_vt['AeroDyn14']['TwrShadow']))
×
1138
            f.write('{:}\n'.format(self.fst_vt['AeroDyn14']['TwrFile']))
×
1139
            f.write('{:}\n'.format(self.fst_vt['AeroDyn14']['CalcTwrAero']))  
×
1140
        else:
1141
            f.write('{: 2.15e}\n'.format(self.fst_vt['AeroDyn14']['ShadHWid']))
×
1142
            f.write('{: 2.15e}\n'.format(self.fst_vt['AeroDyn14']['T_Shad_Refpt']))
×
1143
  
1144
        f.write('{: 2.15e}\n'.format(self.fst_vt['AeroDyn14']['AirDens']))  
×
1145
  
1146
        f.write('{: 2.15e}\n'.format(self.fst_vt['AeroDyn14']['KinVisc']))  
×
1147
  
1148
        f.write('{:2}\n'.format(self.fst_vt['AeroDyn14']['DTAero']))        
×
1149
        
1150

1151
        f.write('{:2}\n'.format(self.fst_vt['AeroDyn14']['NumFoil']))
×
1152
        for i in range (self.fst_vt['AeroDyn14']['NumFoil']):
×
1153
            f.write('"{:}"\n'.format(self.fst_vt['AeroDyn14']['FoilNm'][i]))
×
1154

1155
        f.write('{:2}\n'.format(self.fst_vt['AeroDynBlade']['BldNodes']))
×
1156
        rnodes = self.fst_vt['AeroDynBlade']['RNodes']
×
1157
        twist = self.fst_vt['AeroDynBlade']['AeroTwst']
×
1158
        drnodes = self.fst_vt['AeroDynBlade']['DRNodes']
×
1159
        chord = self.fst_vt['AeroDynBlade']['Chord']
×
1160
        nfoil = self.fst_vt['AeroDynBlade']['NFoil']
×
1161
        prnelm = self.fst_vt['AeroDynBlade']['PrnElm']
×
1162
        f.write('Nodal properties\n')
×
1163
        for r, t, dr, c, a, p in zip(rnodes, twist, drnodes, chord, nfoil, prnelm):
×
1164
            f.write('{: 2.15e}\t{: 2.15e}\t{: 2.15e}\t{: 2.15e}\t{:5}\t{:}\n'.format(r, t, dr, c, a, p))
×
1165

1166
        f.flush()
×
1167
        os.fsync(f)
×
1168
        f.close()        
×
1169

1170
    def write_AeroDyn14Tower(self):
1✔
1171
        # AeroDyn v14.04 Tower
1172
        self.fst_vt['AeroDyn14']['TwrFile'] = self.FAST_namingOut + '_AeroDyn14_tower.dat'
×
1173
        filename = os.path.join(self.FAST_runDirectory, self.fst_vt['AeroDyn14']['TwrFile'])
×
1174
        f = open(filename, 'w')
×
1175

1176
        f.write('AeroDyn tower file, Aerodyn v14.04 formatting\n')
×
1177
        f.write('Generated with AeroElasticSE FAST driver\n')
×
1178
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDynTower']['NTwrHt'], 'NTwrHt', '- Number of tower input height stations listed (-)\n'))
×
1179
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDynTower']['NTwrRe'], 'NTwrRe', '- Number of tower Re values (-)\n'))
×
1180
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDynTower']['NTwrCD'], 'NTwrCD', '- Number of tower CD columns (-) Note: For current versions, this MUST be 1\n'))
×
1181
        f.write('{: 2.15e} {:<11} {:}'.format(self.fst_vt['AeroDynTower']['Tower_Wake_Constant'], 'Tower_Wake_Constant', '- Tower wake constant (-) {0.0: full potential flow, 0.1: Bak model}\n'))
×
1182
        f.write('---------------------- DISTRIBUTED TOWER PROPERTIES ----------------------------\n')
×
1183
        f.write('TwrHtFr  TwrWid  NTwrCDCol\n')
×
1184
        for HtFr, Wid, CDId in zip(self.fst_vt['AeroDynTower']['TwrHtFr'], self.fst_vt['AeroDynTower']['TwrWid'], self.fst_vt['AeroDynTower']['NTwrCDCol']):
×
1185
            f.write('{: 2.15e}  {: 2.15e}   {:d}\n'.format(HtFr, Wid, int(CDId)))
×
1186
        f.write('---------------------- Re v CD PROPERTIES --------------------------------------\n')
×
1187
        f.write('TwrRe  '+ '  '.join(['TwrCD%d'%(i+1) for i in range(self.fst_vt['AeroDynTower']['NTwrCD'])]) +'\n')
×
1188
        for Re, CD in zip(self.fst_vt['AeroDynTower']['TwrRe'], self.fst_vt['AeroDynTower']['TwrCD']):
×
1189
            f.write('% 2.15e' %Re + '   '.join(['% 2.15e'%cdi for cdi in CD]) + '\n')
×
1190
        
1191
        f.flush()
×
1192
        os.fsync(f)
×
1193
        f.close()
×
1194

1195
    def write_AeroDyn14Polar(self, filename, a_i):
1✔
1196
        # AeroDyn v14 Airfoil Polar Input File
1197

1198
        f = open(filename, 'w')
×
1199
        f.write('AeroDyn airfoil file, Aerodyn v14.04 formatting\n')
×
1200
        f.write('Generated with AeroElasticSE FAST driver\n')
×
1201

1202
        f.write('{:9d}\t{:}'.format(self.fst_vt['AeroDynBlade']['af_data'][a_i]['number_tables'], 'Number of airfoil tables in this file\n'))
×
1203
        for i in range(self.fst_vt['AeroDynBlade']['af_data'][a_i]['number_tables']):
×
1204
            param = self.fst_vt['AeroDynBlade']['af_data'][a_i]['af_tables'][i]
×
1205
            f.write('{:9g}\t{:}'.format(i, 'Table ID parameter\n'))
×
1206
            f.write('{: f}\t{:}'.format(param['StallAngle'], 'Stall angle (deg)\n'))
×
1207
            f.write('{: f}\t{:}'.format(0, 'No longer used, enter zero\n'))
×
1208
            f.write('{: f}\t{:}'.format(0, 'No longer used, enter zero\n'))
×
1209
            f.write('{: f}\t{:}'.format(0, 'No longer used, enter zero\n'))
×
1210
            f.write('{: f}\t{:}'.format(param['ZeroCn'], 'Angle of attack for zero Cn for linear Cn curve (deg)\n'))
×
1211
            f.write('{: f}\t{:}'.format(param['CnSlope'], 'Cn slope for zero lift for linear Cn curve (1/rad)\n'))
×
1212
            f.write('{: f}\t{:}'.format(param['CnPosStall'], 'Cn at stall value for positive angle of attack for linear Cn curve\n'))
×
1213
            f.write('{: f}\t{:}'.format(param['CnNegStall'], 'Cn at stall value for negative angle of attack for linear Cn curve\n'))
×
1214
            f.write('{: f}\t{:}'.format(param['alphaCdMin'], 'Angle of attack for minimum CD (deg)\n'))
×
1215
            f.write('{: f}\t{:}'.format(param['CdMin'], 'Minimum CD value\n'))
×
1216
            if param['cm']:
×
1217
                for a, cl, cd, cm in zip(param['alpha'], param['cl'], param['cd'], param['cm']):
×
1218
                    f.write('{: 6e}  {: 6e}  {: 6e}  {: 6e}\n'.format(a, cl, cd, cm))
×
1219
            else:
1220
                for a, cl, cd in zip(param['alpha'], param['cl'], param['cd']):
×
1221
                    f.write('{: 6e}  {: 6e}  {: 6e}\n'.format(a, cl, cd))
×
1222
        
1223
        f.flush()
×
1224
        os.fsync(f)
×
1225
        f.close()
×
1226

1227
    def write_OLAF(self):
1✔
1228

1229
        olaf_file = os.path.join(self.FAST_runDirectory, self.FAST_namingOut + '_OLAF.dat')
×
1230
        f = open(olaf_file, 'w')
×
1231
        
1232
        f.write('--------------------------- OLAF (cOnvecting LAgrangian Filaments) INPUT FILE -----------------\n')
×
1233
        f.write('Generated by WEIS\n')
×
1234
        f.write('--------------------------- GENERAL OPTIONS ---------------------------------------------------\n')
×
1235
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['IntMethod'], 'IntMethod', '- Integration method {1: RK4, 5: Forward Euler 1st order, default: 5} (switch)\n'))
×
1236
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['DTfvw'], 'DTfvw', '- Time interval for wake propagation. {default: dtaero} (s)\n'))
×
1237
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['FreeWakeStart'], 'FreeWakeStart', '- Time when wake is free. (-) value = always free. {default: 0.0} (s)\n'))
×
1238
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['FullCircStart'], 'FullCircStart', '- Time at which full circulation is reached. {default: 0.0} (s)\n'))
×
1239
        f.write('--------------------------- CIRCULATION SPECIFICATIONS ----------------------------------------\n')
×
1240
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['CircSolvMethod'], 'CircSolvingMethod', '- Circulation solving method {1: Cl-Based, 2: No-Flow Through, 3: Prescribed, default: 1 }(switch)\n'))
×
1241
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['CircSolvConvCrit'], 'CircSolvConvCrit', ' - Convergence criteria {default: 0.001} [only if CircSolvMethod=1] (-)\n'))
×
1242
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['CircSolvRelaxation'], 'CircSolvRelaxation', '- Relaxation factor {default: 0.1} [only if CircSolvMethod=1] (-)\n'))
×
1243
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['CircSolvMaxIter'], 'CircSolvMaxIter', ' - Maximum number of iterations for circulation solving {default: 30} (-)\n'))
×
1244
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['PrescribedCircFile'], 'PrescribedCircFile','- File containing prescribed circulation [only if CircSolvMethod=3] (quoted string)\n'))
×
1245
        f.write('===============================================================================================\n')
×
1246
        f.write('--------------------------- WAKE OPTIONS ------------------------------------------------------\n')
×
1247
        f.write('------------------- WAKE EXTENT AND DISCRETIZATION --------------------------------------------\n')
×
1248
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['nNWPanels'], 'nNWPanels','- Number of near-wake panels (-)\n'))
×
1249
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['nNWPanelsFree'], 'nNWPanelsFree','- Number of free near-wake panels (-) {default: nNWPanels}\n'))
×
1250
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['nFWPanels'], 'nFWPanels','- Number of far-wake panels (-) {default: 0}\n'))
×
1251
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['nFWPanelsFree'], 'nFWPanelsFree','- Number of free far-wake panels (-) {default: nFWPanels}\n'))
×
1252
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['FWShedVorticity'], 'FWShedVorticity','- Include shed vorticity in the far wake {default: False}\n'))
×
1253
        f.write('------------------- WAKE REGULARIZATIONS AND DIFFUSION -----------------------------------------\n')
×
1254
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['DiffusionMethod'], 'DiffusionMethod','- Diffusion method to account for viscous effects {0: None, 1: Core Spreading, "default": 0}\n'))
×
1255
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['RegDeterMethod'], 'RegDeterMethod','- Method to determine the regularization parameters {0:  Manual, 1: Optimized, 2: Chord, 3: Span, default: 0 }\n'))
×
1256
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['RegFunction'], 'RegFunction','- Viscous diffusion function {0: None, 1: Rankine, 2: LambOseen, 3: Vatistas, 4: Denominator, "default": 3} (switch)\n'))
×
1257
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['WakeRegMethod'], 'WakeRegMethod','- Wake regularization method {1: Constant, 2: Stretching, 3: Age, default: 3} (switch)\n'))
×
1258
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['WakeRegFactor'], 'WakeRegFactor','- Wake regularization factor (m)\n'))
×
1259
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['WingRegFactor'], 'WingRegFactor','- Wing regularization factor (m)\n'))
×
1260
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['CoreSpreadEddyVisc'], 'CoreSpreadEddyVisc','- Eddy viscosity in core spreading methods, typical values 1-1000\n'))
×
1261
        f.write('------------------- WAKE TREATMENT OPTIONS ---------------------------------------------------\n')
×
1262
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['TwrShadowOnWake'], 'TwrShadowOnWake','- Include tower flow disturbance effects on wake convection {default:false} [only if TwrPotent or TwrShadow]\n'))
×
1263
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['ShearModel'], 'ShearModel','- Shear Model {0: No treatment, 1: Mirrored vorticity, default: 0}\n'))
×
1264
        f.write('------------------- SPEEDUP OPTIONS -----------------------------------------------------------\n')
×
1265
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['VelocityMethod'], 'VelocityMethod','- Method to determine the velocity {1:Segment N^2, 2:Particle tree, 3:Particle N^2, 4:Segment tree, default: 2}\n'))
×
1266
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['TreeBranchFactor'], 'TreeBranchFactor','- Branch radius fraction above which a multipole calculation is used {default: 1.5} [only if VelocityMethod=2,4]\n'))
×
1267
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['PartPerSegment'], 'PartPerSegment','- Number of particles per segment {default: 1} [only if VelocityMethod=2,3]\n'))
×
1268
        f.write('===============================================================================================\n')
×
1269
        f.write('--------------------------- OUTPUT OPTIONS  ---------------------------------------------------\n')
×
1270
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['WrVTk'], 'WrVTk','- Outputs Visualization Toolkit (VTK) (independent of .fst option) {0: NoVTK, 1: Write VTK at VTK_fps, 2: Write VTK at init and final, default: 0} (flag)\n'))
×
1271
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['nVTKBlades'], 'nVTKBlades','- Number of blades for which VTK files are exported {0: No VTK per blade, n: VTK for blade 1 to n, default: 0} (-) \n'))
×
1272
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['VTKCoord'], 'VTKCoord','- Coordinate system used for VTK export. {1: Global, 2: Hub, 3: Both, default: 1} \n'))
×
1273
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['VTK_fps'], 'VTK_fps','- Frame rate for VTK output (frames per second) {"all" for all glue code timesteps, "default" for all OLAF timesteps} [only if WrVTK=1]\n'))
×
1274
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['nGridOut'], 'nGridOut','- Number of grid outputs\n'))
×
1275
        f.write('GridName  GridType  TStart   TEnd    DTGrid   XStart  XEnd   nX   YStart   YEnd   nY   ZStart   ZEnd   nZ\n')
×
1276
        f.write('(-)         (-)      (s)     (s)      (s)       (m)    (m)   (-)   (m)     (m)    (-)   (m)     (m)    (-)\n')
×
1277
        f.write('===============================================================================================\n')
×
1278
        f.write('--------------------------- ADVANCED OPTIONS --------------------------------------------------\n')
×
1279
        f.write('===============================================================================================\n')
×
1280

1281
        f.flush()
×
1282
        os.fsync(f)
×
1283
        f.close()
×
1284
    
1285
    def write_ServoDyn(self):
1✔
1286
        # ServoDyn v1.05 Input File
1287

1288
        self.fst_vt['Fst']['ServoFile'] = self.FAST_namingOut + '_ServoDyn.dat'
1✔
1289
        sd_file = os.path.join(self.FAST_runDirectory,self.fst_vt['Fst']['ServoFile'])
1✔
1290
        f = open(sd_file,'w')
1✔
1291

1292
        f.write('------- SERVODYN v1.05.* INPUT FILE --------------------------------------------\n')
1✔
1293
        f.write('Generated with AeroElasticSE FAST driver\n')
1✔
1294
        f.write('---------------------- SIMULATION CONTROL --------------------------------------\n')
1✔
1295
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['Echo'], 'Echo', '- Echo input data to <RootName>.ech (flag)\n'))
1✔
1296
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['DT'], 'DT', '- Communication interval for controllers (s) (or "default")\n'))
1✔
1297
        f.write('---------------------- PITCH CONTROL -------------------------------------------\n')
1✔
1298
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['PCMode'], 'PCMode', '- Pitch control mode {0: none, 3: user-defined from routine PitchCntrl, 4: user-defined from Simulink/Labview, 5: user-defined from Bladed-style DLL} (switch)\n'))
1✔
1299
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['TPCOn'], 'TPCOn', '- Time to enable active pitch control (s) [unused when PCMode=0]\n'))
1✔
1300
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['TPitManS1'], 'TPitManS(1)', '- Time to start override pitch maneuver for blade 1 and end standard pitch control (s)\n'))
1✔
1301
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['TPitManS2'], 'TPitManS(2)', '- Time to start override pitch maneuver for blade 2 and end standard pitch control (s)\n'))
1✔
1302
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['TPitManS3'], 'TPitManS(3)', '- Time to start override pitch maneuver for blade 3 and end standard pitch control (s) [unused for 2 blades]\n'))
1✔
1303
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['PitManRat(1)'], 'PitManRat(1)', '- Pitch rate at which override pitch maneuver heads toward final pitch angle for blade 1 (deg/s)\n'))
1✔
1304
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['PitManRat(2)'], 'PitManRat(2)', '- Pitch rate at which override pitch maneuver heads toward final pitch angle for blade 2 (deg/s)\n'))
1✔
1305
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['PitManRat(3)'], 'PitManRat(3)', '- Pitch rate at which override pitch maneuver heads toward final pitch angle for blade 3 (deg/s) [unused for 2 blades]\n'))
1✔
1306
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['BlPitchF(1)'], 'BlPitchF(1)', '- Blade 1 final pitch for pitch maneuvers (degrees)\n'))
1✔
1307
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['BlPitchF(2)'], 'BlPitchF(2)', '- Blade 2 final pitch for pitch maneuvers (degrees)\n'))
1✔
1308
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['BlPitchF(3)'], 'BlPitchF(3)', '- Blade 3 final pitch for pitch maneuvers (degrees) [unused for 2 blades]\n'))
1✔
1309
        f.write('---------------------- GENERATOR AND TORQUE CONTROL ----------------------------\n')
1✔
1310
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['VSContrl'], 'VSContrl', '- Variable-speed control mode {0: none, 1: simple VS, 3: user-defined from routine UserVSCont, 4: user-defined from Simulink/Labview, 5: user-defined from Bladed-style DLL} (switch)\n'))
1✔
1311
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['GenModel'], 'GenModel', '- Generator model {1: simple, 2: Thevenin, 3: user-defined from routine UserGen} (switch) [used only when VSContrl=0]\n'))
1✔
1312
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['GenEff'], 'GenEff', '- Generator efficiency [ignored by the Thevenin and user-defined generator models] (%)\n'))
1✔
1313
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['GenTiStr'], 'GenTiStr', '- Method to start the generator {T: timed using TimGenOn, F: generator speed using SpdGenOn} (flag)\n'))
1✔
1314
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['GenTiStp'], 'GenTiStp', '- Method to stop the generator {T: timed using TimGenOf, F: when generator power = 0} (flag)\n'))
1✔
1315
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['SpdGenOn'], 'SpdGenOn', '- Generator speed to turn on the generator for a startup (HSS speed) (rpm) [used only when GenTiStr=False]\n'))
1✔
1316
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['TimGenOn'], 'TimGenOn', '- Time to turn on the generator for a startup (s) [used only when GenTiStr=True]\n'))
1✔
1317
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['TimGenOf'], 'TimGenOf', '- Time to turn off the generator (s) [used only when GenTiStp=True]\n'))
1✔
1318
        f.write('---------------------- SIMPLE VARIABLE-SPEED TORQUE CONTROL --------------------\n')
1✔
1319
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['VS_RtGnSp'], 'VS_RtGnSp', '- Rated generator speed for simple variable-speed generator control (HSS side) (rpm) [used only when VSContrl=1]\n'))
1✔
1320
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['VS_RtTq'], 'VS_RtTq', '- Rated generator torque/constant generator torque in Region 3 for simple variable-speed generator control (HSS side) (N-m) [used only when VSContrl=1]\n'))
1✔
1321
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['VS_Rgn2K'], 'VS_Rgn2K', '- Generator torque constant in Region 2 for simple variable-speed generator control (HSS side) (N-m/rpm^2) [used only when VSContrl=1]\n'))
1✔
1322
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['VS_SlPc'], 'VS_SlPc', '- Rated generator slip percentage in Region 2 1/2 for simple variable-speed generator control (%) [used only when VSContrl=1]\n'))
1✔
1323
        f.write('---------------------- SIMPLE INDUCTION GENERATOR ------------------------------\n')
1✔
1324
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['SIG_SlPc'], 'SIG_SlPc', '- Rated generator slip percentage (%) [used only when VSContrl=0 and GenModel=1]\n'))
1✔
1325
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['SIG_SySp'], 'SIG_SySp', '- Synchronous (zero-torque) generator speed (rpm) [used only when VSContrl=0 and GenModel=1]\n'))
1✔
1326
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['SIG_RtTq'], 'SIG_RtTq', '- Rated torque (N-m) [used only when VSContrl=0 and GenModel=1]\n'))
1✔
1327
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['SIG_PORt'], 'SIG_PORt', '- Pull-out ratio (Tpullout/Trated) (-) [used only when VSContrl=0 and GenModel=1]\n'))
1✔
1328
        f.write('---------------------- THEVENIN-EQUIVALENT INDUCTION GENERATOR -----------------\n')
1✔
1329
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['TEC_Freq'], 'TEC_Freq', '- Line frequency [50 or 60] (Hz) [used only when VSContrl=0 and GenModel=2]\n'))
1✔
1330
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['TEC_NPol'], 'TEC_NPol', '- Number of poles [even integer > 0] (-) [used only when VSContrl=0 and GenModel=2]\n'))
1✔
1331
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['TEC_SRes'], 'TEC_SRes', '- Stator resistance (ohms) [used only when VSContrl=0 and GenModel=2]\n'))
1✔
1332
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['TEC_RRes'], 'TEC_RRes', '- Rotor resistance (ohms) [used only when VSContrl=0 and GenModel=2]\n'))
1✔
1333
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['TEC_VLL'], 'TEC_VLL', '- Line-to-line RMS voltage (volts) [used only when VSContrl=0 and GenModel=2]\n'))
1✔
1334
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['TEC_SLR'], 'TEC_SLR', '- Stator leakage reactance (ohms) [used only when VSContrl=0 and GenModel=2]\n'))
1✔
1335
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['TEC_RLR'], 'TEC_RLR', '- Rotor leakage reactance (ohms) [used only when VSContrl=0 and GenModel=2]\n'))
1✔
1336
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['TEC_MR'], 'TEC_MR', '- Magnetizing reactance (ohms) [used only when VSContrl=0 and GenModel=2]\n'))
1✔
1337
        f.write('---------------------- HIGH-SPEED SHAFT BRAKE ----------------------------------\n')
1✔
1338
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['HSSBrMode'], 'HSSBrMode', '- HSS brake model {0: none, 1: simple, 3: user-defined from routine UserHSSBr, 4: user-defined from Simulink/Labview, 5: user-defined from Bladed-style DLL} (switch)\n'))
1✔
1339
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['THSSBrDp'], 'THSSBrDp', '- Time to initiate deployment of the HSS brake (s)\n'))
1✔
1340
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['HSSBrDT'], 'HSSBrDT', '- Time for HSS-brake to reach full deployment once initiated (sec) [used only when HSSBrMode=1]\n'))
1✔
1341
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['HSSBrTqF'], 'HSSBrTqF', '- Fully deployed HSS-brake torque (N-m)\n'))
1✔
1342
        f.write('---------------------- NACELLE-YAW CONTROL -------------------------------------\n')
1✔
1343
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['YCMode'], 'YCMode', '- Yaw control mode {0: none, 3: user-defined from routine UserYawCont, 4: user-defined from Simulink/Labview, 5: user-defined from Bladed-style DLL} (switch)\n'))
1✔
1344
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['TYCOn'], 'TYCOn', '- Time to enable active yaw control (s) [unused when YCMode=0]\n'))
1✔
1345
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['YawNeut'], 'YawNeut', '- Neutral yaw position--yaw spring force is zero at this yaw (degrees)\n'))
1✔
1346
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['YawSpr'], 'YawSpr', '- Nacelle-yaw spring constant (N-m/rad)\n'))
1✔
1347
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['YawDamp'], 'YawDamp', '- Nacelle-yaw damping constant (N-m/(rad/s))\n'))
1✔
1348
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['TYawManS'], 'TYawManS', '- Time to start override yaw maneuver and end standard yaw control (s)\n'))
1✔
1349
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['YawManRat'], 'YawManRat', '- Yaw maneuver rate (in absolute value) (deg/s)\n'))
1✔
1350
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['NacYawF'], 'NacYawF', '- Final yaw angle for override yaw maneuvers (degrees)\n'))
1✔
1351
        f.write('---------------------- Aerodynamic Flow Control -------------------------------------\n')
1✔
1352
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['AfCmode'], 'AfCmode', '- Airfoil control mode {0- none, 1- cosine wave cycle, 4- user-defined from Simulink/Labview, 5- user-defined from Bladed-style DLL}\n'))
1✔
1353
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['AfC_Mean'], 'AfC_Mean', '- Mean level for sinusoidal cycling or steady value (-) [used only with AfCmode==1]\n'))
1✔
1354
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['AfC_Amp'], 'AfC_Amp', '- Amplitude for for cosine cycling of flap signal (AfC = AfC_Amp*cos(Azimuth+phase)+AfC_mean) (-) [used only with AfCmode==1]\n'))
1✔
1355
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['AfC_Phase'], 'AfC_phase', '- Phase relative to the blade azimuth (0 is vertical) for for cosine cycling of flap signal (deg) [used only with AfCmode==1]\n'))
1✔
1356
        f.write('---------------------- STRUCTURAL CONTROL ---------------------------------------\n')
1✔
1357
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['NumBStC'], 'NumBStC', '- Number of blade structural controllers (integer)\n'))
1✔
1358
        f.write('{!s:<22} {:<11} {:}'.format('"' + '" "'.join(self.fst_vt['ServoDyn']['BStCfiles']) + '"', 'BStCfiles', '- Name of the file for blade tuned mass damper (quoted string) [unused when CompNTMD is false]\n'))
1✔
1359
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['NumNStC'], 'NumNStC', '- Number of nacelle structural controllers (integer)\n'))
1✔
1360
        f.write('{!s:<22} {:<11} {:}'.format('"' + '" "'.join(self.fst_vt['ServoDyn']['NStCfiles']) + '"', 'NStCfiles', '- Name of the file for nacelle tuned mass damper (quoted string) [unused when CompNTMD is false]\n'))
1✔
1361
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['NumTStC'], 'NumTStC', '- Number of tower structural controllers (integer)\n'))
1✔
1362
        f.write('{!s:<22} {:<11} {:}'.format('"' + '" "'.join(self.fst_vt['ServoDyn']['TStCfiles']) + '"', 'TStCfiles', '- Name of the file for tower tuned mass damper (quoted string) [unused when CompNTMD is false]\n'))
1✔
1363
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['NumSStC'], 'NumSStC', '- Number of sbustructure structural controllers (integer)\n'))
1✔
1364
        f.write('{!s:<22} {:<11} {:}'.format('"' + '" "'.join(self.fst_vt['ServoDyn']['SStCfiles']) + '"', 'SStCfiles', '- Name of the file for sbustructure tuned mass damper (quoted string) [unused when CompNTMD is false]\n'))
1✔
1365
        f.write('---------------------- CABLE CONTROL ---------------------------------------- \n')
1✔
1366
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['CCmode'], 'CCmode', '- Cable control mode {0- none, 4- user-defined from Simulink/Labview, 5- user-defineAfC_phased from Bladed-style DLL}\n'))
1✔
1367
        f.write('---------------------- BLADED INTERFACE ---------------------------------------- [used only with Bladed Interface]\n')
1✔
1368
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['ServoDyn']['DLL_FileName']+'"', 'DLL_FileName', '- Name/location of the dynamic library {.dll [Windows] or .so [Linux]} in the Bladed-DLL format (-) [used only with Bladed Interface]\n'))
1✔
1369
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['ServoDyn']['DLL_InFile']+'"', 'DLL_InFile', '- Name of input file sent to the DLL (-) [used only with Bladed Interface]\n'))
1✔
1370
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['ServoDyn']['DLL_ProcName']+'"', 'DLL_ProcName', '- Name of procedure in DLL to be called (-) [case sensitive; used only with DLL Interface]\n'))
1✔
1371
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['DLL_DT'], 'DLL_DT', '- Communication interval for dynamic library (s) (or "default") [used only with Bladed Interface]\n'))
1✔
1372
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['DLL_Ramp'], 'DLL_Ramp', '- Whether a linear ramp should be used between DLL_DT time steps [introduces time shift when true] (flag) [used only with Bladed Interface]\n'))
1✔
1373
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['BPCutoff'], 'BPCutoff', '- Cuttoff frequency for low-pass filter on blade pitch from DLL (Hz) [used only with Bladed Interface]\n'))
1✔
1374
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['NacYaw_North'], 'NacYaw_North', '- Reference yaw angle of the nacelle when the upwind end points due North (deg) [used only with Bladed Interface]\n'))
1✔
1375
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['Ptch_Cntrl'], 'Ptch_Cntrl', '- Record 28: Use individual pitch control {0: collective pitch; 1: individual pitch control} (switch) [used only with Bladed Interface]\n'))
1✔
1376
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['Ptch_SetPnt'], 'Ptch_SetPnt', '- Record  5: Below-rated pitch angle set-point (deg) [used only with Bladed Interface]\n'))
1✔
1377
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['Ptch_Min'], 'Ptch_Min', '- Record  6: Minimum pitch angle (deg) [used only with Bladed Interface]\n'))
1✔
1378
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['Ptch_Max'], 'Ptch_Max', '- Record  7: Maximum pitch angle (deg) [used only with Bladed Interface]\n'))
1✔
1379
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['PtchRate_Min'], 'PtchRate_Min', '- Record  8: Minimum pitch rate (most negative value allowed) (deg/s) [used only with Bladed Interface]\n'))
1✔
1380
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['PtchRate_Max'], 'PtchRate_Max', '- Record  9: Maximum pitch rate  (deg/s) [used only with Bladed Interface]\n'))
1✔
1381
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['Gain_OM'], 'Gain_OM', '- Record 16: Optimal mode gain (Nm/(rad/s)^2) [used only with Bladed Interface]\n'))
1✔
1382
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['GenSpd_MinOM'], 'GenSpd_MinOM', '- Record 17: Minimum generator speed (rpm) [used only with Bladed Interface]\n'))
1✔
1383
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['GenSpd_MaxOM'], 'GenSpd_MaxOM', '- Record 18: Optimal mode maximum speed (rpm) [used only with Bladed Interface]\n'))
1✔
1384
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['GenSpd_Dem'], 'GenSpd_Dem', '- Record 19: Demanded generator speed above rated (rpm) [used only with Bladed Interface]\n'))
1✔
1385
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['GenTrq_Dem'], 'GenTrq_Dem', '- Record 22: Demanded generator torque above rated (Nm) [used only with Bladed Interface]\n'))
1✔
1386
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['GenPwr_Dem'], 'GenPwr_Dem', '- Record 13: Demanded power (W) [used only with Bladed Interface]\n'))
1✔
1387
        f.write('---------------------- BLADED INTERFACE TORQUE-SPEED LOOK-UP TABLE -------------\n')
1✔
1388
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['DLL_NumTrq'], 'DLL_NumTrq', '- Record 26: No. of points in torque-speed look-up table {0 = none and use the optimal mode parameters; nonzero = ignore the optimal mode PARAMETERs by setting Record 16 to 0.0} (-) [used only with Bladed Interface]\n'))
1✔
1389
        f.write('{:<22}\t{:<22}\n'.format("GenSpd_TLU", "GenTrq_TLU"))
1✔
1390
        f.write('{:<22}\t{:<22}\n'.format("(rpm)", "(Nm)"))
1✔
1391
        for i in range(self.fst_vt['ServoDyn']['DLL_NumTrq']):
1✔
1392
            a1 = self.fst_vt['ServoDyn']['GenSpd_TLU'][i]
×
1393
            a2 = self.fst_vt['ServoDyn']['GenTrq_TLU'][i]
×
1394
            f.write('{:<22}\t{:<22}\n'.format(a1, a2))
×
1395
        f.write('---------------------- OUTPUT --------------------------------------------------\n')
1✔
1396
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['SumPrint'], 'SumPrint', '- Print summary data to <RootName>.sum (flag) (currently unused)\n'))
1✔
1397
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['OutFile'], 'OutFile', '- Switch to determine where output will be placed: {1: in module output file only; 2: in glue code output file only; 3: both} (currently unused)\n'))
1✔
1398
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['TabDelim'], 'TabDelim', '- Use tab delimiters in text tabular output file? (flag) (currently unused)\n'))
1✔
1399
        f.write('{:<22} {:<11} {:}'.format('"'+self.fst_vt['ServoDyn']['OutFmt']+'"', 'OutFmt', '- Format used for text tabular output (except time).  Resulting field should be 10 characters. (quoted string) (currently unused)\n'))
1✔
1400
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['ServoDyn']['TStart'], 'TStart', '- Time to begin tabular output (s) (currently unused)\n'))
1✔
1401
        f.write('              OutList      - The next line(s) contains a list of output parameters.  See OutListParameters.xlsx for a listing of available output channels, (-)\n')
1✔
1402
        
1403
        outlist = self.get_outlist(self.fst_vt['outlist'], ['ServoDyn'])
1✔
1404
        for channel_list in outlist:
1✔
1405
            for i in range(len(channel_list)):
1✔
1406
                f.write('"' + channel_list[i] + '"\n')
1✔
1407

1408
        f.write('END of input file (the word "END" must appear in the first 3 columns of this last OutList line)\n')
1✔
1409
        f.write('---------------------------------------------------------------------------------------\n')
1✔
1410

1411
        f.flush()
1✔
1412
        os.fsync(f)
1✔
1413
        f.close()
1✔
1414

1415
    def write_DISCON_in(self):
1✔
1416
        # Generate Bladed style Interface controller input file, intended for ROSCO https://github.com/NREL/rosco.toolbox
1417

1418
        # Fill controller and turbine objects for ROSCO 
1419
        # - controller
1420
        controller = type('', (), {})()
1✔
1421
        
1422
        turbine = type('', (), {})()
1✔
1423
        turbine.Cp = type('', (), {})()
1✔
1424
        turbine.Ct = type('', (), {})()
1✔
1425
        turbine.Cq = type('', (), {})()
1✔
1426
        turbine.v_rated                 = self.fst_vt['DISCON_in']['v_rated']
1✔
1427
        turbine.Cp                      = self.fst_vt['DISCON_in']['Cp']
1✔
1428
        turbine.Ct                      = self.fst_vt['DISCON_in']['Ct']
1✔
1429
        turbine.Cq                      = self.fst_vt['DISCON_in']['Cq']
1✔
1430
        turbine.Cp_table                = self.fst_vt['DISCON_in']['Cp_table']
1✔
1431
        turbine.Ct_table                = self.fst_vt['DISCON_in']['Ct_table']
1✔
1432
        turbine.Cq_table                = self.fst_vt['DISCON_in']['Cq_table']
1✔
1433
        turbine.pitch_initial_rad       = self.fst_vt['DISCON_in']['Cp_pitch_initial_rad']
1✔
1434
        turbine.TSR_initial             = self.fst_vt['DISCON_in']['Cp_TSR_initial']
1✔
1435
        turbine.TurbineName             = 'WEIS Turbine'
1✔
1436

1437
        # Define DISCON infile paths
1438
        self.fst_vt['ServoDyn']['DLL_InFile'] = self.FAST_namingOut + '_DISCON.IN'
1✔
1439
        discon_in_file = os.path.join(self.FAST_runDirectory, self.fst_vt['ServoDyn']['DLL_InFile'])
1✔
1440
        self.fst_vt['DISCON_in']['PerfFileName'] = self.FAST_namingOut + '_Cp_Ct_Cq.txt'
1✔
1441
        
1442
        # Write DISCON input files
1443
        ROSCO_utilities.write_rotor_performance(
1✔
1444
            turbine, 
1445
            txt_filename=os.path.join(self.FAST_runDirectory, self.fst_vt['DISCON_in']['PerfFileName'])
1446
            )
1447
        
1448
        ROSCO_utilities.write_DISCON(
1✔
1449
            turbine,
1450
            controller,
1451
            param_file=discon_in_file, 
1452
            txt_filename=self.fst_vt['DISCON_in']['PerfFileName'],
1453
            rosco_vt=self.fst_vt['DISCON_in']
1454
            )
1455

1456
    def write_HydroDyn(self):
1✔
1457

1458
        # Generate HydroDyn v2.03 input file
1459
        self.fst_vt['Fst']['HydroFile'] = self.FAST_namingOut + '_HydroDyn.dat'
1✔
1460
        hd_file = os.path.join(self.FAST_runDirectory, self.fst_vt['Fst']['HydroFile'])
1✔
1461
        f = open(hd_file, 'w')
1✔
1462

1463
        f.write('------- HydroDyn v2.03.* Input File --------------------------------------------\n')
1✔
1464
        f.write('Generated with AeroElasticSE FAST driver\n')
1✔
1465
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['Echo'], 'Echo', '- Echo the input file data (flag)\n'))
1✔
1466
        f.write('---------------------- ENVIRONMENTAL CONDITIONS --------------------------------\n')
1✔
1467
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WtrDens'], 'WtrDens', '- Water density (kg/m^3)\n'))
1✔
1468
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WtrDpth'], 'WtrDpth', '- Water depth (meters)\n'))
1✔
1469
        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'))
1✔
1470
        f.write('---------------------- WAVES ---------------------------------------------------\n')
1✔
1471
        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'))
1✔
1472
        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'))
1✔
1473
        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'))
1✔
1474
        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'))
1✔
1475
        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'))
1✔
1476
        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'))
1✔
1477
        if isinstance(self.fst_vt['HydroDyn']['WavePkShp'], float):
1✔
1478
            if self.fst_vt['HydroDyn']['WavePkShp'] == 0.:
1✔
UNCOV
1479
                WavePkShp = 'Default'
×
1480
            else: 
1481
                WavePkShp = self.fst_vt['HydroDyn']['WavePkShp']
1✔
1482
        else:
1483
            WavePkShp = self.fst_vt['HydroDyn']['WavePkShp']
1✔
1484
        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'))
1✔
1485
        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'))
1✔
1486
        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'))
1✔
1487
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WaveDir'], 'WaveDir', '- Incident wave propagation heading direction                         (degrees) [unused when WaveMod=0 or 6]\n'))
1✔
1488
        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'))
1✔
1489
        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'))
1✔
1490
        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'))
1✔
1491
        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'))
1✔
1492
        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'))
1✔
1493
        
1494
        try:
1✔
1495
            seed2 = int(self.fst_vt['HydroDyn']['WaveSeed2'])
1✔
1496
            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'))
×
1497
        except ValueError:
1✔
1498
            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'))
1✔
1499
            
1500
        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'))
1✔
1501
        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'))
1✔
1502
        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'))
1✔
1503
        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'))
1✔
1504
        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'))
1✔
1505
        f.write('---------------------- 2ND-ORDER WAVES ----------------------------------------- [unused with WaveMod=0 or 6]\n')
1✔
1506
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WvDiffQTF'], 'WvDiffQTF', '- Full difference-frequency 2nd-order wave kinematics (flag)\n'))
1✔
1507
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['WvSumQTF'], 'WvSumQTF', '- Full summation-frequency  2nd-order wave kinematics (flag)\n'))
1✔
1508
        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'))
1✔
1509
        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'))
1✔
1510
        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'))
1✔
1511
        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'))
1✔
1512
        f.write('---------------------- CURRENT ------------------------------------------------- [unused with WaveMod=6]\n')
1✔
1513
        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'))
1✔
1514
        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'))
1✔
1515
        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'))
1✔
1516
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['CurrNSRef'], 'CurrNSRef', '- Near-surface current reference depth            (meters) [used only when CurrMod=1]\n'))
1✔
1517
        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'))
1✔
1518
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['CurrNSDir'], 'CurrNSDir', '- Near-surface current heading direction         (degrees) [used only when CurrMod=1]\n'))
1✔
1519
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['CurrDIV'], 'CurrDIV', '- Depth-independent current velocity                 (m/s) [used only when CurrMod=1]\n'))
1✔
1520
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['CurrDIDir'], 'CurrDIDir', '- Depth-independent current heading direction    (degrees) [used only when CurrMod=1]\n'))
1✔
1521
        f.write('---------------------- FLOATING PLATFORM --------------------------------------- [unused with WaveMod=6]\n')
1✔
1522
        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'))
1✔
1523
        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'))
1✔
1524
        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'))
1✔
1525
        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'))
1✔
1526
        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'))
1✔
1527
        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'))
1✔
1528
        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'))
1✔
1529
        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'))
1✔
1530
        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'))
1✔
1531
        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'))
1✔
1532
        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'))
1✔
1533
        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'))
1✔
1534
        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'))
1✔
1535
        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'))
1✔
1536
        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'))
1✔
1537
        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'))
1✔
1538
        f.write('---------------------- 2ND-ORDER FLOATING PLATFORM FORCES ---------------------- [unused with WaveMod=0 or 6, or PotMod=0 or 2]\n')
1✔
1539
        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"))
1✔
1540
        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"))
1✔
1541
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['DiffQTF'], 'DiffQTF', "- Full difference-frequency 2nd-order forces computed with full QTF          {0: None; [10, 11, or 12]: WAMIT file to use}          [Only one of MnDrift, NewmanApp, or DiffQTF can be non-zero]\n"))
1✔
1542
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['SumQTF'], 'SumQTF', "- Full summation -frequency 2nd-order forces computed with full QTF          {0: None; [10, 11, or 12]: WAMIT file to use}\n"))
1✔
1543
        f.write('---------------------- PLATFORM ADDITIONAL STIFFNESS AND DAMPING  --------------\n')
1✔
1544
        for j in range(6):
1✔
1545
            if type(self.fst_vt['HydroDyn']['AddF0'][j]) == float:
1✔
1546
                ln = '{:14}   '.format(self.fst_vt['HydroDyn']['AddF0'][j])  
1✔
1547
            elif type(self.fst_vt['HydroDyn']['AddF0'][j]) in [list, np.ndarray]:
1✔
1548
                ln = '{:14}   '.format(' '.join([f'{val}' for val in self.fst_vt['HydroDyn']['AddF0'][j]]))
1✔
1549
            else:
1550
                raise Exception("Check type of self.fst_vt['HydroDyn']['AddF0']")
×
1551
            
1552
            if j == 0:
1✔
1553
                ln = ln + 'AddF0    - Additional preload (N, N-m) [If NBodyMod=1, one size 6*NBody x 1 vector; if NBodyMod>1, NBody size 6 x 1 vectors]\n'
1✔
1554
            else:
1555
                ln = ln + '\n'
1✔
1556
            f.write(ln)
1✔
1557
        for j in range(6):
1✔
1558
            try:
1✔
1559
                ln = " ".join(['{:14}'.format(i) for i in self.fst_vt['HydroDyn']['AddCLin'][j,:]])
1✔
1560
            except:
×
1561
                ln = " ".join(['{:14}'.format(i) for i in self.fst_vt['HydroDyn']['AddCLin'][j]])
×
1562
            if j == 0:
1✔
1563
                ln = ln + "   AddCLin  - Additional linear stiffness (N/m, N/rad, N-m/m, N-m/rad)\n"
1✔
1564
            else:
1565
                ln = ln  + "\n"
1✔
1566
            f.write(ln)
1✔
1567
        for j in range(6):
1✔
1568
            try:
1✔
1569
                ln = " ".join(['{:14}'.format(i) for i in self.fst_vt['HydroDyn']['AddBLin'][j,:]])
1✔
1570
            except:
×
1571
                ln = " ".join(['{:14}'.format(i) for i in self.fst_vt['HydroDyn']['AddBLin'][j]])
×
1572
            if j == 0:
1✔
1573
                ln = ln + "   AddBLin  - Additional linear damping(N/(m/s), N/(rad/s), N-m/(m/s), N-m/(rad/s))\n"
1✔
1574
            else:
1575
                ln = ln  + "\n"
1✔
1576
            f.write(ln)
1✔
1577
        for j in range(6):
1✔
1578
            try:
1✔
1579
                ln = " ".join(['{:14}'.format(i) for i in self.fst_vt['HydroDyn']['AddBQuad'][j,:]])
1✔
1580
            except:
×
1581
                ln = " ".join(['{:14}'.format(i) for i in self.fst_vt['HydroDyn']['AddBQuad'][j]])
×
1582
            if j == 0:
1✔
1583
                ln = ln + "   AddBQuad - Additional quadratic drag(N/(m/s)^2, N/(rad/s)^2, N-m(m/s)^2, N-m/(rad/s)^2)\n"
1✔
1584
            else:
1585
                ln = ln  + "\n"
1✔
1586
            f.write(ln)
1✔
1587
        f.write('---------------------- AXIAL COEFFICIENTS --------------------------------------\n')
1✔
1588
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NAxCoef'], 'NAxCoef', '- Number of axial coefficients (-)\n'))
1✔
1589
        f.write(" ".join(['{:^11s}'.format(i) for i in ['AxCoefID', 'AxCd', 'AxCa', 'AxCp']])+'\n')
1✔
1590
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)']*4])+'\n')
1✔
1591
        for i in range(self.fst_vt['HydroDyn']['NAxCoef']):
1✔
1592
            ln = []
1✔
1593
            ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['AxCoefID'][i]))
1✔
1594
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['AxCd'][i]))
1✔
1595
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['AxCa'][i]))
1✔
1596
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['AxCp'][i]))
1✔
1597
            f.write(" ".join(ln) + '\n')
1✔
1598
        f.write('---------------------- MEMBER JOINTS -------------------------------------------\n')
1✔
1599
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NJoints'], 'NJoints', '- Number of joints (-)   [must be exactly 0 or at least 2]\n'))
1✔
1600
        f.write(" ".join(['{:^11s}'.format(i) for i in ['JointID', 'Jointxi', 'Jointyi', 'Jointzi', 'JointAxID', 'JointOvrlp']])+'  ! [JointOvrlp= 0: do nothing at joint, 1: eliminate overlaps by calculating super member]\n')
1✔
1601
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)', '(m)', '(m)', '(m)', '(-)', '(switch)']])+'\n')
1✔
1602
        for i in range(self.fst_vt['HydroDyn']['NJoints']):
1✔
1603
            ln = []
1✔
1604
            ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['JointID'][i]))
1✔
1605
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['Jointxi'][i]))
1✔
1606
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['Jointyi'][i]))
1✔
1607
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['Jointzi'][i]))
1✔
1608
            ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['JointAxID'][i]))
1✔
1609
            ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['JointOvrlp'][i]))
1✔
1610
            f.write(" ".join(ln) + '\n')
1✔
1611
        f.write('---------------------- MEMBER CROSS-SECTION PROPERTIES -------------------------\n')
1✔
1612
        f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NPropSets'], 'NPropSets', '- Number of member property sets (-)\n'))
1✔
1613
        f.write(" ".join(['{:^11s}'.format(i) for i in ['PropSetID', 'PropD', 'PropThck']])+'\n')
1✔
1614
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)', '(m)', '(m)']])+'\n')
1✔
1615
        for i in range(self.fst_vt['HydroDyn']['NPropSets']):
1✔
1616
            ln = []
1✔
1617
            ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['PropSetID'][i]))
1✔
1618
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['PropD'][i]))
1✔
1619
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['PropThck'][i]))
1✔
1620
            f.write(" ".join(ln) + '\n')
1✔
1621
        f.write('---------------------- SIMPLE HYDRODYNAMIC COEFFICIENTS (model 1) --------------\n')
1✔
1622
        f.write(" ".join(['{:^11s}'.format(i) for i in ['SimplCd', 'SimplCdMG', 'SimplCa', 'SimplCaMG', 'SimplCp', 'SimplCpMG', 'SimplAxCd', 'SimplAxCdMG', 'SimplAxCa', 'SimplAxCaMG', 'SimplAxCp', 'SimplAxCpMG']])+'\n')
1✔
1623
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)']*12])+'\n')
1✔
1624
        ln = []
1✔
1625
        ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplCd']))
1✔
1626
        ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplCdMG']))
1✔
1627
        ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplCa']))
1✔
1628
        ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplCaMG']))
1✔
1629
        ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplCp']))
1✔
1630
        ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplCpMG']))
1✔
1631
        ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplAxCd']))
1✔
1632
        ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplAxCdMG']))
1✔
1633
        ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplAxCa']))
1✔
1634
        ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplAxCaMG']))
1✔
1635
        ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplAxCp']))
1✔
1636
        ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplAxCpMG']))
1✔
1637
        f.write(" ".join(ln) + '\n')
1✔
1638
        f.write('---------------------- DEPTH-BASED HYDRODYNAMIC COEFFICIENTS (model 2) ---------\n')        
1✔
1639
        f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NCoefDpth'], 'NCoefDpth', '- Number of depth-dependent coefficients (-)\n'))
1✔
1640
        f.write(" ".join(['{:^11s}'.format(i) for i in ['Dpth', 'DpthCd', 'DpthCdMG', 'DpthCa', 'DpthCaMG', 'DpthCp', 'DpthCpMG', 'DpthAxCd', 'DpthAxCdMG', 'DpthAxCa', 'DpthAxCaMG', 'DpthAxCp', 'DpthAxCpMG']])+'\n')
1✔
1641
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(m)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)']])+'\n')
1✔
1642
        for i in range(self.fst_vt['HydroDyn']['NCoefDpth']):
1✔
1643
            ln = []
×
1644
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['Dpth'][i]))
×
1645
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthCd'][i]))
×
1646
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthCdMG'][i]))
×
1647
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthCa'][i]))
×
1648
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthCaMG'][i]))
×
1649
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthCp'][i]))
×
1650
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthCpMG'][i]))
×
1651
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthAxCd'][i]))
×
1652
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthAxCdMG'][i]))
×
1653
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthAxCa'][i]))
×
1654
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthAxCaMG'][i]))
×
1655
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthAxCp'][i]))
×
1656
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthAxCpMG'][i]))
×
1657
            f.write(" ".join(ln) + '\n')
×
1658
        f.write('---------------------- MEMBER-BASED HYDRODYNAMIC COEFFICIENTS (model 3) --------\n')
1✔
1659
        f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NCoefMembers'], 'NCoefMembers', '- Number of member-based coefficients (-)\n'))
1✔
1660
        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')
1✔
1661
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)']*25])+'\n')
1✔
1662
        for i in range(self.fst_vt['HydroDyn']['NCoefMembers']):
1✔
1663
            ln = []
×
1664
            ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MemberID_HydC'][i]))
×
1665
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCd1'][i]))
×
1666
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCd2'][i]))
×
1667
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCdMG1'][i]))
×
1668
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCdMG2'][i]))
×
1669
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCa1'][i]))
×
1670
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCa2'][i]))
×
1671
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCaMG1'][i]))
×
1672
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCaMG2'][i]))
×
1673
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCp1'][i]))
×
1674
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCp2'][i]))
×
1675
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCpMG1'][i]))
×
1676
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCpMG2'][i]))
×
1677
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCd1'][i]))
×
1678
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCd2'][i]))
×
1679
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCdMG1'][i]))
×
1680
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCdMG2'][i]))
×
1681
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCa1'][i]))
×
1682
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCa2'][i]))
×
1683
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCaMG1'][i]))
×
1684
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCaMG2'][i]))
×
1685
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCp1'][i]))
×
1686
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCp2'][i]))
×
1687
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCpMG1'][i]))
×
1688
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCpMG2'][i]))
×
1689
            f.write(" ".join(ln) + '\n')
×
1690
        f.write('-------------------- MEMBERS -------------------------------------------------\n')
1✔
1691
        f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NMembers'], 'NMembers', '- Number of members (-)\n'))
1✔
1692
        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')
1✔
1693
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)', '(-)', '(-)', '(-)', '(-)', '(m)', '(switch)', '(flag)']])+'\n')
1✔
1694
        for i in range(self.fst_vt['HydroDyn']['NMembers']):
1✔
1695
            ln = []
1✔
1696
            ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MemberID'][i]))
1✔
1697
            ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MJointID1'][i]))
1✔
1698
            ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MJointID2'][i]))
1✔
1699
            ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MPropSetID1'][i]))
1✔
1700
            ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MPropSetID2'][i]))
1✔
1701
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MDivSize'][i]))
1✔
1702
            ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MCoefMod'][i]))
1✔
1703
            ln.append('{!s:^11}'.format(self.fst_vt['HydroDyn']['PropPot'][i]))
1✔
1704
            f.write(" ".join(ln) + '\n')
1✔
1705
        f.write("---------------------- FILLED MEMBERS ------------------------------------------\n")
1✔
1706
        f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NFillGroups'], 'NFillGroups', '- Number of filled member groups (-) [If FillDens = DEFAULT, then FillDens = WtrDens; FillFSLoc is related to MSL2SWL]\n'))
1✔
1707
        f.write(" ".join(['{:^11s}'.format(i) for i in ['FillNumM', 'FillMList', 'FillFSLoc', 'FillDens']])+'\n')
1✔
1708
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)', '(-)', '(m)', '(kg/m^3)']])+'\n')
1✔
1709
        for i in range(self.fst_vt['HydroDyn']['NFillGroups']):
1✔
1710
            ln = []
×
1711
            ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['FillNumM'][i]))
×
1712
            ln.append(" ".join(['%d'%j for j in self.fst_vt['HydroDyn']['FillMList'][i]]))
×
1713
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['FillFSLoc'][i]))
×
1714
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['FillDens'][i]))
×
1715
            f.write(" ".join(ln) + '\n')
×
1716
        f.write("---------------------- MARINE GROWTH -------------------------------------------\n")
1✔
1717
        f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NMGDepths'], 'NMGDepths', '- Number of marine-growth depths specified (-)\n'))
1✔
1718
        f.write(" ".join(['{:^11s}'.format(i) for i in ['MGDpth', 'MGThck', 'MGDens']])+'\n')
1✔
1719
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(m)', '(m)', '(kg/m^3)']])+'\n')
1✔
1720
        for i in range(self.fst_vt['HydroDyn']['NMGDepths']):
1✔
1721
            ln = []
×
1722
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MGDpth'][i]))
×
1723
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MGThck'][i]))
×
1724
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MGDens'][i]))
×
1725
            f.write(" ".join(ln) + '\n')
×
1726
        f.write("---------------------- MEMBER OUTPUT LIST --------------------------------------\n")
1✔
1727
        f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NMOutputs'], 'NMOutputs', '- Number of member outputs (-) [must be < 10]\n'))
1✔
1728
        f.write(" ".join(['{:^11s}'.format(i) for i in ['MemberID_out', 'NOutLoc', 'NodeLocs']])+'\n')
1✔
1729
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)']*3])+'\n')
1✔
1730
        for i in range(self.fst_vt['HydroDyn']['NMOutputs']):
1✔
1731
            ln = []
×
1732
            ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MemberID_out'][i]))
×
1733
            ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['NOutLoc'][i]))
×
1734
            ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['NodeLocs'][i]))
×
1735
            f.write(" ".join(ln) + '\n')
×
1736
        f.write("---------------------- JOINT OUTPUT LIST ---------------------------------------\n")
1✔
1737
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NJOutputs'], 'NJOutputs', '- Number of joint outputs [Must be < 10]\n'))
1✔
1738
        f.write('{:<22} {:<11} {:}'.format(" ".join(["%d"%i for i in self.fst_vt['HydroDyn']['JOutLst']]), 'JOutLst', '- List of JointIDs which are to be output (-)[unused if NJOutputs=0]\n'))
1✔
1739
        f.write("---------------------- OUTPUT --------------------------------------------------\n")
1✔
1740
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['HDSum'], 'HDSum', '- Output a summary file [flag]\n'))
1✔
1741
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['OutAll'], 'OutAll', '- Output all user-specified member and joint loads (only at each member end, not interior locations) [flag]\n'))
1✔
1742
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['OutSwtch'], 'OutSwtch', '- Output requested channels to: [1=Hydrodyn.out, 2=GlueCode.out, 3=both files]\n'))
1✔
1743
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['OutFmt'], 'OutFmt', '- Output format for numerical results (quoted string) [not checked for validity!]\n'))
1✔
1744
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['HydroDyn']['OutSFmt'], 'OutSFmt', '- Output format for header strings (quoted string) [not checked for validity!]\n'))
1✔
1745
        f.write('---------------------- OUTPUT CHANNELS -----------------------------------------\n')
1✔
1746
        outlist = self.get_outlist(self.fst_vt['outlist'], ['HydroDyn'])
1✔
1747
        for channel_list in outlist:
1✔
1748
            for i in range(len(channel_list)):
1✔
1749
                f.write('"' + channel_list[i] + '"\n')
1✔
1750
            
1751
        f.write('END of output channels and end of file. (the word "END" must appear in the first 3 columns of this line)\n')
1✔
1752
        
1753

1754
        f.flush()
1✔
1755
        os.fsync(f)
1✔
1756
        f.close()
1✔
1757

1758
    def write_SubDyn(self):
1✔
1759
        # Generate SubDyn v1.1 input file
1760
        self.fst_vt['Fst']['SubFile'] = self.FAST_namingOut + '_SubDyn.dat'
1✔
1761
        sd_file = os.path.join(self.FAST_runDirectory, self.fst_vt['Fst']['SubFile'])
1✔
1762
        f = open(sd_file, 'w')
1✔
1763

1764
        f.write('----------- SubDyn v1.01.x MultiMember Support Structure Input File ------------\n')
1✔
1765
        f.write('Generated with AeroElasticSE FAST driver\n')
1✔
1766
        f.write('-------------------------- SIMULATION CONTROL  ---------------------------------\n')
1✔
1767
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['SubDyn']['Echo'], 'Echo', '- Echo input data to "<rootname>.SD.ech" (flag)\n'))
1✔
1768
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SubDyn']['SDdeltaT'], 'SDdeltaT', '- Local Integration Step. If "default", the glue-code integration step will be used.\n'))
1✔
1769
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['IntMethod'], 'IntMethod', '- Integration Method [1/2/3/4 = RK4/AB4/ABM4/AM2].\n'))
1✔
1770
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['SubDyn']['SttcSolve'], 'SttcSolve', '- Solve dynamics about static equilibrium point\n'))
1✔
1771
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['SubDyn']['GuyanLoadCorrection'], 'GuyanLoadCorrection', '- Include extra moment from lever arm at interface and rotate FEM for floating.\n'))
1✔
1772
        f.write('-------------------- FEA and CRAIG-BAMPTON PARAMETERS---------------------------\n')
1✔
1773
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['FEMMod'], 'FEMMod', '- FEM switch: element model in the FEM. [1= Euler-Bernoulli(E-B);  2=Tapered E-B (unavailable);  3= 2-node Timoshenko;  4= 2-node tapered Timoshenko (unavailable)]\n'))
1✔
1774
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NDiv'], 'NDiv', '- Number of sub-elements per member\n'))
1✔
1775
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['SubDyn']['CBMod'], 'CBMod', '- [T/F] If True perform C-B reduction, else full FEM dofs will be retained. If True, select Nmodes to retain in C-B reduced system.\n'))
1✔
1776
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['Nmodes'], 'Nmodes', '- Number of internal modes to retain (ignored if CBMod=False). If Nmodes=0 --> Guyan Reduction.\n'))
1✔
1777
        
1778
        JDampings = self.fst_vt['SubDyn']['JDampings']
1✔
1779
        if isinstance(JDampings, float):
1✔
1780
            f.write('{:<22} {:<11} {:}'.format(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'))
1✔
1781
        else: # list of floats
1782
            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'))
1✔
1783
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['GuyanDampMod'], 'GuyanDampMod', '- Guyan damping {0=none, 1=Rayleigh Damping, 2=user specified 6x6 matrix}.\n'))
1✔
1784
        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'))
1✔
1785
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['GuyanDampSize'], 'GuyanDampSize', '- Guyan damping matrix (6x6) [only if GuyanDampMod=2].\n'))
1✔
1786
        for j in range(self.fst_vt['SubDyn']['GuyanDampSize']):
1✔
1787
            try:
1✔
1788
                ln = " ".join(['{:14}'.format(i) for i in self.fst_vt['SubDyn']['GuyanDamp'][j,:]])
1✔
1789
            except:
×
1790
                ln = " ".join(['{:14}'.format(i) for i in self.fst_vt['SubDyn']['GuyanDamp'][j]])
×
1791
            ln += "\n"
1✔
1792
            f.write(ln)
1✔
1793
        
1794
        f.write('---- STRUCTURE JOINTS: joints connect structure members (~Hydrodyn Input File)---\n')
1✔
1795
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NJoints'], 'NJoints', '- Number of joints (-)\n'))
1✔
1796
        f.write(" ".join(['{:^11s}'.format(i) for i in ['JointID','JointXss','JointYss','JointZss','JointType','JointDirX','JointDirY','JointDirZ','JointStiff']])+'\n')
1✔
1797
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)','(m)','(m)','(m)','(-)','(-)','(-)','(-)','(Nm/rad)']])+'\n')
1✔
1798
        for i in range(self.fst_vt['SubDyn']['NJoints']):
1✔
1799
            ln = []
1✔
1800
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['JointID'][i]))
1✔
1801
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['JointXss'][i]))
1✔
1802
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['JointYss'][i]))
1✔
1803
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['JointZss'][i]))
1✔
1804
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['JointType'][i]))
1✔
1805
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['JointDirX'][i]))
1✔
1806
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['JointDirY'][i]))
1✔
1807
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['JointDirZ'][i]))
1✔
1808
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['JointStiff'][i]))
1✔
1809
            f.write(" ".join(ln) + '\n')        
1✔
1810
        f.write('------------------- BASE REACTION JOINTS: 1/0 for Locked/Free DOF @ each Reaction Node ---------------------\n')
1✔
1811
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NReact'], 'NReact', '- Number of Joints with reaction forces; be sure to remove all rigid motion DOFs of the structure  (else det([K])=[0])\n'))
1✔
1812
        f.write(" ".join(['{:^11s}'.format(i) for i in ['RJointID', 'RctTDXss', 'RctTDYss', 'RctTDZss', 'RctRDXss', 'RctRDYss', 'RctRDZss','SSIfile']])+' ! [Global Coordinate System]\n')
1✔
1813
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)', '(flag)', '(flag)', '(flag)', '(flag)', '(flag)', '(flag)', '(string)']])+'\n')
1✔
1814
        for i in range(self.fst_vt['SubDyn']['NReact']):
1✔
1815
            ln = []
1✔
1816
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['RJointID'][i]))
1✔
1817
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['RctTDXss'][i]))
1✔
1818
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['RctTDYss'][i]))
1✔
1819
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['RctTDZss'][i]))
1✔
1820
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['RctRDXss'][i]))
1✔
1821
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['RctRDYss'][i]))
1✔
1822
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['RctRDZss'][i]))
1✔
1823
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['Rct_SoilFile'][i]))
1✔
1824
            f.write(" ".join(ln) + '\n')
1✔
1825
        f.write('------- INTERFACE JOINTS: 1/0 for Locked (to the TP)/Free DOF @each Interface Joint (only Locked-to-TP implemented thus far (=rigid TP)) ---------\n')
1✔
1826
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NInterf'], 'NInterf', '- Number of interface joints locked to the Transition Piece (TP):  be sure to remove all rigid motion dofs\n'))
1✔
1827
        f.write(" ".join(['{:^11s}'.format(i) for i in ['IJointID', 'ItfTDXss', 'ItfTDYss', 'ItfTDZss', 'ItfRDXss', 'ItfRDYss', 'ItfRDZss']])+' ! [Global Coordinate System]\n')
1✔
1828
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)', '(flag)', '(flag)', '(flag)', '(flag)', '(flag)', '(flag)']])+'\n')
1✔
1829
        for i in range(self.fst_vt['SubDyn']['NInterf']):
1✔
1830
            ln = []
1✔
1831
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['IJointID'][i]))
1✔
1832
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['ItfTDXss'][i]))
1✔
1833
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['ItfTDYss'][i]))
1✔
1834
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['ItfTDZss'][i]))
1✔
1835
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['ItfRDXss'][i]))
1✔
1836
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['ItfRDYss'][i]))
1✔
1837
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['ItfRDZss'][i]))
1✔
1838
            f.write(" ".join(ln) + '\n')
1✔
1839
        f.write('----------------------------------- MEMBERS --------------------------------------\n')
1✔
1840
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NMembers'], 'NMembers', '- Number of frame members\n'))
1✔
1841
        f.write(" ".join(['{:^11s}'.format(i) for i in ['MemberID', 'MJointID1', 'MJointID2', 'MPropSetID1', 'MPropSetID2', 'MType', 'COSMID']])+'\n')
1✔
1842
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)','(-)','(-)','(-)','(-)','(-)','(-)']])+'\n')
1✔
1843
        for i in range(self.fst_vt['SubDyn']['NMembers']):
1✔
1844
            ln = []
1✔
1845
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['MemberID'][i]))
1✔
1846
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['MJointID1'][i]))
1✔
1847
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['MJointID2'][i]))
1✔
1848
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['MPropSetID1'][i]))
1✔
1849
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['MPropSetID2'][i]))
1✔
1850
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['MType'][i]))
1✔
1851
            if self.fst_vt['SubDyn']['NCOSMs'] > 0:
1✔
1852
                ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['COSMID'][i]))
×
1853
            f.write(" ".join(ln) + '\n')
1✔
1854
        f.write('------------------ MEMBER X-SECTION PROPERTY data 1/2 [isotropic material for now: use this table for circular-tubular elements] ------------------------\n')
1✔
1855
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NPropSets'], 'NPropSets', '- Number of structurally unique x-sections (i.e. how many groups of X-sectional properties are utilized throughout all of the members)\n'))
1✔
1856
        f.write(" ".join(['{:^11s}'.format(i) for i in ['PropSetID', 'YoungE', 'ShearG1', 'MatDens', 'XsecD', 'XsecT']])+'\n')
1✔
1857
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)','(N/m2)','(N/m2)','(kg/m3)','(m)','(m)']])+'\n')
1✔
1858
        for i in range(self.fst_vt['SubDyn']['NPropSets']):
1✔
1859
            ln = []
1✔
1860
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['PropSetID1'][i]))
1✔
1861
            ln.append('{:^11e}'.format(self.fst_vt['SubDyn']['YoungE1'][i]))
1✔
1862
            ln.append('{:^11e}'.format(self.fst_vt['SubDyn']['ShearG1'][i]))
1✔
1863
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['MatDens1'][i]))
1✔
1864
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecD'][i]))
1✔
1865
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecT'][i]))
1✔
1866
            f.write(" ".join(ln) + '\n')
1✔
1867
        f.write('------------------ MEMBER X-SECTION PROPERTY data 2/2 [isotropic material for now: use this table if any section other than circular, however provide COSM(i,j) below] ------------------------\n')
1✔
1868
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NXPropSets'], 'NXPropSets', '- Number of structurally unique non-circular x-sections (if 0 the following table is ignored)\n'))
1✔
1869
        f.write(" ".join(['{:^11s}'.format(i) for i in ['PropSetID', 'YoungE', 'ShearG2', 'MatDens', 'XsecA', 'XsecAsx', 'XsecAsy', 'XsecJxx', 'XsecJyy', 'XsecJ0']])+'\n')
1✔
1870
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)','(N/m2)','(N/m2)','(kg/m3)','(m2)','(m2)','(m2)','(m4)','(m4)','(m4)']])+'\n')
1✔
1871
        for i in range(self.fst_vt['SubDyn']['NXPropSets']):
1✔
1872
            ln = []
×
1873
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['PropSetID2'][i]))
×
1874
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['YoungE2'][i]))
×
1875
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['ShearG2'][i]))
×
1876
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['MatDens2'][i]))
×
1877
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecA'][i]))
×
1878
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecAsx'][i]))
×
1879
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecAsy'][i]))
×
1880
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecJxx'][i]))
×
1881
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecJyy'][i]))
×
1882
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecJ0'][i]))
×
1883
            f.write(" ".join(ln) + '\n')
×
1884
        f.write('-------------------------- CABLE PROPERTIES  -------------------------------------\n')
1✔
1885
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NCablePropSets'], 'NCablePropSets', '- Number of cable cable properties\n'))
1✔
1886
        f.write(" ".join(['{:^11s}'.format(i) for i in ['PropSetID', 'EA', 'MatDens', 'T0']])+'\n')
1✔
1887
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)','(N)','(kg/m)','(N)']])+'\n')
1✔
1888
        for i in range(self.fst_vt['SubDyn']['NCablePropSets']):
1✔
1889
            ln = []
×
1890
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['CablePropSetID'][i]))
×
1891
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['CableEA'][i]))
×
1892
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['CableMatDens'][i]))
×
1893
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['CableT0'][i]))
×
1894
            f.write(" ".join(ln) + '\n')
×
1895
        f.write('----------------------- RIGID LINK PROPERTIES ------------------------------------\n')
1✔
1896
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NRigidPropSets'], 'NRigidPropSets', '- Number of rigid link properties\n'))
1✔
1897
        f.write(" ".join(['{:^11s}'.format(i) for i in ['PropSetID', 'MatDens']])+'\n')
1✔
1898
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)','(kg/m)']])+'\n')
1✔
1899
        for i in range(self.fst_vt['SubDyn']['NRigidPropSets']):
1✔
1900
            ln = []
×
1901
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['RigidPropSetID'][i]))
×
1902
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['RigidMatDens'][i]))
×
1903
            f.write(" ".join(ln) + '\n')
×
1904
        f.write('---------------------- MEMBER COSINE MATRICES COSM(i,j) ------------------------\n')
1✔
1905
        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'))
1✔
1906
        f.write(" ".join(['{:^11s}'.format(i) for i in ['COSMID', 'COSM11', 'COSM12', 'COSM13', 'COSM21', 'COSM22', 'COSM23', 'COSM31', 'COSM32', 'COSM33']])+'\n')
1✔
1907
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)','(-)','(-)','(-)','(-)','(-)','(-)','(-)','(-)','(-)']])+'\n')
1✔
1908
        for i in range(self.fst_vt['SubDyn']['NCOSMs']):
1✔
1909
            ln = []
×
1910
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['COSMID'][i]))
×
1911
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['COSM11'][i]))
×
1912
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['COSM12'][i]))
×
1913
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['COSM13'][i]))
×
1914
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['COSM21'][i]))
×
1915
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['COSM22'][i]))
×
1916
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['COSM23'][i]))
×
1917
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['COSM31'][i]))
×
1918
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['COSM32'][i]))
×
1919
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['COSM33'][i]))
×
1920
            f.write(" ".join(ln) + '\n')
×
1921
        f.write('------------------------ JOINT ADDITIONAL CONCENTRATED MASSES--------------------------\n')
1✔
1922
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NCmass'], 'NCmass', '- Number of joints with concentrated masses; Global Coordinate System\n'))
1✔
1923
        f.write(" ".join(['{:^11s}'.format(i) for i in ['CMJointID','JMass','JMXX','JMYY','JMZZ','JMXY','JMXZ','JMYZ','MCGX','MCGY','MCGZ']])+'\n')
1✔
1924
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)','(kg)','(kg*m^2)','(kg*m^2)','(kg*m^2)','(kg*m^2)','(kg*m^2)','(kg*m^2)','(m)','(m)','(m)']])+'\n')
1✔
1925
        for i in range(self.fst_vt['SubDyn']['NCmass']):
1✔
1926
            ln = []
1✔
1927
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['CMJointID'][i]))
1✔
1928
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['JMass'][i]))
1✔
1929
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['JMXX'][i]))
1✔
1930
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['JMYY'][i]))
1✔
1931
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['JMZZ'][i]))
1✔
1932
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['JMXY'][i]))
1✔
1933
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['JMXZ'][i]))
1✔
1934
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['JMYZ'][i]))
1✔
1935
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['MCGX'][i]))
1✔
1936
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['MCGY'][i]))
1✔
1937
            ln.append('{:^11}'.format(self.fst_vt['SubDyn']['MCGZ'][i]))
1✔
1938
            f.write(" ".join(ln) + '\n')
1✔
1939
        f.write('---------------------------- OUTPUT: SUMMARY & OUTFILE ------------------------------\n')
1✔
1940
        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'))
1✔
1941
        if 'OutCBModes' in self.fst_vt['SubDyn']:
1✔
1942
            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'))
1✔
1943
        if 'OutFEMModes' in self.fst_vt['SubDyn']:
1✔
1944
            f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['OutFEMModes'], 'OutFEMModes', '-  Output first 30 FEM modes {0 No output, 1 JSON output} (flag)\n'))
1✔
1945
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['SubDyn']['OutCOSM'], 'OutCOSM', '- Output cosine matrices with the selected output member forces (flag)\n'))
1✔
1946
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['SubDyn']['OutAll'], 'OutAll', "- [T/F] Output all members' end forces\n"))
1✔
1947
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['OutSwtch'], 'OutSwtch', '- [1/2/3] Output requested channels to: 1=<rootname>.SD.out;  2=<rootname>.out (generated by FAST);  3=both files.\n'))
1✔
1948
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['SubDyn']['TabDelim'], 'TabDelim', '- Generate a tab-delimited output in the <rootname>.SD.out file\n'))
1✔
1949
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['OutDec'], 'OutDec', '- Decimation of output in the <rootname>.SD.out file\n'))
1✔
1950
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SubDyn']['OutFmt'], 'OutFmt', '- Output format for numerical results in the <rootname>.SD.out file\n'))
1✔
1951
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['SubDyn']['OutSFmt'], 'OutSFmt', '- Output format for header strings in the <rootname>.SD.out file\n'))
1✔
1952
        f.write('------------------------- MEMBER OUTPUT LIST ------------------------------------------\n')
1✔
1953
        f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NMOutputs'], 'NMOutputs', '- Number of members whose forces/displacements/velocities/accelerations will be output (-) [Must be <= 9].\n'))
1✔
1954
        f.write(" ".join(['{:^11s}'.format(i) for i in ['MemberID', 'NOutCnt', 'NodeCnt']])+' ! [NOutCnt=how many nodes to get output for [< 10]; NodeCnt are local ordinal numbers from the start of the member, and must be >=1 and <= NDiv+1] If NMOutputs=0 leave blank as well.\n')
1✔
1955
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)','(-)','(-)']])+'\n')
1✔
1956
        for i in range(self.fst_vt['SubDyn']['NMOutputs']):
1✔
1957
            ln = []
1✔
1958
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['MemberID_out'][i]))
1✔
1959
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['NOutCnt'][i]))
1✔
1960
            ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['NodeCnt'][i]))
1✔
1961
            f.write(" ".join(ln) + '\n')
1✔
1962
        f.write('------------------------- SDOutList: The next line(s) contains a list of output parameters that will be output in <rootname>.SD.out or <rootname>.out. ------\n')
1✔
1963
        outlist = self.get_outlist(self.fst_vt['outlist'], ['SubDyn'])
1✔
1964
        for channel_list in outlist:
1✔
1965
            for i in range(len(channel_list)):
1✔
1966
                f.write('"' + channel_list[i] + '"\n')
1✔
1967
        f.write('END of output channels and end of file. (the word "END" must appear in the first 3 columns of this line)\n')
1✔
1968
        f.flush()
1✔
1969
        os.fsync(f)
1✔
1970
        f.close()
1✔
1971

1972
    def write_MAP(self):
1✔
1973

1974
        # Generate MAP++ input file
1975
        self.fst_vt['Fst']['MooringFile'] = self.FAST_namingOut + '_MAP.dat'
×
1976
        map_file = os.path.join(self.FAST_runDirectory, self.fst_vt['Fst']['MooringFile'])
×
1977
        f = open(map_file, 'w')
×
1978
        
1979
        f.write('---------------------- LINE DICTIONARY ---------------------------------------\n')
×
1980
        f.write(" ".join(['{:<11s}'.format(i) for i in ['LineType', 'Diam', 'MassDenInAir', 'EA', 'CB', 'CIntDamp', 'Ca', 'Cdn', 'Cdt']])+'\n')
×
1981
        f.write(" ".join(['{:<11s}'.format(i) for i in ['(-)', '(m)', '(kg/m)', '(N)', '(-)', '(Pa-s)', '(-)', '(-)', '(-)']])+'\n')
×
1982
        ln =[]
×
1983
        for i in range(self.fst_vt['MAP']['NTypes']):
×
1984
            ln = []
×
1985
            ln.append('{:^11}'.format(self.fst_vt['MAP']['LineType'][i]))
×
1986
            ln.append('{:^11}'.format(self.fst_vt['MAP']['Diam'][i]))
×
1987
            ln.append('{:^11}'.format(self.fst_vt['MAP']['MassDen'][i]))
×
1988
            ln.append('{:^11}'.format(self.fst_vt['MAP']['EA'][i]))
×
1989
            ln.append('{:<11}'.format(self.fst_vt['MAP']['CB'][i]))
×
1990
            ln.append('{:<11}'.format(self.fst_vt['MAP']['CIntDamp'][i]))
×
1991
            ln.append('{:<11}'.format(self.fst_vt['MAP']['Ca'][i]))
×
1992
            ln.append('{:<11}'.format(self.fst_vt['MAP']['Cdn'][i]))
×
1993
            ln.append('{:<11}'.format(self.fst_vt['MAP']['Cdt'][i]))
×
1994
        f.write(" ".join(ln) + '\n')
×
1995
        f.write('---------------------- NODE PROPERTIES ---------------------------------------\n')
×
1996
        f.write(" ".join(['{:<11s}'.format(i) for i in ['Node', 'Type', 'X', 'Y', 'Z', 'M', 'B', 'FX', 'FY', 'FZ']])+'\n')
×
1997
        f.write(" ".join(['{:<11s}'.format(i) for i in ['(-)', '(-)', '(m)', '(m)', '(m)', '(kg)', '(m^3)', '(N)', '(N)', '(N)']])+'\n')
×
1998
        for i, type in enumerate(self.fst_vt['MAP']['Type']):
×
1999
            ln = []
×
2000
            ln.append('{:<11}'.format(self.fst_vt['MAP']['Node'][i]))
×
2001
            ln.append('{:<11}'.format(self.fst_vt['MAP']['Type'][i]))
×
2002
            ln.append('{:<11}'.format(self.fst_vt['MAP']['X'][i]))
×
2003
            ln.append('{:<11}'.format(self.fst_vt['MAP']['Y'][i]))
×
2004
            ln.append('{:<11}'.format(self.fst_vt['MAP']['Z'][i]))
×
2005
            ln.append('{:<11}'.format(self.fst_vt['MAP']['M'][i]))
×
2006
            ln.append('{:<11}'.format(self.fst_vt['MAP']['B'][i]))
×
2007
            ln.append('{:<11}'.format(self.fst_vt['MAP']['FX'][i]))
×
2008
            ln.append('{:<11}'.format(self.fst_vt['MAP']['FY'][i]))
×
2009
            ln.append('{:<11}'.format(self.fst_vt['MAP']['FZ'][i]))
×
2010
            f.write(" ".join(ln) + '\n')
×
2011
        f.write('---------------------- LINE PROPERTIES ---------------------------------------\n')
×
2012
        f.write(" ".join(['{:<11s}'.format(i) for i in ['Line', 'LineType', 'UnstrLen', 'NodeAnch', 'NodeFair', 'Flags']])+'\n')
×
2013
        f.write(" ".join(['{:<11s}'.format(i) for i in ['(-)', '(-)', '(m)', '(-)', '(-)', '(-)']])+'\n')
×
2014
        for i in range(self.fst_vt['MAP']['NLines']):
×
2015
            ln = []
×
2016
            ln.append('{:^11d}'.format(self.fst_vt['MAP']['Line'][i]))
×
2017
            ln.append('{:^11}'.format(self.fst_vt['MAP']['LineType'][i]))
×
2018
            ln.append('{:^11}'.format(self.fst_vt['MAP']['UnstrLen'][i]))
×
2019
            ln.append('{:^11d}'.format(self.fst_vt['MAP']['NodeAnch'][i]))
×
2020
            ln.append('{:^11d}'.format(self.fst_vt['MAP']['NodeFair'][i]))
×
2021
            # ln.append('{:^11}'.format(self.fst_vt['MAP']['Outputs'][i]))
2022
            # ln.append('{:^11}'.format(self.fst_vt['MAP']['CtrlChan'][i]))
2023
            # ln.append('{:<11}'.format(" ".join(self.fst_vt['MAP']['Flags'])))
2024
            f.write(" ".join(ln) + '\n')
×
2025
        ln =[]
×
2026
        f.write('---------------------- SOLVER OPTIONS-----------------------------------------\n')
×
2027
        f.write('{:<11s}'.format('Option'+'\n'))
×
2028
        f.write('{:<11s}'.format('(-)')+'\n')
×
2029
        f.write("\n".join(self.fst_vt['MAP']['Option']).strip() + '\n')
×
2030

2031
        f.flush()
×
2032
        os.fsync(f)
×
2033
        f.close()
×
2034

2035
    def write_MoorDyn(self):
1✔
2036

2037
        self.fst_vt['Fst']['MooringFile'] = self.FAST_namingOut + '_MoorDyn.dat'
1✔
2038
        moordyn_file = os.path.join(self.FAST_runDirectory, self.fst_vt['Fst']['MooringFile'])
1✔
2039
        f = open(moordyn_file, 'w')
1✔
2040

2041
        f.write('--------------------- MoorDyn Input File ------------------------------------\n')
1✔
2042
        f.write('Generated with AeroElasticSE FAST driver\n')
1✔
2043
        f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['MoorDyn']['Echo'], 'Echo', '- echo the input file data (flag)\n'))
1✔
2044
        f.write('----------------------- LINE TYPES ------------------------------------------\n')
1✔
2045
        f.write(" ".join(['{:^11s}'.format(i) for i in ['Name', 'Diam', 'MassDen', 'EA', 'BA/-zeta', 'EI', 'Cd', 'Ca', 'CdAx', 'CaAx']])+'\n')
1✔
2046
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)', '(m)', '(kg/m)', '(N)', '(N-s/-)', '(-)', '(-)', '(-)', '(-)', '(-)']])+'\n')
1✔
2047
        for i in range(len(self.fst_vt['MoorDyn']['Name'])):
1✔
2048
            ln = []
1✔
2049
            ln.append('{:^11}'.format(self.fst_vt['MoorDyn']['Name'][i]))
1✔
2050
            ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Diam'][i]))
1✔
2051
            ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['MassDen'][i]))
1✔
2052
            ln.append('{:^11.4e}'.format(self.fst_vt['MoorDyn']['EA'][i]))
1✔
2053
            ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['BA_zeta'][i]))
1✔
2054
            ln.append('{:^11.4e}'.format(self.fst_vt['MoorDyn']['EI'][i]))
1✔
2055
            ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Cd'][i]))
1✔
2056
            ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Ca'][i]))
1✔
2057
            ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['CdAx'][i]))
1✔
2058
            ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['CaAx'][i]))
1✔
2059
            f.write(" ".join(ln) + '\n')
1✔
2060
        f.write('---------------------- POINTS --------------------------------\n')
1✔
2061
        f.write(" ".join(['{:^11s}'.format(i) for i in ['ID', 'Attachment', 'X', 'Y', 'Z', 'M', 'V', 'CdA', 'CA']])+'\n')
1✔
2062
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)', '(-)', '(m)', '(m)', '(m)', '(kg)', '(m^3)', '(m^2)', '(-)']])+'\n')
1✔
2063
        for i in range(len(self.fst_vt['MoorDyn']['Point_ID'])):
1✔
2064
            ln = []
1✔
2065
            ln.append('{:^11d}'.format(self.fst_vt['MoorDyn']['Point_ID'][i]))
1✔
2066
            ln.append('{:^11}'.format(self.fst_vt['MoorDyn']['Attachment'][i]))
1✔
2067
            ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['X'][i]))
1✔
2068
            ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Y'][i]))
1✔
2069
            ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['Z'][i]))
1✔
2070
            ln.append('{:^11.4e}'.format(self.fst_vt['MoorDyn']['M'][i]))
1✔
2071
            ln.append('{:^11.4e}'.format(self.fst_vt['MoorDyn']['V'][i]))
1✔
2072
            ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['CdA'][i]))
1✔
2073
            ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['CA'][i]))
1✔
2074
            f.write(" ".join(ln) + '\n')
1✔
2075
        f.write('---------------------- LINES --------------------------------------\n')
1✔
2076
        f.write(" ".join(['{:^11s}'.format(i) for i in ['Line', 'LineType', 'AttachA', 'AttachB', 'UnstrLen', 'NumSegs',  'Outputs']])+'\n')
1✔
2077
        f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)', '(-)', '(-)', '(-)', '(m)', '(-)',  '(-)']])+'\n')
1✔
2078
        for i in range(len(self.fst_vt['MoorDyn']['Line_ID'])):
1✔
2079
            ln = []
1✔
2080
            ln.append('{:^11d}'.format(self.fst_vt['MoorDyn']['Line_ID'][i]))
1✔
2081
            ln.append('{:^11}'.format(self.fst_vt['MoorDyn']['LineType'][i]))
1✔
2082
            ln.append('{:^11d}'.format(self.fst_vt['MoorDyn']['AttachA'][i]))
1✔
2083
            ln.append('{:^11d}'.format(self.fst_vt['MoorDyn']['AttachB'][i]))
1✔
2084
            ln.append('{:^11.4f}'.format(self.fst_vt['MoorDyn']['UnstrLen'][i]))
1✔
2085
            ln.append('{:^11d}'.format(self.fst_vt['MoorDyn']['NumSegs'][i]))
1✔
2086
            ln.append('{:^11}'.format(self.fst_vt['MoorDyn']['Outputs'][i]))
1✔
2087
            f.write(" ".join(ln) + '\n')
1✔
2088

2089
        if self.fst_vt['MoorDyn']['ChannelID']: # There are control inputs
1✔
2090
            f.write('---------------------- CONTROL ---------------------------------------\n')
×
2091
            f.write(" ".join(['{:^11s}'.format(i) for i in ['ChannelID', 'Line(s)']])+'\n')
×
2092
            f.write(" ".join(['{:^11s}'.format(i) for i in ['()', '(,)']])+'\n')
×
2093
            for i_line in range(len(self.fst_vt['MoorDyn']['ChannelID'])):
×
2094
                ln = []
×
2095
                ln.append('{:^11d}'.format(self.fst_vt['MoorDyn']['ChannelID'][i_line]))
×
2096
                ln.append(','.join(self.fst_vt['MoorDyn']['Lines_Control'][i_line]))
×
2097
                f.write(" ".join(ln) + '\n')
×
2098

2099
        f.write('---------------------- SOLVER OPTIONS ---------------------------------------\n')
1✔
2100
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['MoorDyn']['dtM'], 'dtM', '- time step to use in mooring integration (s)\n'))
1✔
2101
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['MoorDyn']['kbot'], 'kbot', '- bottom stiffness (Pa/m)\n'))
1✔
2102
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['MoorDyn']['cbot'], 'cbot', '- bottom damping (Pa-s/m)\n'))
1✔
2103
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['MoorDyn']['dtIC'], 'dtIC', '- time interval for analyzing convergence during IC gen (s)\n'))
1✔
2104
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['MoorDyn']['TmaxIC'], 'TmaxIC', '- max time for ic gen (s)\n'))
1✔
2105
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['MoorDyn']['CdScaleIC'], 'CdScaleIC', '- factor by which to scale drag coefficients during dynamic relaxation (-)\n'))
1✔
2106
        f.write('{:<22} {:<11} {:}'.format(self.fst_vt['MoorDyn']['threshIC'], 'threshIC', '- threshold for IC convergence (-)\n'))
1✔
2107
        f.write('------------------------ OUTPUTS --------------------------------------------\n')
1✔
2108
        outlist = self.get_outlist(self.fst_vt['outlist'], ['MoorDyn'])
1✔
2109
        for channel_list in outlist:
1✔
2110
            for i in range(len(channel_list)):
1✔
2111
                f.write('"' + channel_list[i] + '"\n')
1✔
2112
        f.write('END\n')
1✔
2113
        f.write('------------------------- need this line --------------------------------------\n')
1✔
2114

2115
        f.flush()
1✔
2116
        os.fsync(f)
1✔
2117
        f.close()
1✔
2118
        
2119
        
2120
    def write_StC(self,StC_vt,StC_filename):
1✔
2121

2122
        stc_file = os.path.join(self.FAST_runDirectory, StC_filename)
1✔
2123
        f = open(stc_file, 'w')
1✔
2124
        
2125
        f.write('------- STRUCTURAL CONTROL (StC) INPUT FILE ----------------------------\n')
1✔
2126
        f.write('Generated with AeroElasticSE FAST driver within WEIS\n')
1✔
2127
        
2128
        f.write('---------------------- SIMULATION CONTROL --------------------------------------\n')
1✔
2129
        f.write('{!s:<22} {:<11} {:}'.format(StC_vt['Echo'], 'Echo', '- Echo input data to "<rootname>.SD.ech" (flag)\n'))
1✔
2130
        
2131
        f.write('---------------------- StC DEGREES OF FREEDOM ----------------------------------\n')
1✔
2132
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_DOF_MODE'], 'StC_DOF_MODE', '- DOF mode (switch) {0: No StC or TLCD DOF; 1: StC_X_DOF, StC_Y_DOF, and/or StC_Z_DOF (three independent StC DOFs); 2: StC_XY_DOF (Omni-Directional StC); 3: TLCD; 4: Prescribed force/moment time series}\n'))
1✔
2133
        f.write('{!s:<22} {:<11} {:}'.format(StC_vt['StC_X_DOF'], 'StC_X_DOF', '- DOF on or off for StC X (flag) [Used only when StC_DOF_MODE=1]\n'))
1✔
2134
        f.write('{!s:<22} {:<11} {:}'.format(StC_vt['StC_Y_DOF'], 'StC_Y_DOF', '- DOF on or off for StC Y (flag) [Used only when StC_DOF_MODE=1]\n'))
1✔
2135
        f.write('{!s:<22} {:<11} {:}'.format(StC_vt['StC_Z_DOF'], 'StC_Z_DOF', '- DOF on or off for StC Z (flag) [Used only when StC_DOF_MODE=1]\n'))
1✔
2136
        
2137
        f.write('---------------------- StC LOCATION ------------------------------------------- [relative to the reference origin of component attached to]\n')
1✔
2138
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_P_X'], 'StC_P_X', '- At rest X position of StC (m)\n'))
1✔
2139
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_P_Y'], 'StC_P_Y', '- At rest Y position of StC (m)\n'))
1✔
2140
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_P_Z'], 'StC_P_Z', '- At rest Z position of StC (m)\n'))
1✔
2141
        
2142
        f.write('---------------------- StC INITIAL CONDITIONS --------------------------------- [used only when StC_DOF_MODE=1 or 2]\n')
1✔
2143
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_X_DSP'], 'StC_X_DSP', '- StC X initial displacement (m) [relative to at rest position]\n'))
1✔
2144
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Y_DSP'], 'StC_Y_DSP', '- StC Y initial displacement (m) [relative to at rest position]\n'))
1✔
2145
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Z_DSP'], 'StC_Z_DSP', '- StC Z initial displacement (m) [relative to at rest position; used only when StC_DOF_MODE=1 and StC_Z_DOF=TRUE]\n'))
1✔
2146
        f.write('{!s:<22} {:<11} {:}'.format(StC_vt['StC_Z_PreLd'], 'StC_Z_PreLd', '- StC Z pre-load (N) {"gravity" to offset for gravity load; "none" or 0 to turn off} [used only when StC_DOF_MODE=1 and StC_Z_DOF=TRUE]\n'))
1✔
2147
        
2148
        f.write('---------------------- StC CONFIGURATION -------------------------------------- [used only when StC_DOF_MODE=1 or 2]\n')
1✔
2149
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_X_PSP'], 'StC_X_PSP', '- Positive stop position (maximum X mass displacement) (m)\n'))
1✔
2150
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_X_NSP'], 'StC_X_NSP', '- Negative stop position (minimum X mass displacement) (m)\n'))
1✔
2151
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Y_PSP'], 'StC_Y_PSP', '- Positive stop position (maximum Y mass displacement) (m)\n'))
1✔
2152
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Y_NSP'], 'StC_Y_NSP', '- Negative stop position (minimum Y mass displacement) (m)\n'))
1✔
2153
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Z_PSP'], 'StC_Z_PSP', '- Positive stop position (maximum Z mass displacement) (m) [used only when StC_DOF_MODE=1 and StC_Z_DOF=TRUE]\n'))
1✔
2154
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Z_NSP'], 'StC_Z_NSP', '- Negative stop position (minimum Z mass displacement) (m) [used only when StC_DOF_MODE=1 and StC_Z_DOF=TRUE]\n'))
1✔
2155
        
2156
        f.write('---------------------- StC MASS, STIFFNESS, & DAMPING ------------------------- [used only when StC_DOF_MODE=1 or 2]\n')
1✔
2157
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_X_M'], 'StC_X_M', '- StC X mass (kg) [must equal StC_Y_M for StC_DOF_MODE = 2]\n'))
1✔
2158
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Y_M'], 'StC_Y_M', '- StC Y mass (kg) [must equal StC_X_M for StC_DOF_MODE = 2]\n'))
1✔
2159
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Z_M'], 'StC_Z_M', '- StC Z mass (kg) [used only when StC_DOF_MODE=1 and StC_Z_DOF=TRUE]\n'))
1✔
2160
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_XY_M'], 'StC_XY_M', '- StC Z mass (kg) [used only when StC_DOF_MODE=2]\n'))
1✔
2161
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_X_K'], 'StC_X_K', '- StC X stiffness (N/m)\n'))
1✔
2162
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Y_K'], 'StC_Y_K', '- StC Y stiffness (N/m)\n'))
1✔
2163
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Z_K'], 'StC_Z_K', '- StC Z stiffness (N/m) [used only when StC_DOF_MODE=1 and StC_Z_DOF=TRUE]\n'))
1✔
2164
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_X_C'], 'StC_X_C', '- StC X damping (N/(m/s))\n'))
1✔
2165
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Y_C'], 'StC_Y_C', '- StC Y damping (N/(m/s))\n'))
1✔
2166
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Z_C'], 'StC_Z_C', '- StC Z damping (N/(m/s)) [used only when StC_DOF_MODE=1 and StC_Z_DOF=TRUE]\n'))
1✔
2167
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_X_KS'], 'StC_X_KS', '- Stop spring X stiffness (N/m)\n'))
1✔
2168
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Y_KS'], 'StC_Y_KS', '- Stop spring Y stiffness (N/m)\n'))
1✔
2169
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Z_KS'], 'StC_Z_KS', '- Stop spring Z stiffness (N/m) [used only when StC_DOF_MODE=1 and StC_Z_DOF=TRUE]\n'))
1✔
2170
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_X_CS'], 'StC_X_CS', '- Stop spring X damping (N/(m/s))\n'))
1✔
2171
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Y_CS'], 'StC_Y_CS', '- Stop spring Y damping (N/(m/s))\n'))
1✔
2172
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Z_CS'], 'StC_Z_CS', '- Stop spring Z damping (N/(m/s)) [used only when StC_DOF_MODE=1 and StC_Z_DOF=TRUE]\n'))
1✔
2173
        
2174
        f.write('---------------------- StC USER-DEFINED SPRING FORCES ------------------------- [used only when StC_DOF_MODE=1 or 2]\n')
1✔
2175
        f.write('{!s:<22} {:<11} {:}'.format(StC_vt['Use_F_TBL'], 'Use_F_TBL', '- Use spring force from user-defined table (flag)\n'))
1✔
2176
        f.write('{:<22} {:<11} {:}'.format(StC_vt['NKInpSt'], 'NKInpSt', '- Number of spring force input stations\n'))
1✔
2177
        
2178
        f.write('---------------------- StC SPRING FORCES TABLE -------------------------------- [used only when StC_DOF_MODE=1 or 2]\n')
1✔
2179
        f.write('X                F_X               Y              F_Y              Z              F_Z\n')
1✔
2180
        f.write('(m)               (N)              (m)             (N)             (m)             (N)\n')
1✔
2181
        table = StC_vt['SpringForceTable']
1✔
2182
        for x, f_x, y, f_y, z, f_z in zip(table['X'],table['F_X'],table['Y'],table['F_Y'],table['Z'],table['F_Z']):
1✔
2183
            row = [x, f_x, y, f_y, z, f_z]
1✔
2184
            f.write(' '.join(['{: 2.8e}'.format(val) for val in row])+'\n')
1✔
2185
        
2186
        f.write('---------------------- StructCtrl CONTROL -------------------------------------------- [used only when StC_DOF_MODE=1 or 2]\n')
1✔
2187
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_CMODE'],     'StC_CMODE',        '- Control mode (switch) {0:none; 1: Semi-Active Control Mode; 2: Active Control Mode}\n'))
1✔
2188
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_CChan'],     'StC_CChan',        '- Control channel group (1:10) for stiffness and damping (StC_[XYZ]_K, StC_[XYZ]_C, and StC_[XYZ]_Brake) (specify additional channels for blade instances of StC active control -- one channel per blade) [used only when StC_DOF_MODE=1 or 2, and StC_CMODE=4 or 5]\n'))
1✔
2189
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_SA_MODE'],   'StC_SA_MODE',      '- Semi-Active control mode {1: velocity-based ground hook control; 2: Inverse velocity-based ground hook control; 3: displacement-based ground hook control 4: Phase difference Algorithm with Friction Force 5: Phase difference Algorithm with Damping Force} (-)\n'))
1✔
2190
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_X_C_HIGH'],  'StC_X_C_HIGH',     '- StC X high damping for ground hook control\n'))
1✔
2191
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_X_C_LOW'],   'StC_X_C_LOW',      '- StC X low damping for ground hook control\n'))
1✔
2192
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Y_C_HIGH'],  'StC_Y_C_HIGH',     '- StC Y high damping for ground hook control\n'))
1✔
2193
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Y_C_LOW'],   'StC_Y_C_LOW',      '- StC Y low damping for ground hook control\n'))
1✔
2194
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Z_C_HIGH'],  'StC_Z_C_HIGH',     '- StC Z high damping for ground hook control [used only when StC_DOF_MODE=1 and StC_Z_DOF=TRUE]\n'))
1✔
2195
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Z_C_LOW'],   'StC_Z_C_LOW',      '- StC Z low damping for ground hook control  [used only when StC_DOF_MODE=1 and StC_Z_DOF=TRUE]\n'))
1✔
2196
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_X_C_BRAKE'], 'StC_X_C_BRAKE',    '- StC X high damping for braking the StC (Don''t use it now. should be zero)\n'))
1✔
2197
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Y_C_BRAKE'], 'StC_Y_C_BRAKE',    '- StC Y high damping for braking the StC (Don''t use it now. should be zero)\n'))
1✔
2198
        f.write('{:<22} {:<11} {:}'.format(StC_vt['StC_Z_C_BRAKE'], 'StC_Z_C_BRAKE',    '- StC Z high damping for braking the StC (Don''t use it now. should be zero) [used only when StC_DOF_MODE=1 and StC_Z_DOF=TRUE]\n'))
1✔
2199

2200
        f.write('---------------------- TLCD --------------------------------------------------- [used only when StC_DOF_MODE=3]\n')
1✔
2201
        f.write('{:<22} {:<11} {:}'.format(StC_vt['L_X'], 'L_X', '- X TLCD total length (m)\n'))
1✔
2202
        f.write('{:<22} {:<11} {:}'.format(StC_vt['B_X'], 'B_X', '- X TLCD horizontal length (m)\n'))
1✔
2203
        f.write('{:<22} {:<11} {:}'.format(StC_vt['area_X'], 'area_X', '- X TLCD cross-sectional area of vertical column (m^2)\n'))
1✔
2204
        f.write('{:<22} {:<11} {:}'.format(StC_vt['area_ratio_X'], 'area_ratio_X', '- X TLCD cross-sectional area ratio (vertical column area divided by horizontal column area) (-)\n'))
1✔
2205
        f.write('{:<22} {:<11} {:}'.format(StC_vt['headLossCoeff_X'], 'headLossCoeff_X', '- X TLCD head loss coeff (-)\n'))
1✔
2206
        f.write('{:<22} {:<11} {:}'.format(StC_vt['rho_X'], 'rho_X', '- X TLCD liquid density (kg/m^3)\n'))
1✔
2207
        f.write('{:<22} {:<11} {:}'.format(StC_vt['L_Y'], 'L_Y', '- Y TLCD total length (m)\n'))
1✔
2208
        f.write('{:<22} {:<11} {:}'.format(StC_vt['B_Y'], 'B_Y', '- Y TLCD horizontal length (m)\n'))
1✔
2209
        f.write('{:<22} {:<11} {:}'.format(StC_vt['area_Y'], 'area_Y', '- Y TLCD cross-sectional area of vertical column (m^2)\n'))
1✔
2210
        f.write('{:<22} {:<11} {:}'.format(StC_vt['area_ratio_Y'], 'area_ratio_Y', '- Y TLCD cross-sectional area ratio (vertical column area divided by horizontal column area) (-)\n'))
1✔
2211
        f.write('{:<22} {:<11} {:}'.format(StC_vt['headLossCoeff_Y'], 'headLossCoeff_Y', '- Y TLCD head loss coeff (-)\n'))
1✔
2212
        f.write('{:<22} {:<11} {:}'.format(StC_vt['rho_Y'], 'rho_Y', '- Y TLCD liquid density (kg/m^3)\n'))
1✔
2213
        
2214
        f.write('---------------------- PRESCRIBED TIME SERIES --------------------------------- [used only when StC_DOF_MODE=4]\n')
1✔
2215
        f.write('{:<22} {:<11} {:}'.format(StC_vt['PrescribedForcesCoord'], 'PrescribedForcesCoord',    '- Prescribed forces are in global or local coordinates (switch) {1: global; 2: local}\n'))
1✔
2216
        f.write('{!s:<22} {:<11} {:}'.format(StC_vt['PrescribedForcesFile'], 'PrescribedForcesFile', '- Time series force and moment (7 columns of time, FX, FY, FZ, MX, MY, MZ)\n'))
1✔
2217
        f.write('-------------------------------------------------------------------------------\n')
1✔
2218

2219
        f.flush()
1✔
2220
        os.fsync(f)
1✔
2221
        f.close()
1✔
2222

2223
if __name__=="__main__":
1✔
2224

2225
    fst_update = {}
×
2226
    fst_update['Fst', 'TMax'] = 20.
×
2227
    fst_update['AeroDyn15', 'TwrAero'] = False
×
2228

2229
    examples_dir = os.path.dirname( os.path.dirname( os.path.dirname( os.path.realpath(__file__) ) ) ) + os.sep
×
2230

2231
    # Read the model
2232
    fast = InputReader_OpenFAST()
×
2233
    fast.FAST_InputFile = 'IEA-15-240-RWT-UMaineSemi.fst'   # FAST input file (ext=.fst)
×
2234
    fast.FAST_directory = os.path.join(examples_dir, 'examples', '01_aeroelasticse',
×
2235
                                                     'OpenFAST_models', 'IEA-15-240-RWT',
2236
                                                     'IEA-15-240-RWT-UMaineSemi')   # Path to fst directory files
2237
    fast.execute()
×
2238
    
2239
    # Write out the model
2240
    fastout = InputWriter_OpenFAST()
×
2241
    fastout.fst_vt = fast.fst_vt
×
2242
    fastout.FAST_runDirectory = 'temp/OpenFAST'
×
2243
    fastout.FAST_namingOut = 'iea15'
×
2244
    fastout.update(fst_update=fst_update)
×
2245
    fastout.execute()
×
2246

2247
    # import pickle
2248
    # with open('fst_vt.pkl','rb') as f:
2249
    #     fst_vt = pickle.load(f)
2250

2251
    # fastout = InputWriter_OpenFAST()
2252
    # fastout.FAST_runDirectory = 'none'
2253

2254
    # fst_vt['TStC'][0]['NKInpSt']      = 2
2255

2256
    # for i_TStC, TStC in enumerate(fst_vt['TStC']):
2257
    #     fastout.write_StC(TStC,fst_vt['ServoDyn']['TStCfiles'][i_TStC])
2258
    # print('here')
2259

2260

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc