# Load yaml file parameter_filename = 'NREL5MW_example.yaml' inps = yaml.safe_load(open(parameter_filename)) path_params = inps['path_params'] turbine_params = inps['turbine_params'] controller_params = inps['controller_params'] # Ensure minimum generator speed at 50 rpm (for example's sake), turn on peak shaving and cp-maximizing min pitch controller_params['vs_minspd'] = 50 controller_params['PS_Mode'] = 3 # Instantiate turbine, controller, and file processing classes turbine = ROSCO_turbine.Turbine(turbine_params) controller = ROSCO_controller.Controller(controller_params) file_processing = ROSCO_utilities.FileProcessing() # Load turbine data from OpenFAST and rotor performance text file turbine.load_from_fast(path_params['FAST_InputFile'], path_params['FAST_directory'], dev_branch=True, rot_source='txt', txt_filename=path_params['rotor_performance_filename']) # Tune controller controller.tune_controller(turbine) # Plot minimum pitch schedule plt.plot(controller.v, controller.pitch_op, label='Steady State Operation') plt.plot(controller.v, controller.ps_min_bld_pitch,
'OpenFAST_executables', 'openfast_x64.exe') elif platform.system() == 'Darwin': openfast_call = 'openfast' # Load yaml file parameter_filename = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'BAR_00', 'ServoData', 'BAR_00.yaml') inps = yaml.safe_load(open(parameter_filename)) path_params = inps['path_params'] turbine_params = inps['turbine_params'] controller_params = inps['controller_params'] # Instantiate turbine, controller, and file processing classes turb = turbine.Turbine(turbine_params) cont = controller.Controller(controller_params) file_processing = utilities.FileProcessing() fast_io = utilities.FAST_IO() # Load turbine data from OpenFAST and rotor performance text file turb.load_from_fast(path_params['FAST_InputFile'], path_params['FAST_directory'], dev_branch=True) # Tune controller cont.tune_controller(turb) # Write parameter input file param_filename = 'OpenFAST_BAR_00_DISCON.IN' param_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'BAR_00', param_filename) file_processing.write_DISCON(
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 wisdem.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'] 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 Cp, Ct, Cq tables if rot_source == 'cc-blade': # Use cc-blade self.load_from_ccblade() elif rot_source == 'txt': # Use specified text file file_processing = ROSCO_utilities.FileProcessing() self.pitch_initial_rad, self.TSR_initial, self.Cp_table, self.Ct_table, self.Cq_table = file_processing.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'])): if os.path.exists(fast.fst_vt['DISCON_in']['PerfFileName']): 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'] else: # 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)
path_params['FAST_InputFile'], path_params['FAST_directory'], dev_branch=True, rot_source='txt', txt_filename=path_params['rotor_performance_filename']) # Tune controller controller.tune_controller(turbine) controller.turbine = turbine linCont = lin_mod.LinearControlModel(controller) else: # Load Controller from DISCON.IN fp = ROSCO_utilities.FileProcessing() f = fp.read_DISCON( '/Users/dzalkind/Tools/SaveData/Float_Test/UM_DLC0_100_DISCON.IN') linCont = lin_mod.LinearControlModel([], fromDISCON_IN=True, DISCON_file=f) # 3. Use wind disturbance to determine operating point for turbine, pitch controller # 4. Run linear simulation Lin_OutList, Lin_OutData, P_cl = linTurb.solve(tt, u_h, Plot=False, open_loop=False, controller=linCont) # linear plot