def PowerCurveParametricExample1(): """ Example to run a set of FAST simulations to determine a power curve. In this example, the WS, RPM and Pitch are set within a for loop. If the controller and generator are active, these are just "initial conditions". Additional parameters may be set by adjusting the BaseDict. This script is based on a reference directory which contains a reference main input file (.fst) Everything is copied to a working directory. The different fast inputs are generated based on a list of dictionaries, named `PARAMS`. For each dictionary: - they keys are "path" to a input parameter, e.g. `EDFile|RotSpeed` or `TMax`. These should correspond to whater name of the variable is used in the FAST inputs files. - they values are the values corresponding to this parameter """ # --- Parameters for this script FAST_EXE = os.path.join(MyDir, '../../../data/openfast.exe') # Location of a FAST exe (and dll) ref_dir = os.path.join(MyDir, '../../../data/NREL5MW/') # Folder where the fast input files are located (will be copied) main_file = 'Main_Onshore_OF2.fst' # Main file in ref_dir, used as a template work_dir = '_NREL5MW_PowerCurveParametric/' # Output folder (will be created) # --- Defining the parametric study (list of dictionnaries with keys as FAST parameters) WS = [3,5,7,9 ,11,13,15] RPM = [5,6,7,10,10,10,10] # initial conditions PITCH = [0,0,0,0 ,5 ,10,15] # initial conditions BaseDict = {'TMax': 100, 'DT': 0.01, 'DT_Out': 0.1} #BaseDict = case_gen.paramsNoController(BaseDict) #BaseDict = case_gen.paramsStiff(BaseDict) #BaseDict = case_gen.paramsNoGen(BaseDict) PARAMS=[] for wsp,rpm,pitch in zip(WS,RPM,PITCH): # NOTE: same length of WS and RPM otherwise do multiple for loops p=BaseDict.copy() p['EDFile|RotSpeed'] = rpm p['EDFile|BlPitch(1)'] = pitch p['EDFile|BlPitch(2)'] = pitch p['EDFile|BlPitch(3)'] = pitch p['InflowFile|HWindSpeed'] = wsp p['InflowFile|WindType'] = 1 # Setting steady wind p['__name__'] = 'ws{:04.1f}'.format(p['InflowFile|HWindSpeed']) PARAMS.append(p) # --- Generating all files in a workdir fastFiles=case_gen.templateReplace(PARAMS, ref_dir, work_dir, removeRefSubFiles=True, main_file=main_file) print(fastFiles) # --- Creating a batch script just in case runner.writeBatch(os.path.join(work_dir,'_RUN_ALL.bat'), fastFiles,fastExe=FAST_EXE) # --- Running the simulations print('>>> Running {} simulations in {} ...'.format(len(fastFiles), work_dir)) runner.run_fastfiles(fastFiles, fastExe=FAST_EXE, parallel=True, showOutputs=False, nCores=2) # --- Simple Postprocessing outFiles = [os.path.splitext(f)[0]+'.outb' for f in fastFiles] avg_results = postpro.averagePostPro(outFiles,avgMethod='constantwindow',avgParam=10, ColMap = {'WS_[m/s]':'Wind1VelX_[m/s]'},ColSort='WS_[m/s]') print('>>> Average results:') print(avg_results) avg_results.to_csv('_PowerCurve1.csv',sep='\t',index=False)
def main(): # --- Main Parameters ref_dir = os.path.join( MyDir, '../../../data/NREL5MW/' ) # Folder where the fast input files are located (will be copied) FAST_EXE = os.path.join( MyDir, '../../../data/openfast.exe') # Location of a FAST exe (and dll) main_file = 'Main_Onshore_OF2.fst' # Main file in ref_dir, used as a template work_dir = '_NREL5MW_ParametricExcel/' # Output folder (will be created) parametricFile = 'ParametricExcel.xlsx' # Excel file containing set of parameters # --- Reading Excel file, converting it to a list of dictionaries, and generate input files dfs = io.excel_file.ExcelFile(parametricFile).toDataFrame() df = dfs[list(dfs.keys())[0]] PARAMS = df.to_dict('records') print(df) fastFiles = case_gen.templateReplace(PARAMS, ref_dir, outputDir=work_dir, removeRefSubFiles=True, removeAllowed=False, main_file=main_file) # --- Running fast simulations print('>>> Running {} simulations in {} ...'.format( len(fastFiles), work_dir)) runner.writeBatch(os.path.join(work_dir, '_RUN_ALL.bat'), fastFiles, fastExe=FAST_EXE) runner.run_fastfiles(fastFiles, showOutputs=False, fastExe=FAST_EXE, nCores=4) # --- Postpro - Computing averages at the end of the simluation print('>>> Postprocessing...') outFiles = [os.path.splitext(f)[0] + '.outb' for f in fastFiles] ColKeepStats = [ 'RotSpeed_[rpm]', 'BldPitch1_[deg]', 'RtAeroCp_[-]', 'RtAeroCt_[-]', 'Wind1VelX_[m/s]' ] result = postpro.averagePostPro(outFiles, avgMethod='constantwindow', avgParam=5, ColKeep=ColKeepStats, ColSort='RotSpeed_[rpm]') result.to_csv('ParametricExcel_Summary.csv', sep='\t', index=False) print('Average values saved to _ParametricExcel_Summary.csv')
def PowerCurveParametricExample2(): """ Example to run a set of FAST simulations to determine a power curve. In this example, the WS, RPM and Pitch are set within a for loop. If the controller and generator are active, these are just "initial conditions". Additional parameters may be set by adjusting the BaseDict. This script is based on a reference directory which contains a reference main input file (.fst) Everything is copied to a working directory. The different fast inputs are generated based on a list of dictionaries, named `PARAMS`. For each dictionary: - they keys are "path" to a input parameter, e.g. `EDFile|RotSpeed` or `TMax`. These should correspond to whater name of the variable is used in the FAST inputs files. - they values are the values corresponding to this parameter """ # --- Parameters for this script FAST_EXE = os.path.join(MyDir, '../../../data/openfast.exe') # Location of a FAST exe (and dll) ref_dir = os.path.join(MyDir, '../../../data/NREL5MW/') # Folder where the fast input files are located (will be copied) main_file = 'Main_Onshore_OF2.fst' # Main file in ref_dir, used as a template work_dir = '_NREL5MW_PowerCurveParametric2/' # Output folder (will be created) out_Ext = '.outb' # Output extension # --- Defining the parametric study (list of dictionnaries with keys as FAST parameters) WS = [3,5,7,9 ,11,13,15] RPM = [5,6,7,10,10,10,10] PITCH = [0,0,0,0 ,5 ,10,15] BaseDict = {'TMax': 10, 'DT': 0.01, 'DT_Out': 0.1} PARAMS = case_gen.paramsWS_RPM_Pitch(WS, RPM, PITCH, baseDict=BaseDict, flatInputs=True) # --- Generating all files in a workdir fastFiles = case_gen.templateReplace(PARAMS, ref_dir, work_dir, removeRefSubFiles=True, removeAllowed=True, main_file=main_file) # --- Creating a batch script just in case runner.writeBatch(os.path.join(work_dir,'_RUN_ALL.bat'), fastFiles,fastExe=FAST_EXE) # --- Running the simulations runner.run_fastfiles(fastFiles, fastExe=FAST_EXE, parallel=True, showOutputs=False, nCores=2) # --- Simple Postprocessing outFiles = [os.path.splitext(f)[0]+out_Ext for f in fastFiles] avg_results = postpro.averagePostPro(outFiles,avgMethod='constantwindow',avgParam=10, ColMap = {'WS_[m/s]':'Wind1VelX_[m/s]'},ColSort='WS_[m/s]') print('>>> Average results:') print(avg_results) avg_results.to_csv('_PowerCurve2.csv',sep='\t',index=False)
def run_linearization(): """ Example to run a set of OpenFAST simulations (linearizations) This script uses a reference directory (`ref_dir`) which contains a reference input file (.fst) 1) The reference directory is copied to a working directory (`out_dir`). 2) All the fast input files are generated in this directory based on a list of dictionaries (`PARAMS`). For each dictionary in this list: - The keys are "path" to a input parameter, e.g. `EDFile|RotSpeed` or `FAST|TMax`. These should correspond to the variables used in the FAST inputs files. - The values are the values corresponding to this parameter For instance: PARAMS[0]['DT'] = 0.01 PARAMS[0]['EDFile|RotSpeed'] = 5 PARAMS[0]['InflowFile|HWindSpeed'] = 10 3) The simulations are run, successively distributed on `nCores` CPUs. 4) The output files are read, and averaged based on a method (e.g. average over a set of periods, see averagePostPro in postpro for the different averaging methods). A pandas DataFrame is returned """ # --- Parameters for this script of_dir = '/home/equon/WEIS/local' this_dir = os.path.dirname(__file__) ref_dir = '../OpenFAST' # Folder where the fast input files are located (will be copied) out_dir = os.path.join(this_dir,'outputs') # Output folder (will be created) main_file = 'NREL-1p7-103.fst' # Main file in ref_dir, used as a template FAST_EXE = os.path.join(of_dir,'bin/openfast') # Location of a FAST exe (and dll) # --- Read outputs from OF power curve to get operating points (EWQ) #op = pd.read_csv('../NREL-1.7-103_openfast.csv').set_index('Wind1VelX_[m/s]') op = pd.read_csv('../NREL-1.7-103_openfast.csv').set_index('rotor speed [RPM]') op = op.loc[op['Wind1VelX_[m/s]'] <= 11] GenTorque = op['generator torque [kN-m]'] * 1000. minRotSpeed = op.index[0] # --- Defining the parametric study (list of dictionnaries with keys as FAST parameters) LinStart = 600.0 BaseDict = {'TMax': 660.0} BaseDict = case_gen.paramsLinearTrim(BaseDict) # Run linear trim case print(BaseDict) RotSpeeds = np.arange(0,17) PARAMS=[] for i,rpm in enumerate(RotSpeeds): p=BaseDict.copy() GenTq = np.interp(rpm, GenTorque.index, GenTorque, left=1e-9) # Turn off aero p['CompAero'] = 0 p['CompInflow'] = 0 # Turn on all pertinent structural DOFs p['EDFile|FlapDOF1'] = 'True' p['EDFile|FlapDOF2'] = 'True' p['EDFile|EdgeDOF'] = 'True' p['EDFile|DrTrDOF'] = 'True' p['EDFile|GenDOF'] = 'False' #'True' p['EDFile|TwFADOF1'] = 'True' p['EDFile|TwFADOF2'] = 'True' p['EDFile|TwSSDOF1'] = 'True' p['EDFile|TwSSDOF2'] = 'True' # rated generator speed, torque, control params #p['ServoFile|VS_RtGnSp'] = 1429.36707 * .9 # Rated generator speed [RPM] #p['ServoFile|VS_RtTq'] = 12389.06909 # Rated torque, from DISCON.IN [Nm] #p['ServoFile|VS_Rgn2K'] = 0.006851918024 # Generator torque const, from DISCON.IN [Nm/RPM^2] #p['ServoFile|VS_SlPc'] = 10. # const generator torque # https://github.com/OpenFAST/openfast/issues/478#issuecomment-649819664 #p['ServoFile|VS_RtTq'] = np.interp(rpm, GenTorque.index, GenTorque, left=1e-9) p['ServoFile|VS_RtTq'] = GenTq p['ServoFile|VS_RtGnSp'] = 1e-9 p['ServoFile|VS_Rgn2K'] = 1e-9 p['ServoFile|VS_SlPc'] = 1e-9 # Operating conditions p['EDFile|RotSpeed'] = rpm p['EDFile|BlPitch(1)'] = 0.0 p['EDFile|BlPitch(2)'] = 0.0 p['EDFile|BlPitch(3)'] = 0.0 # Set number of linearizations #p['TrimCase'] = 2 p['CalcSteady'] = 'False' #p['OutFmt'] = 'E20.12' if rpm > 0: p['NLinTimes'] = 36 LinTimes = np.linspace(LinStart, LinStart+60./rpm, num=p['NLinTimes'], endpoint=False) p['LinTimes'] = np.array_str(LinTimes, max_line_width=9000, precision=3)[1:-1] else: p['NLinTimes'] = 1 p['LinTimes'] = f'{LinStart:.3f}' p['TMax'] = LinStart # Set case name p['__name__'] = f'{i:03d}_{rpm:.1f}rpm' PARAMS.append(p) # --- Generating all files in a output directory fastfiles=case_gen.templateReplace(PARAMS,ref_dir,outputDir=out_dir,removeRefSubFiles=True,main_file=main_file, oneSimPerDir=False) print(fastfiles) # --- Creating a batch script just in case #runner.writeBatch(os.path.join(out_dir,'_RUN_ALL.bat'),fastfiles,fastExe=FAST_EXE) # --- Running the simulations if parallel_flag: nCores = min(len(RotSpeeds), os.cpu_count()) runner.run_fastfiles(fastfiles,fastExe=FAST_EXE,parallel=True,showOutputs=True,nCores=nCores) else: #runner.run_fastfiles(fastfiles,fastExe=FAST_EXE,parallel=False,showOutputs=True) # causes error when calling wait() runner.run_fastfiles(fastfiles,fastExe=FAST_EXE,parallel=True,showOutputs=True,nCores=1) # --- Simple Postprocessing # (averaging each signal over the last period for each simulation) outFiles = [os.path.splitext(f)[0]+'.outb' for f in fastfiles] # avg_results = postpro.averagePostPro(outFiles, avgMethod='periods', avgParam=1, ColMap = {'WS_[m/s]':'Wind1VelX_[m/s]'},ColSort='WS_[m/s]') # avg_results.drop('Time_[s]',axis=1, inplace=True) return outFiles
def writeLinearizationFiles(main_fst, workDir, operatingPointsFile, nPerPeriod=36, baseDict=None, tStart=100, LinInputs=0, LinOutputs=0): """ Write FAST inputs files for linearization, to a given directory `workDir`. INPUTS: - main_fst: path to an existing .fst file This file (and the ones it refers to) will be used as templates. Values of the templates can be modified using `baseDict`. The parent directory of the main fst file will be copied to `workDir`. - workDir: directory (will be created) where the simulation files will be generated - operatingPointsFile: csv file containing operating conditions - nPerPeriod : number of linearization points per rotation (usually 12 or 36) - baseDict : a dictionary of inputs files keys to be applied to all simulations Ignored if not provided. e.g. baseDict={'DT':0.01, 'EDFile|ShftTilt':-5, 'InflowFile|PLexp':0.0} see templateReplaceGeneral. - tStart: time at which the linearization will start. When triming option is not available, this needs to be sufficiently large for the rotor to reach an equilibrium - LinInputs: linearize wrt. inputs (see OpenFAST documentation). {0,1,2, default:1} - LinOutputs: linearize wrt. outputs (see OpenFAST documentation). {0,1, default:0} OUTPUTS: - list of fst files created """ # --- Optional values if baseDict is None: baseDict = dict() # --- Checking main fst file fst = FASTInputFile(main_fst) hasTrim = 'TrimCase' in fst.keys() if fst['CompServo'] == 1: print('[WARN] For now linearization is done without controller.') baseDict['CompServo'] = 0 # --- Reading operating points OP = readOperatingPoints(operatingPointsFile) # --- Generating list of parameters that vary based on the operating conditions provided PARAMS = [] for i, op in OP.iterrows(): # Extract operating conditions (TODO, handling of missing fields) ws = op['WindSpeed_[m/s]'] rpm = op['RotorSpeed_[rpm]'] pitch = op['PitchAngle_[deg]'] filename = op['Filename_[-]'] # TODO gen trq or Tower top displacement # Determine linearization times based on RPM and nPerPeriod Omega = rpm / 60 * 2 * np.pi if abs(Omega) < 0.001: LinTimes = [tStart] Tmax = tStart + 1 else: T = 2 * np.pi / Omega LinTimes = np.linspace(tStart, tStart + T, nPerPeriod + 1)[:-1] Tmax = tStart + 1.01 * T # --- Creating "linDict", dictionary of changes to fast input files for linearization linDict = dict() linDict['__name__'] = os.path.splitext(filename)[0] # --- Main fst options linDict['TMax'] = Tmax linDict['TStart'] = 0 if abs(ws) < 0.001: linDict['CompAero'] = 0 linDict['CompInflow'] = 0 # --- Linearization options linDict['Linearize'] = True linDict['NLinTimes'] = len(LinTimes) linDict['LinTimes'] = list(LinTimes) linDict['OutFmt'] = '"ES20.12E3"' # Important for decent resolution linDict[ 'LinInputs'] = LinInputs # 0: none, 1: standard, 2: to get full linearizations linDict['LinOutputs'] = LinOutputs # 0: none, 1: based on outlist # --- New Linearization options # TrimCase - Controller parameter to be trimmed {1:yaw; 2:torque; 3:pitch} [used only when CalcSteady=True] # TrimTol - Tolerance for the rotational speed convergence [>eps] [used only when CalcSteady=True] # TrimGain - Proportional gain for the rotational speed error (rad/(rad/s) or Nm/(rad/s)) [>0] [used only when CalcSteady=True] # Twr_Kdmp - Damping factor for the tower (N/(m/s)) [>=0] [used only when CalcSteady=True] # Bld_Kdmp - Damping factor for the blade (N/(m/s)) [>=0] [used only when CalcSteady=True] # --- Mode shape vizualization options if hasTrim: linDict['WrVTK'] = 3 linDict['VTK_type'] = 1 linDict['VTK_fields'] = True linDict['VTK_fps'] = 30 else: linDict['WrVTK'] = 0 # --- Aero options linDict['AeroFile|WakeMod'] = 1 # Needed for linearization linDict['AeroFile|AFAeroMod'] = 1 # Needed for linearization linDict['AeroFile|FrozenWake'] = True # Needed for linearization # --- Inflow options linDict['InflowFile|WindType'] = 1 linDict['InflowFile|HWindSpeed'] = ws # --- ElastoDyn options linDict['EDFile|BlPitch(1)'] = pitch linDict['EDFile|BlPitch(2)'] = pitch linDict['EDFile|BlPitch(3)'] = pitch linDict['EDFile|RotSpeed'] = rpm #linDict['EDFile|TTDspFA'] = tt # --- Servo options # --- Merging linDict dictionary with user override inputs for k, v in baseDict.items(): if k in linDict and v != linDict[k]: print('Overriding key {} with value {} (previous value {})'. format(k, v, linDict[k])) linDict[k] = v PARAMS.append(linDict) # --- Generating all files in a workDir refDir = os.path.dirname(main_fst) main_file = os.path.basename(main_fst) fastfiles = templateReplace(PARAMS, refDir, outputDir=workDir, removeRefSubFiles=True, main_file=main_file) return fastfiles
def ParametricExample(): """ Example to run a set of OpenFAST simulations (parametric study) This script uses a reference directory (`ref_dir`) which contains a reference input file (.fst) 1) The reference directory is copied to a working directory (`out_dir`). 2) All the fast input files are generated in this directory based on a list of dictionaries (`PARAMS`). For each dictionary in this list: - The keys are "path" to a input parameter, e.g. `EDFile|RotSpeed` or `FAST|TMax`. These should correspond to the variables used in the FAST inputs files. - The values are the values corresponding to this parameter For instance: PARAMS[0]['DT'] = 0.01 PARAMS[0]['EDFile|RotSpeed'] = 5 PARAMS[0]['InflowFile|HWindSpeed'] = 10 3) The simulations are run, successively distributed on `nCores` CPUs. 4) The output files are read, and averaged based on a method (e.g. average over a set of periods, see averagePostPro in postpro for the different averaging methods). A pandas DataFrame is returned """ # --- Parameters for this script ref_dir = 'NREL5MW/' # Folder where the fast input files are located (will be copied) out_dir = 'NREL5MW_Parametric/' # Output folder (will be created) main_file = 'Main_Onshore_OF2.fst' # Main file in ref_dir, used as a template FAST_EXE = 'openfast2.3_x64s.exe' # Location of a FAST exe (and dll) # --- Defining the parametric study (list of dictionnaries with keys as FAST parameters) WS = [3, 5, 6, 7] RPM = [10, 12, 13, 15] BaseDict = {'TMax': 10, 'DT': 0.01, 'DT_Out': 0.1} BaseDict = case_gen.paramsNoController(BaseDict) # Remove the controller #BaseDict = case_gen.paramsControllerDLL(BaseDict) # Activate the controller #BaseDict = case_gen.paramsStiff(BaseDict) # Make the turbine stiff (except generator) #BaseDict = case_gen.paramsNoGen(BaseDict) # Remove the Generator DOF PARAMS = [] for i, (wsp, rpm) in enumerate( zip(WS, RPM) ): # NOTE: same length of WS and RPM otherwise do multiple for loops p = BaseDict.copy() #p['AeroFile|TwrAero'] = True #p['EDFile|BldFile(1)|AdjBlMs'] =1.1 #p['EDFile|BldFile(2)|AdjBlMs'] =1.1 #p['EDFile|BldFile(3)|AdjBlMs'] =1.1 p['EDFile|RotSpeed'] = rpm p['InflowFile|HWindSpeed'] = wsp p['InflowFile|WindType'] = 1 # Setting steady wind p['__name__'] = '{:03d}_ws{:04.1f}_om{:04.2f}'.format( i, p['InflowFile|HWindSpeed'], p['EDFile|RotSpeed']) PARAMS.append(p) i = i + 1 # --- Generating all files in a output directory fastfiles = case_gen.templateReplace(PARAMS, ref_dir, outputDir=out_dir, removeRefSubFiles=True, main_file=main_file, oneSimPerDir=False) print(fastfiles) # --- Creating a batch script just in case runner.writeBatch(os.path.join(out_dir, '_RUN_ALL.bat'), fastfiles, fastExe=FAST_EXE) # --- Running the simulations runner.run_fastfiles(fastfiles, fastExe=FAST_EXE, parallel=True, showOutputs=False, nCores=4) # --- Simple Postprocessing # (averaging each signal over the last period for each simulation) outFiles = [os.path.splitext(f)[0] + '.outb' for f in fastfiles] avg_results = postpro.averagePostPro( outFiles, avgMethod='periods', avgParam=1, ColMap={'WS_[m/s]': 'Wind1VelX_[m/s]'}, ColSort='WS_[m/s]') avg_results.drop('Time_[s]', axis=1, inplace=True) print(avg_results) return avg_results
def run_linearization(): """ Example to run a set of OpenFAST simulations (linearizations) This script uses a reference directory (`ref_dir`) which contains a reference input file (.fst) 1) The reference directory is copied to a working directory (`out_dir`). 2) All the fast input files are generated in this directory based on a list of dictionaries (`PARAMS`). For each dictionary in this list: - The keys are "path" to a input parameter, e.g. `EDFile|RotSpeed` or `FAST|TMax`. These should correspond to the variables used in the FAST inputs files. - The values are the values corresponding to this parameter For instance: PARAMS[0]['DT'] = 0.01 PARAMS[0]['EDFile|RotSpeed'] = 5 PARAMS[0]['InflowFile|HWindSpeed'] = 10 3) The simulations are run, successively distributed on `nCores` CPUs. 4) The output files are read, and averaged based on a method (e.g. average over a set of periods, see averagePostPro in postpro for the different averaging methods). A pandas DataFrame is returned """ # --- Parameters for this script of_dir = '/Users/dzalkind/Tools/openfast-dev' # openfast dir, using dev branch as of Jan-14 this_dir = os.path.dirname(__file__) ref_dir = '/Users/dzalkind/Tools/ROSCO_toolbox/Test_Cases/NREL-5MW' # Folder where the fast input files are located (will be copied) out_dir = os.path.join( this_dir, 'NREL-5MW_Linear/') # Output folder (will be created) main_file = 'NREL-5MW.fst' # Main file in ref_dir, used as a template FAST_EXE = os.path.join( of_dir, 'install/bin/openfast') # Location of a FAST exe (and dll) # --- Defining the parametric study (list of dictionnaries with keys as FAST parameters) WS = [14, 16, 18] BaseDict = {'TMax': 600} BaseDict = case_gen.paramsLinearTrim(BaseDict) # Run linear trim case PARAMS = [] for i, wsp in enumerate(WS): p = BaseDict.copy() p['InflowFile|HWindSpeed'] = wsp p['InflowFile|WindType'] = 1 # Setting steady wind # Set DOFs p['EDFile|GenDOF'] = 'True' p['EDFile|FlapDOF1'] = 'True' p['EDFile|TwFADOF1'] = 'True' # NREL-5MW rated generator speed, torque, control params p['ServoFile|VS_RtGnSp'] = 1173 * .9 p['ServoFile|VS_RtTq'] = 47402 p['ServoFile|VS_Rgn2K'] = 0.0226 p['ServoFile|VS_SlPc'] = 10. # Trim solution will converge to this rotor speed p['EDFile|RotSpeed'] = 12.1 # Set number of linearizations p['NLinTimes'] = 12 p['__name__'] = '{:03d}_ws{:04.1f}'.format(i, p['InflowFile|HWindSpeed']) PARAMS.append(p) i = i + 1 # --- Generating all files in a output directory fastfiles = case_gen.templateReplace(PARAMS, ref_dir, outputDir=out_dir, removeRefSubFiles=True, main_file=main_file, oneSimPerDir=False) print(fastfiles) # --- Creating a batch script just in case runner.writeBatch(os.path.join(out_dir, '_RUN_ALL.bat'), fastfiles, fastExe=FAST_EXE) # --- Running the simulations runner.run_fastfiles(fastfiles, fastExe=FAST_EXE, parallel=True, showOutputs=True, nCores=4) # --- Simple Postprocessing # (averaging each signal over the last period for each simulation) outFiles = [os.path.splitext(f)[0] + '.outb' for f in fastfiles] # avg_results = postpro.averagePostPro(outFiles, avgMethod='periods', avgParam=1, ColMap = {'WS_[m/s]':'Wind1VelX_[m/s]'},ColSort='WS_[m/s]') # avg_results.drop('Time_[s]',axis=1, inplace=True) return outFiles