예제 #1
0
    def ROSCO_Test_lite(self, more_case_inputs={}, U=[]):
        '''
        DLC 1.1 - 5 wind speeds, 60s

        Parameters:
        -----------
        more_case_inputs: dict
            Additional case inputs
        U: list
            List of wind inputs
        '''

        # Check for time and wind inputs
        if ('Fst', 'TMax') in more_case_inputs.keys():
            self.TMax = np.max(more_case_inputs[('Fst', 'TMax')]['vals'])
        else:
            self.TMax = 330

        if len(U) > 0:
            WindSpeeds = U
        else:
            WindSpeeds = [5, 8, 11, 14, 17]

        fastRead = InputReader_OpenFAST(FAST_ver=self.FAST_ver,
                                        dev_branch=self.dev_branch)
        fastRead.FAST_InputFile = self.FAST_InputFile  # FAST input file (ext=.fst)
        # Path to fst directory files
        fastRead.FAST_directory = self.FAST_directory

        # Read FAST inputs for generating cases
        fastRead.execute()

        # Start near the steady state, controller should be able to handle startup transients.
        iec = CaseGen_IEC()
        iec.init_cond[("ElastoDyn", "RotSpeed")] = {'U': [2, 30]}
        iec.init_cond[("ElastoDyn", "RotSpeed")]['val'] = np.ones(
            [2]) * fastRead.fst_vt['ElastoDyn']['RotSpeed'] * .75
        iec.init_cond[("ElastoDyn", "BlPitch1")] = {'U': [2, 30]}
        iec.init_cond[("ElastoDyn", "BlPitch1")]['val'] = np.ones([2]) * 0
        iec.init_cond[("ElastoDyn", "BlPitch2")] = iec.init_cond[("ElastoDyn",
                                                                  "BlPitch1")]
        iec.init_cond[("ElastoDyn", "BlPitch3")] = iec.init_cond[("ElastoDyn",
                                                                  "BlPitch1")]
        iec.Turbine_Class = self.Turbine_Class
        iec.Turbulence_Class = self.Turbulence_Class
        iec.D = fastRead.fst_vt['ElastoDyn']['TipRad'] * 2.
        iec.z_hub = fastRead.fst_vt['InflowWind']['RefHt']
        iec.TMax = self.TMax

        iec.dlc_inputs = {}
        iec.dlc_inputs['DLC'] = [1.1]  # ,6.1,6.3]
        iec.dlc_inputs['U'] = [WindSpeeds]
        iec.dlc_inputs['Seeds'] = [[971231]]
        iec.dlc_inputs['Yaw'] = [[]]
        iec.transient_dir_change = '-'  # '+','-','both': sign for transient events in EDC, EWS
        iec.transient_shear_orientation = 'v'  # 'v','h','both': vertical or horizontal shear for EWS

        if self.wind_dir:
            iec.wind_dir = self.wind_dir
        else:
            iec.wind_dir = os.path.join(self.runDir, 'wind')

        iec.case_name_base = self.namebase
        iec.Turbsim_exe = self.Turbsim_exe
        iec.debug_level = self.debug_level
        iec.cores = self.cores
        iec.run_dir = self.runDir
        iec.overwrite = self.overwrite
        # iec.overwrite       = False
        if self.cores > 1:
            iec.parallel_windfile_gen = True
        else:
            iec.parallel_windfile_gen = False

        # mpi_run = False
        if self.mpi_run:
            iec.mpi_run = mpi_run
            iec.comm_map_down = mpi_comm_map_down

        case_inputs = {}
        case_inputs[("Fst", "TMax")] = {'vals': [self.TMax], 'group': 0}
        case_inputs[("Fst", "OutFileFmt")] = {
            'vals': [self.outfile_fmt],
            'group': 0
        }

        case_inputs[('ServoDyn', 'GenTiStr')] = {'vals': ['True'], 'group': 0}
        case_inputs[('ServoDyn', 'GenTiStp')] = {'vals': ['True'], 'group': 0}
        case_inputs[('ServoDyn', 'SpdGenOn')] = {'vals': [0.], 'group': 0}
        case_inputs[('ServoDyn', 'TimGenOn')] = {'vals': [0.], 'group': 0}
        case_inputs[('ServoDyn', 'DLL_FileName')] = {
            'vals': [self.rosco_path],
            'group': 0
        }
        case_inputs[('ServoDyn', 'DLL_DT')] = {
            'vals': ['"default"'],
            'group': 0
        }

        case_inputs[("AeroDyn15", "WakeMod")] = {'vals': [1], 'group': 0}
        case_inputs[("AeroDyn15", "AFAeroMod")] = {'vals': [2], 'group': 0}
        case_inputs[("AeroDyn15", "TwrPotent")] = {'vals': [0], 'group': 0}
        case_inputs[("AeroDyn15", "TwrShadow")] = {
            'vals': ['False'],
            'group': 0
        }
        case_inputs[("AeroDyn15", "TwrAero")] = {'vals': ['False'], 'group': 0}
        case_inputs[("AeroDyn15", "SkewMod")] = {'vals': [1], 'group': 0}
        case_inputs[("AeroDyn15", "TipLoss")] = {'vals': ['True'], 'group': 0}
        case_inputs[("AeroDyn15", "HubLoss")] = {'vals': ['True'], 'group': 0}
        case_inputs[("AeroDyn15", "TanInd")] = {'vals': ['True'], 'group': 0}
        case_inputs[("AeroDyn15", "AIDrag")] = {'vals': ['True'], 'group': 0}
        case_inputs[("AeroDyn15", "TIDrag")] = {'vals': ['True'], 'group': 0}
        case_inputs[("AeroDyn15", "IndToler")] = {'vals': [1.e-5], 'group': 0}
        case_inputs[("AeroDyn15", "MaxIter")] = {'vals': [5000], 'group': 0}
        case_inputs[("AeroDyn15", "UseBlCm")] = {'vals': ['True'], 'group': 0}

        if more_case_inputs:
            case_inputs.update(more_case_inputs)

        # generate cases
        case_list, case_name_list, _ = iec.execute(case_inputs=case_inputs)

        # Ensure proper output channels
        var_out = self.var_out

        channels = {}
        for var in var_out:
            channels[var] = True

        # Set up FAST Sims
        fastBatch = runFAST_pywrapper_batch()
        fastBatch.FAST_ver = self.FAST_ver
        fastBatch.FAST_exe = self.FAST_exe  # Path to executable
        fastBatch.FAST_runDirectory = self.runDir
        fastBatch.FAST_InputFile = self.FAST_InputFile  # FAST input file (ext=.fst)
        fastBatch.FAST_directory = self.FAST_directory  # Path to fst directory files
        fastBatch.debug_level = self.debug_level
        fastBatch.dev_branch = self.dev_branch

        fastBatch.case_list = case_list
        fastBatch.case_name_list = case_name_list
        fastBatch.channels = channels

        # Check if simulation has been run
        if self.outfile_fmt == 1:
            outfile_ext = '.out'
        elif self.outfile_fmt == 2:
            outfile_ext = '.outb'
        elif self.outfile_fmt == 3:
            outfile_ext = '.outb'
        else:
            print(
                'Warning, outfile format may be invalid. Attempting to read binary outputs.'
            )
            outfile_ext = 'outb'
        outFileNames = [
            os.path.join(fastBatch.FAST_runDirectory, case_name + outfile_ext)
            for case_name in case_name_list
        ]
        outFileThere = [
            os.path.exists(outFileName) for outFileName in outFileNames
        ]

        # Run simulations if they're not all there or if you want to overwrite
        if not all(outFileThere) or self.overwrite:
            if self.cores > 1:
                fastBatch.run_multi(self.cores)
            else:
                fastBatch.run_serial()

        self.print_results(outFileNames)
예제 #2
0
    def generate_rotperf_fast(self,
                              openfast_path,
                              FAST_runDirectory=None,
                              run_BeamDyn=False,
                              debug_level=1,
                              run_type='multi'):
        '''
        Use openfast to generate Cp surface data. Will be slow, especially if using BeamDyn,
        but may be necessary if cc-blade is not sufficient.

        Parameters:
        -----------
        openfast_path: str
            path to openfast
        FAST_runDirectory: str
            directory to run openfast simulations in
        run_BeamDyn: bool
            Flag to run beamdyn - does not exist yet
        debug_level: float
            0 - no outputs, 1 - simple outputs, 2 - all outputs
        run_type: str
            'serial' - run in serial, 'multi' - run using python multiprocessing tools, 
            'mpi' - run using mpi tools
        '''
        from ROSCO_toolbox.ofTools.case_gen import runFAST_pywrapper, CaseGen_General
        from ROSCO_toolbox.ofTools.util import FileTools
        # Load pCrunch tools
        from pCrunch import pdTools, Processing

        # setup values for surface
        v0 = self.v_rated + 2
        TSR_initial = np.arange(3, 15, 1)
        pitch_initial = np.arange(-1, 25, 1)
        rotspeed_initial = TSR_initial * v0 / self.rotor_radius * RadSec2rpm  # rpms

        # Specify Case Inputs
        case_inputs = {}

        # ------- Setup OpenFAST inputs --------
        case_inputs[('Fst', 'TMax')] = {'vals': [330], 'group': 0}
        case_inputs[('Fst', 'Compinflow')] = {'vals': [1], 'group': 0}
        case_inputs[('Fst', 'CompAero')] = {'vals': [2], 'group': 0}
        case_inputs[('Fst', 'CompServo')] = {'vals': [1], 'group': 0}
        case_inputs[('Fst', 'CompHydro')] = {'vals': [0], 'group': 0}
        if run_BeamDyn:
            case_inputs[('Fst', 'CompElast')] = {'vals': [2], 'group': 0}
        else:
            case_inputs[('Fst', 'CompElast')] = {'vals': [1], 'group': 0}
        case_inputs[('Fst', 'OutFileFmt')] = {'vals': [2], 'group': 0}

        # AeroDyn15
        case_inputs[('AeroDyn15', 'WakeMod')] = {'vals': [1], 'group': 0}
        case_inputs[('AeroDyn15', 'AfAeroMod')] = {'vals': [1], 'group': 0}
        case_inputs[('AeroDyn15', 'TwrPotent')] = {'vals': [0], 'group': 0}

        # ElastoDyn
        case_inputs[('ElastoDyn', 'FlapDOF1')] = {'vals': ['True'], 'group': 0}
        case_inputs[('ElastoDyn', 'FlapDOF2')] = {'vals': ['True'], 'group': 0}
        case_inputs[('ElastoDyn', 'EdgeDOF')] = {'vals': ['True'], 'group': 0}
        case_inputs[('ElastoDyn', 'TeetDOF')] = {'vals': ['False'], 'group': 0}
        case_inputs[('ElastoDyn', 'DrTrDOF')] = {'vals': ['False'], 'group': 0}
        case_inputs[('ElastoDyn', 'GenDOF')] = {'vals': ['False'], 'group': 0}
        case_inputs[('ElastoDyn', 'YawDOF')] = {'vals': ['False'], 'group': 0}
        case_inputs[('ElastoDyn', 'TwFADOF1')] = {
            'vals': ['False'],
            'group': 0
        }
        case_inputs[('ElastoDyn', 'TwFADOF2')] = {
            'vals': ['False'],
            'group': 0
        }
        case_inputs[('ElastoDyn', 'TwSSDOF1')] = {
            'vals': ['False'],
            'group': 0
        }
        case_inputs[('ElastoDyn', 'TwSSDOF2')] = {
            'vals': ['False'],
            'group': 0
        }
        case_inputs[('ElastoDyn', 'PtfmSgDOF')] = {
            'vals': ['False'],
            'group': 0
        }
        case_inputs[('ElastoDyn', 'PtfmSwDOF')] = {
            'vals': ['False'],
            'group': 0
        }
        case_inputs[('ElastoDyn', 'PtfmHvDOF')] = {
            'vals': ['False'],
            'group': 0
        }
        case_inputs[('ElastoDyn', 'PtfmRDOF')] = {
            'vals': ['False'],
            'group': 0
        }
        case_inputs[('ElastoDyn', 'PtfmPDOF')] = {
            'vals': ['False'],
            'group': 0
        }
        case_inputs[('ElastoDyn', 'PtfmYDOF')] = {
            'vals': ['False'],
            'group': 0
        }

        # BeamDyn
        # NEEDED

        # InflowWind
        case_inputs[('InflowWind', 'WindType')] = {'vals': [1], 'group': 0}
        case_inputs[('InflowWind', 'HWindSpeed')] = {'vals': [v0], 'group': 0}
        case_inputs[('InflowWind', 'PLexp')] = {'vals': [0], 'group': 0}

        # ServoDyn
        case_inputs[('ServoDyn', 'PCMode')] = {'vals': [0], 'group': 0}
        case_inputs[('ServoDyn', 'VSContrl')] = {'vals': [0], 'group': 0}
        case_inputs[('ServoDyn', 'HSSBrMode')] = {'vals': [0], 'group': 0}
        case_inputs[('ServoDyn', 'YCMode')] = {'vals': [0], 'group': 0}

        # ------- Setup sweep values inputs --------
        case_inputs[('ElastoDyn', 'BlPitch1')] = {
            'vals': list(pitch_initial),
            'group': 1
        }
        case_inputs[('ElastoDyn', 'BlPitch2')] = {
            'vals': list(pitch_initial),
            'group': 1
        }
        case_inputs[('ElastoDyn', 'BlPitch3')] = {
            'vals': list(pitch_initial),
            'group': 1
        }
        case_inputs[('ElastoDyn', 'RotSpeed')] = {
            'vals': list(rotspeed_initial),
            'group': 2
        }

        # FAST details
        fastBatch = runFAST_pywrapper.runFAST_pywrapper_batch(
            FAST_ver='OpenFAST', dev_branch=True)
        fastBatch.FAST_exe = openfast_path  # Path to executable
        fastBatch.FAST_InputFile = self.fast.FAST_InputFile
        fastBatch.FAST_directory = self.fast.FAST_directory
        if not FAST_runDirectory:
            FAST_runDirectory = os.path.join(os.getcwd(), 'RotPerf_OpenFAST')
        fastBatch.FAST_runDirectory = FAST_runDirectory
        fastBatch.debug_level = debug_level

        # Generate cases
        case_name_base = self.TurbineName + '_rotperf'
        case_list, case_name_list = CaseGen_General.CaseGen_General(
            case_inputs,
            dir_matrix=fastBatch.FAST_runDirectory,
            namebase=case_name_base)
        fastBatch.case_list = case_list
        fastBatch.case_name_list = case_name_list

        # Make sure proper outputs exist
        var_out = [
            # ElastoDyn (this is probably overkill on the outputs)
            "BldPitch1",
            "BldPitch2",
            "BldPitch3",
            "Azimuth",
            "RotSpeed",
            "GenSpeed",
            "NacYaw",
            "OoPDefl1",
            "IPDefl1",
            "TwstDefl1",
            "OoPDefl2",
            "IPDefl2",
            "TwstDefl2",
            "OoPDefl3",
            "IPDefl3",
            "TwstDefl3",
            "RootFxc1",
            "RootFyc1",
            "RootFzc1",
            "RootMxc1",
            "RootMyc1",
            "RootMzc1",
            "RootFxc2",
            "RootFyc2",
            "RootFzc2",
            "RootMxc2",
            "RootMyc2",
            "RootMzc2",
            "RootFxc3",
            "RootFyc3",
            "RootFzc3",
            "RootMxc3",
            "RootMyc3",
            "RootMzc3",
            "Spn1MLxb1",
            "Spn1MLyb1",
            "Spn1MLzb1",
            "Spn1MLxb2",
            "Spn1MLyb2",
            "Spn1MLzb2",
            "Spn1MLxb3",
            "Spn1MLyb3",
            "Spn1MLzb3",
            "RotThrust",
            "LSSGagFya",
            "LSSGagFza",
            "RotTorq",
            "LSSGagMya",
            "LSSGagMza",
            # ServoDyn
            "GenPwr",
            "GenTq",
            # AeroDyn15
            "RtArea",
            "RtVAvgxh",
            "B1N3Clrnc",
            "B2N3Clrnc",
            "B3N3Clrnc",
            "RtAeroCp",
            'RtAeroCq',
            'RtAeroCt',
            'RtTSR',  # NECESSARY
            # InflowWind
            "Wind1VelX",
        ]
        channels = {}
        for var in var_out:
            channels[var] = True
        fastBatch.channels = channels

        # Run OpenFAST
        if run_type.lower() == 'multi':
            fastBatch.run_multi()
        elif run_type.lower() == 'mpi':
            fastBatch.run_mpi()
        elif run_type.lower() == 'serial':
            fastBatch.run_serial()

        # ========== Post Processing ==========
        # Save statistics
        fp = Processing.FAST_Processing()

        # Find all outfiles
        fname_case_matrix = os.path.join(FAST_runDirectory, 'case_matrix.yaml')
        case_matrix = FileTools.load_yaml(fname_case_matrix, package=1)
        cm = pd.DataFrame(case_matrix)
        # Parse case matrix and find outfiles names
        outfiles = []
        case_names = cm['Case_Name']
        outfiles = []
        for name in case_names:
            outfiles.append(os.path.join(FAST_runDirectory, name + '.outb'))

        # Set some processing parameters
        fp.OpenFAST_outfile_list = outfiles
        fp.namebase = case_name_base
        fp.t0 = 270
        fp.parallel_analysis = True
        fp.results_dir = os.path.join(FAST_runDirectory, 'stats')
        fp.verbose = True
        # Save for debug!
        fp.save_LoadRanking = False
        fp.save_SummaryStats = False

        print('Processing openfast data on {} cores.'.format(
            fp.parallel_cores))

        # Load and save statistics and load rankings
        stats, load_rankings = fp.batch_processing()

        # Get means of last 30 seconds of 300 second simulation
        CP = stats[0]['RtAeroCp']['mean']
        CT = stats[0]['RtAeroCt']['mean']
        CQ = stats[0]['RtAeroCq']['mean']

        # Reshape Cp, Ct and Cq
        Cp = np.transpose(
            np.reshape(CP, (len(pitch_initial), len(TSR_initial))))
        Ct = np.transpose(
            np.reshape(CT, (len(pitch_initial), len(TSR_initial))))
        Cq = np.transpose(
            np.reshape(CQ, (len(pitch_initial), len(TSR_initial))))

        # Store necessary metrics for analysis
        self.pitch_initial_rad = pitch_initial * deg2rad
        self.TSR_initial = TSR_initial
        self.Cp_table = Cp
        self.Ct_table = Ct
        self.Cq_table = Cq
예제 #3
0
    def ROSCO_Test_heavy(self, more_case_inputs={}, U=[]):
        '''
        Run extensive DLCs for ROSCO
            - DLC 1.3 - Cutin-Cutout, 2 seeds
            - DLC 1.4 - 2 wind speeds

        more_case_inputs: dict
            Additional case inputs
        U: list-like
            List like with two lists of wind speeds, first entry for DLC 1.3 and second entry for DLC 1.4
        '''

        # Check for time and wind inputs
        if ('Fst', 'TMax') in more_case_inputs.keys():
            self.TMax = np.max(more_case_inputs[('Fst', 'TMax')]['vals'])
        else:
            self.TMax = 630

        if len(U) > 0:
            WindSpeeds = U
            if len(U) != 2:
                ValueError(
                    'For a user defined input, U, two sets of wind speeds must be defined.'
                )
        else:
            WindSpeeds = [[4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24],
                          [8.88, 12.88]]

        fastRead = InputReader_OpenFAST(FAST_ver=self.FAST_ver,
                                        dev_branch=self.dev_branch)
        fastRead.FAST_InputFile = self.FAST_InputFile  # FAST input file (ext=.fst)
        # Path to fst directory files
        fastRead.FAST_directory = self.FAST_directory

        # Read FAST inputs for generating cases
        fastRead.execute()

        # Start near the steady state, controller should be able to handle startup transients.
        iec = CaseGen_IEC()
        iec.init_cond[("ElastoDyn", "RotSpeed")] = {'U': [2, 30]}
        iec.init_cond[("ElastoDyn", "RotSpeed")]['val'] = np.ones(
            [2]) * fastRead.fst_vt['ElastoDyn']['RotSpeed'] * .75
        iec.init_cond[("ElastoDyn", "BlPitch1")] = {'U': [2, 30]}
        iec.init_cond[("ElastoDyn", "BlPitch1")]['val'] = np.ones([2]) * 0
        iec.init_cond[("ElastoDyn", "BlPitch2")] = iec.init_cond[("ElastoDyn",
                                                                  "BlPitch1")]
        iec.init_cond[("ElastoDyn", "BlPitch3")] = iec.init_cond[("ElastoDyn",
                                                                  "BlPitch1")]

        # waves
        if self.FAST_InputFile == 'IEA-15-240-RWT-UMaineSemi.fst':
            iec.init_cond[('HydroDyn', 'WaveHs')] = {
                'U': [4., 6., 8., 10., 12., 14., 16., 18., 20., 22., 24.]
            }
            iec.init_cond[('HydroDyn', 'WaveHs')]['val'] = [
                1.102, 1.179, 1.316, 1.537, 1.836, 2.188, 2.598, 3.061, 3.617,
                4.027, 4.516
            ]
            iec.init_cond[('HydroDyn', 'WaveTp')] = {
                'U': [4., 6., 8., 10., 12., 14., 16., 18., 20., 22., 24.]
            }
            iec.init_cond[('HydroDyn', 'WaveTp')]['val'] = [
                8.515, 8.310, 8.006, 7.651, 7.441, 7.461, 7.643, 8.047, 8.521,
                8.987, 9.452
            ]

        iec.Turbine_Class = self.Turbine_Class
        iec.Turbulence_Class = self.Turbulence_Class
        iec.D = fastRead.fst_vt['ElastoDyn']['TipRad'] * 2.
        iec.z_hub = fastRead.fst_vt['InflowWind']['RefHt']
        iec.TMax = self.TMax

        iec.dlc_inputs = {}
        iec.dlc_inputs['DLC'] = [1.3, 1.4]
        iec.dlc_inputs['U'] = WindSpeeds
        iec.dlc_inputs['Seeds'] = [[991235, 5123], []]
        iec.dlc_inputs['Yaw'] = [[], []]
        iec.transient_dir_change = '-'  # '+','-','both': sign for transient events in EDC, EWS
        iec.transient_shear_orientation = 'v'  # 'v','h','both': vertical or horizontal shear for EWS
        iec.uniqueSeeds = True
        iec.uniqueWaveSeeds = True

        if self.wind_dir:
            iec.wind_dir = self.wind_dir
        else:
            iec.wind_dir = os.path.join(self.runDir, 'wind')
        iec.case_name_base = self.namebase
        iec.Turbsim_exe = self.Turbsim_exe
        iec.debug_level = self.debug_level
        iec.cores = self.cores
        iec.run_dir = os.path.join(self.runDir)
        iec.overwrite = self.overwrite
        # iec.overwrite       = False
        if self.cores > 1:
            iec.parallel_windfile_gen = True
        else:
            iec.parallel_windfile_gen = False

        # mpi_run = False
        if self.mpi_run:
            iec.mpi_run = mpi_run
            iec.comm_map_down = mpi_comm_map_down

        case_inputs = {}
        case_inputs[("Fst", "TMax")] = {'vals': [self.TMax], 'group': 0}
        case_inputs[("Fst", "OutFileFmt")] = {
            'vals': [self.outfile_fmt],
            'group': 0
        }

        case_inputs[('ServoDyn', 'GenTiStr')] = {'vals': ['False'], 'group': 0}
        case_inputs[('ServoDyn', 'GenTiStp')] = {'vals': ['True'], 'group': 0}
        case_inputs[('ServoDyn', 'SpdGenOn')] = {'vals': [0.], 'group': 0}
        case_inputs[('ServoDyn', 'DLL_FileName')] = {
            'vals': [self.rosco_path],
            'group': 0
        }

        case_inputs[("AeroDyn15", "WakeMod")] = {'vals': [1], 'group': 0}
        case_inputs[("AeroDyn15", "AFAeroMod")] = {'vals': [2], 'group': 0}
        case_inputs[("AeroDyn15", "TwrPotent")] = {'vals': [0], 'group': 0}
        case_inputs[("AeroDyn15", "TwrShadow")] = {
            'vals': ['False'],
            'group': 0
        }
        case_inputs[("AeroDyn15", "TwrAero")] = {'vals': ['False'], 'group': 0}
        case_inputs[("AeroDyn15", "SkewMod")] = {'vals': [1], 'group': 0}
        case_inputs[("AeroDyn15", "TipLoss")] = {'vals': ['True'], 'group': 0}
        case_inputs[("AeroDyn15", "HubLoss")] = {'vals': ['True'], 'group': 0}
        case_inputs[("AeroDyn15", "TanInd")] = {'vals': ['True'], 'group': 0}
        case_inputs[("AeroDyn15", "AIDrag")] = {'vals': ['True'], 'group': 0}
        case_inputs[("AeroDyn15", "TIDrag")] = {'vals': ['True'], 'group': 0}
        case_inputs[("AeroDyn15", "IndToler")] = {'vals': [1.e-5], 'group': 0}
        case_inputs[("AeroDyn15", "MaxIter")] = {'vals': [5000], 'group': 0}
        case_inputs[("AeroDyn15", "UseBlCm")] = {'vals': ['True'], 'group': 0}

        if self.FAST_InputFile == 'IEA-15-240-RWT-UMaineSemi.fst':
            case_inputs[("HydroDyn", "WaveMod")] = {'vals': [2], 'group': 0}

        if more_case_inputs:
            case_inputs.update(more_case_inputs)

        case_list, case_name_list, _ = iec.execute(case_inputs=case_inputs)

        # Ensure proper output channels
        var_out = self.var_out

        channels = {}
        for var in var_out:
            channels[var] = True

        # Set up FAST Sims, move setup up
        fastBatch = runFAST_pywrapper_batch()
        fastBatch.FAST_ver = self.FAST_ver
        fastBatch.FAST_exe = self.FAST_exe  # Path to executable
        fastBatch.FAST_runDirectory = self.runDir
        fastBatch.FAST_InputFile = self.FAST_InputFile  # FAST input file (ext=.fst)
        fastBatch.FAST_directory = self.FAST_directory  # Path to fst directory files
        fastBatch.debug_level = self.debug_level
        fastBatch.dev_branch = self.dev_branch

        fastBatch.case_list = case_list
        fastBatch.case_name_list = case_name_list
        fastBatch.channels = channels

        # Check if simulation has been run
        if self.outfile_fmt == 1:
            outfile_ext = '.out'
        elif self.outfile_fmt == 2:
            outfile_ext = '.outb'
        elif self.outfile_fmt == 3:
            outfile_ext = '.outb'
        else:
            print(
                'Warning, outfile format may be invalid. Attempting to read binary outputs.'
            )
            outfile_ext = 'outb'
        outFileNames = [
            os.path.join(fastBatch.FAST_runDirectory, case_name + outfile_ext)
            for case_name in case_name_list
        ]
        outFileThere = [
            os.path.exists(outFileName) for outFileName in outFileNames
        ]

        # Run simulations if they're not all there or if you want to overwrite
        if not all(outFileThere) or self.overwrite:
            if self.cores > 1:
                fastBatch.run_multi(self.cores)
            else:
                fastBatch.run_serial()

        self.print_results(outFileNames)