Example #1
0
    def execute(self):

        # FAST version specific initialization
        if self.FAST_ver.lower() == 'fast7':
            reader = InputReader_FAST7(FAST_ver=self.FAST_ver)
            writer = InputWriter_FAST7(FAST_ver=self.FAST_ver)
        elif self.FAST_ver.lower() in ['fast8','openfast']:
            reader = InputReader_OpenFAST(FAST_ver=self.FAST_ver)
            writer = InputWriter_OpenFAST(FAST_ver=self.FAST_ver)
        wrapper = FastWrapper(FAST_ver=self.FAST_ver, debug_level=self.debug_level)

        # Read input model, FAST files or Yaml
        if self.fst_vt == {}:
            if self.read_yaml:
                reader.FAST_yamlfile = self.FAST_yamlfile_in
                reader.read_yaml()
            else:
                reader.FAST_InputFile = self.FAST_InputFile
                reader.FAST_directory = self.FAST_directory
                reader.execute()
        
            # Initialize writer variables with input model
            writer.fst_vt = reader.fst_vt
        else:
            writer.fst_vt = self.fst_vt
        writer.FAST_runDirectory = self.FAST_runDirectory
        writer.FAST_namingOut = self.FAST_namingOut
        # Make any case specific variable changes
        if self.case:
            writer.update(fst_update=self.case)
        # Modify any specified output channels
        if self.channels:
            writer.update_outlist(self.channels)
        # Write out FAST model
        writer.execute()
        if self.write_yaml:
            writer.FAST_yamlfile = self.FAST_yamlfile_out
            writer.write_yaml()

        # Run FAST
        wrapper.FAST_exe = self.FAST_exe
        wrapper.FAST_InputFile = os.path.split(writer.FAST_InputFileOut)[1]
        wrapper.FAST_directory = os.path.split(writer.FAST_InputFileOut)[0]

        FAST_Output     = os.path.join(wrapper.FAST_directory, wrapper.FAST_InputFile[:-3]+'outb')
        FAST_Output_txt = os.path.join(wrapper.FAST_directory, wrapper.FAST_InputFile[:-3]+'out')

        #check if OpenFAST is set not to overwrite existing output files, TODO: move this further up in the workflow for minor computation savings
        if self.overwrite_outfiles or (not self.overwrite_outfiles and not (os.path.exists(FAST_Output) or os.path.exists(FAST_Output_txt))):
            wrapper.execute()
        else:
            if self.debug_level>0:
                print('OpenFAST not execute: Output file "%s" already exists. To overwrite this output file, set "overwrite_outfiles = True".'%FAST_Output)

        return FAST_Output
Example #2
0
def gen_linear_model(wind_speeds, Tmax=600.):
    """ 
    Generate OpenFAST linearizations across wind speeds

    Only needs to be performed once for each model

    """

    linear = LinearFAST(FAST_ver='OpenFAST', dev_branch=True)

    # fast info
    linear.weis_dir = os.path.dirname(
        os.path.dirname(os.path.dirname(__file__))) + os.sep

    linear.FAST_InputFile = 'IEA-15-240-RWT-UMaineSemi.fst'  # FAST input file (ext=.fst)
    linear.FAST_directory = os.path.join(
        linear.weis_dir,
        'examples/01_aeroelasticse/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-UMaineSemi'
    )  # Path to fst directory files
    linear.FAST_steadyDirectory = os.path.join(linear.weis_dir, 'outputs',
                                               'iea_semi_steady')
    linear.FAST_linearDirectory = os.path.join(linear.weis_dir, 'outputs',
                                               'iea_semi_lin')
    linear.debug_level = 2
    linear.dev_branch = True
    linear.write_yaml = True

    # do a read to get gearbox ratio
    fastRead = InputReader_OpenFAST(FAST_ver='OpenFAST', dev_branch=True)
    fastRead.FAST_InputFile = linear.FAST_InputFile  # FAST input file (ext=.fst)
    fastRead.FAST_directory = linear.FAST_directory  # Path to fst directory files

    fastRead.execute()

    # linearization setup
    linear.v_rated = 10.74  # needed as input from RotorSE or something, to determine TrimCase for linearization
    linear.GBRatio = fastRead.fst_vt['ElastoDyn']['GBRatio']
    linear.WindSpeeds = wind_speeds  #[8.,10.,12.,14.,24.]
    linear.DOFs = ['GenDOF']  #,'TwFADOF1','PtfmPDOF']  # enable with
    linear.TMax = Tmax  # should be 1000-2000 sec or more with hydrodynamic states
    linear.NLinTimes = 12

    #if true, there will be a lot of hydronamic states, equal to num. states in ss_exct and ss_radiation models
    linear.HydroStates = False  # taking out to speed up for test

    # simulation setup
    linear.parallel = False
    linear.cores = 8

    # overwrite steady & linearizations
    linear.overwrite = False

    # run steady state sims
    linear.runFAST_steady()

    # process results
    linear.postFAST_steady()

    # run linearizations
    linear.runFAST_linear()
Example #3
0
    def set_openfast_data(self):
        # Openfast
        if self.modeling_options['Level3']['flag'] == True:
            fast                = InputReader_OpenFAST(FAST_ver='OpenFAST')
            self.modeling_options['openfast']['fst_vt'] = {}
            self.modeling_options['openfast']['fst_vt']['outlist'] = fast.fst_vt['outlist']

            if self.modeling_options['openfast']['file_management']['FAST_directory'] != 'none':
                # Load Input OpenFAST model variable values
                fast.FAST_InputFile = self.modeling_options['openfast']['file_management']['FAST_InputFile']
                if os.path.isabs(self.modeling_options['openfast']['file_management']['FAST_directory']):
                    fast.FAST_directory = self.modeling_options['openfast']['file_management']['FAST_directory']
                else:
                    fast.FAST_directory = os.path.join(os.path.dirname(self.modeling_options['fname_input_modeling']), self.modeling_options['openfast']['file_management']['FAST_directory'])

            # Find the controller
            run_dir = os.path.dirname( os.path.dirname( os.path.dirname( os.path.realpath(__file__) ) ) ) + os.sep
            if platform.system() == 'Windows':
                path2dll = os.path.join(run_dir, 'local/lib/libdiscon.dll')
            elif platform.system() == 'Darwin':
                path2dll = os.path.join(run_dir, 'local/lib/libdiscon.dylib')
            else:
                path2dll = os.path.join(run_dir, 'local/lib/libdiscon.so')
            if self.modeling_options['openfast']['file_management']['path2dll'] == 'none':
                self.modeling_options['openfast']['file_management']['path2dll'] = path2dll
                
            if os.path.isabs(self.modeling_options['openfast']['file_management']['path2dll']) == False:
                self.modeling_options['openfast']['file_management']['path2dll'] = os.path.join(os.path.dirname(self.modeling_options['fname_input_modeling']), self.modeling_options['openfast']['file_management']['path2dll'])

            if self.modeling_options['openfast']['file_management']['FAST_directory'] != 'none':
                fast.path2dll = self.modeling_options['openfast']['file_management']['path2dll']
                fast.execute()
            
            if self.modeling_options['openfast']['analysis_settings']['Analysis_Level'] == 2 and self.modeling_options['openfast']['dlc_settings']['run_power_curve'] == False and self.modeling_options['openfast']['dlc_settings']['run_IEC'] == False:
                raise Exception('WEIS is set to run OpenFAST, but both flags for power curve and IEC cases are set to False among the modeling options. Set at least one of the two to True to proceed.')
        
        # XFoil
        if not os.path.isfile(self.modeling_options["xfoil"]["path"]) and self.modeling_options['Level3']['ROSCO']['Flp_Mode']:
            raise Exception("A distributed aerodynamic control device is defined in the geometry yaml, but the path to XFoil in the modeling options is not defined correctly")
Example #4
0
    def load_from_fast(self,
                       FAST_InputFile,
                       FAST_directory,
                       FAST_ver='OpenFAST',
                       dev_branch=True,
                       rot_source=None,
                       txt_filename=None):
        """
        Load the parameter files directly from a FAST input deck

        Parameters:
        -----------
            Fast_InputFile: str
                            Primary fast model input file (*.fst)
            FAST_directory: str
                            Directory for primary fast model input file
            FAST_ver: string, optional
                      fast version, usually OpenFAST
            dev_branch: bool, optional
                        dev_branch input to InputReader_OpenFAST, probably True
            rot_source: str, optional
                        desired source for rotor to get Cp, Ct, Cq tables. Default is to run cc-blade. 
                            options: cc-blade - run cc-blade
                                     txt - from *.txt file
            txt_filename: str, optional
                          filename for *.txt, only used if rot_source='txt'
        """
        from weis.aeroelasticse.FAST_reader import InputReader_OpenFAST

        print('Loading FAST model: %s ' % FAST_InputFile)
        self.TurbineName = FAST_InputFile.strip('.fst')
        fast = self.fast = InputReader_OpenFAST(FAST_ver=FAST_ver,
                                                dev_branch=dev_branch)
        fast.FAST_InputFile = FAST_InputFile
        fast.FAST_directory = FAST_directory
        fast.execute()

        if txt_filename:
            self.rotor_performance_filename = txt_filename
        else:
            self.rotor_performance_filename = 'Cp_Ct_Cq.txt'

        # Grab general turbine parameters
        self.TipRad = fast.fst_vt['ElastoDyn']['TipRad']
        self.Rhub = fast.fst_vt['ElastoDyn']['HubRad']
        self.hubHt = fast.fst_vt['ElastoDyn']['TowerHt'] + fast.fst_vt[
            'ElastoDyn']['Twr2Shft']
        self.NumBl = fast.fst_vt['ElastoDyn']['NumBl']
        self.TowerHt = fast.fst_vt['ElastoDyn']['TowerHt']
        self.shearExp = 0.2  #HARD CODED FOR NOW
        self.rho = fast.fst_vt['AeroDyn15']['AirDens']
        self.mu = fast.fst_vt['AeroDyn15']['KinVisc']
        self.Ng = fast.fst_vt['ElastoDyn']['GBRatio']
        self.GenEff = fast.fst_vt['ServoDyn']['GenEff']
        self.GBoxEff = fast.fst_vt['ElastoDyn']['GBoxEff']
        self.DTTorSpr = fast.fst_vt['ElastoDyn']['DTTorSpr']
        self.generator_inertia = fast.fst_vt['ElastoDyn']['GenIner']
        self.tilt = fast.fst_vt['ElastoDyn']['ShftTilt']
        try:
            self.precone = fast.fst_vt['ElastoDyn'][
                'PreCone1']  # May need to change to PreCone(1) depending on OpenFAST files
        except:
            self.precone = fast.fst_vt['ElastoDyn']['PreCone(1)']
        self.yaw = 0.0
        self.J = self.rotor_inertia + self.generator_inertia * self.Ng**2
        self.rated_torque = self.rated_power / (
            self.GenEff / 100 * self.rated_rotor_speed * self.Ng)
        self.max_torque = self.rated_torque * 1.1
        self.rotor_radius = self.TipRad
        # self.omega_dt = np.sqrt(self.DTTorSpr/self.J)

        # Load blade information
        self.load_blade_info()

        # Load Cp, Ct, Cq tables
        if rot_source == 'cc-blade':  # Use cc-blade
            self.load_from_ccblade()
        elif rot_source == 'txt':  # Use specified text file
            self.pitch_initial_rad, self.TSR_initial, self.Cp_table, self.Ct_table, self.Cq_table = load_from_txt(
                txt_filename)
        else:  # Use text file from DISCON.in
            if os.path.exists(
                    os.path.join(FAST_directory,
                                 fast.fst_vt['ServoDyn']['DLL_InFile'])):
                try:
                    self.pitch_initial_rad = fast.fst_vt['DISCON_in'][
                        'Cp_pitch_initial_rad']
                    self.TSR_initial = fast.fst_vt['DISCON_in'][
                        'Cp_TSR_initial']
                    self.Cp_table = fast.fst_vt['DISCON_in']['Cp_table']
                    self.Ct_table = fast.fst_vt['DISCON_in']['Ct_table']
                    self.Cq_table = fast.fst_vt['DISCON_in']['Cq_table']
                except:  # Load from cc-blade
                    print(
                        'No rotor performance data source available, running CC-Blade.'
                    )
                    self.load_from_ccblade()

        # Parse rotor performance data
        self.Cp = RotorPerformance(self.Cp_table, self.pitch_initial_rad,
                                   self.TSR_initial)
        self.Ct = RotorPerformance(self.Ct_table, self.pitch_initial_rad,
                                   self.TSR_initial)
        self.Cq = RotorPerformance(self.Cq_table, self.pitch_initial_rad,
                                   self.TSR_initial)

        # Define operational TSR
        if not self.TSR_operational:
            self.TSR_operational = self.Cp.TSR_opt

        # Pull out some floating-related data
        wave_tp = fast.fst_vt['HydroDyn']['WaveTp']
        try:
            self.wave_peak_period = 1 / wave_tp  # Will work if HydroDyn exists and a peak period is defined...
        except:
            self.wave_peak_period = 0.0  # Set as 0.0 when HydroDyn doesn't exist (fixed bottom)
Example #5
0
    def execute(self):

        # FAST version specific initialization
        if self.FAST_ver.lower() == 'fast7':
            reader = InputReader_FAST7(FAST_ver=self.FAST_ver)
            writer = InputWriter_FAST7(FAST_ver=self.FAST_ver)
        elif self.FAST_ver.lower() in ['fast8','openfast']:
            reader = InputReader_OpenFAST(FAST_ver=self.FAST_ver)
            writer = InputWriter_OpenFAST(FAST_ver=self.FAST_ver)

        # Read input model, FAST files or Yaml
        if self.fst_vt == {}:
            if self.read_yaml:
                reader.FAST_yamlfile = self.FAST_yamlfile_in
                reader.read_yaml()
            else:
                reader.FAST_InputFile = self.FAST_InputFile
                reader.FAST_directory = self.FAST_directory
                reader.execute()
        
            # Initialize writer variables with input model
            writer.fst_vt = self.fst_vt = reader.fst_vt
        else:
            writer.fst_vt = self.fst_vt
        writer.FAST_runDirectory = self.FAST_runDirectory
        writer.FAST_namingOut = self.FAST_namingOut
        # Make any case specific variable changes
        if self.case:
            writer.update(fst_update=self.case)
        # Modify any specified output channels
        if self.channels:
            writer.update_outlist(self.channels)
        # Write out FAST model
        writer.execute()
        if self.write_yaml:
            writer.FAST_yamlfile = self.FAST_yamlfile_out
            writer.write_yaml()

        FAST_directory = os.path.split(writer.FAST_InputFileOut)[0]
        input_file_name = create_string_buffer(os.path.abspath(writer.FAST_InputFileOut).encode('utf-8'))
        t_max = c_double(self.fst_vt['Fst']['TMax'])

        orig_dir = os.getcwd()
        os.chdir(FAST_directory)
        
        openfastlib = FastLibAPI(self.FAST_lib, input_file_name, t_max)
        openfastlib.fast_run()

        output_dict = {}
        for i, channel in enumerate(openfastlib.output_channel_names):
            output_dict[channel] = openfastlib.output_values[:,i]
        del(openfastlib)
        
        output = OpenFASTOutput.from_dict(output_dict, self.FAST_namingOut, magnitude_channels=magnitude_channels)
        if self.fst_vt['Fst']['TStart'] > 0.0:
            output.trim_data(tmin=self.fst_vt['Fst']['TStart'], tmax=self.fst_vt['Fst']['TMax'])
        case_name, sum_stats, extremes, dels = la._process_output(output)

        # if save_file: write_fast
        os.chdir(orig_dir)

        if not self.keep_time: output_dict = None
        return case_name, sum_stats, extremes, dels, output_dict
Example #6
0
    def set_openfast_data(self):
        # Openfast
        if self.modeling_options['Analysis_Flags']['OpenFAST'] == True:
            # Load Input OpenFAST model variable values
            fast = InputReader_OpenFAST(FAST_ver='OpenFAST')
            fast.FAST_InputFile = self.modeling_options['openfast'][
                'file_management']['FAST_InputFile']
            if os.path.isabs(self.modeling_options['openfast']
                             ['file_management']['FAST_directory']):
                fast.FAST_directory = self.modeling_options['openfast'][
                    'file_management']['FAST_directory']
            else:
                fast.FAST_directory = os.path.join(
                    os.path.dirname(
                        self.modeling_options['fname_input_modeling']),
                    self.modeling_options['openfast']['file_management']
                    ['FAST_directory'])

            # Find the controller
            run_dir = os.path.dirname(
                os.path.dirname(os.path.dirname(
                    os.path.realpath(__file__)))) + os.sep
            if platform.system() == 'Windows':
                path2dll = os.path.join(run_dir, 'local/lib/libdiscon.dll')
            elif platform.system() == 'Darwin':
                path2dll = os.path.join(run_dir, 'local/lib/libdiscon.dylib')
            else:
                path2dll = os.path.join(run_dir, 'local/lib/libdiscon.so')
            if self.modeling_options['openfast']['file_management'][
                    'path2dll'] != 'none':
                if os.path.isabs(self.modeling_options['openfast']
                                 ['file_management']['path2dll']):
                    fast.path2dll = self.modeling_options['openfast'][
                        'file_management']['path2dll']
                else:
                    fast.path2dll = os.path.join(
                        os.path.dirname(
                            self.modeling_options['fname_input_modeling']),
                        self.modeling_options['openfast']['file_management']
                        ['path2dll'])
            else:
                fast.path2dll = path2dll

            fast.execute()
            self.modeling_options['openfast']['fst_vt'] = fast.fst_vt

            if os.path.isabs(self.modeling_options['openfast']
                             ['file_management']['Simulation_Settings_File']):
                path2settings = self.modeling_options['openfast'][
                    'file_management']['Simulation_Settings_File']
            else:
                path2settings = os.path.join(
                    os.path.dirname(
                        self.modeling_options['fname_input_modeling']),
                    self.modeling_options['openfast']['file_management']
                    ['Simulation_Settings_File'])
            if os.path.exists(path2settings):
                self.modeling_options['openfast']['fst_settings'] = dict(
                    sch.load_yaml(path2settings))
            else:
                print(
                    'WARNING: OpenFAST is called, but no file with settings is found.'
                )
                self.modeling_options['openfast']['fst_settings'] = {}

            if os.path.isabs(self.modeling_options['xfoil']['path']):
                self.modeling_options['airfoils'][
                    'xfoil_path'] = self.modeling_options['xfoil']['path']
            else:
                self.modeling_options['airfoils']['xfoil_path'] = os.path.join(
                    os.path.dirname(
                        self.modeling_options['fname_input_modeling']),
                    self.modeling_options['xfoil']['path'])
            if self.modeling_options['openfast']['analysis_settings'][
                    'Analysis_Level'] == 2 and self.modeling_options[
                        'openfast']['dlc_settings'][
                            'run_power_curve'] == False and self.modeling_options[
                                'openfast']['dlc_settings']['run_IEC'] == False:
                raise ValueError(
                    'WEIS is set to run OpenFAST, but both flags for power curve and IEC cases are set to False among the modeling options. Set at least one of the two to True to proceed.'
                )
        else:
            self.modeling_options['openfast']['fst_vt'] = {}
            self.modeling_options['airfoils']['xfoil_path'] = ''