dev_branch=True,rot_source='txt',txt_filename=path_params['rotor_performance_filename']) else: turbine.load_from_fast(path_params['FAST_InputFile'], \ os.path.join(this_dir,path_params['FAST_directory']), \ dev_branch=True,rot_source=None, txt_filename=path_params['rotor_performance_filename']) write_rotor_performance(turbine, txt_filename=os.path.join( this_dir, path_params['rotor_performance_filename'])) # Flap tuning if necessary if controller_params['Flp_Mode']: turbine.load_blade_info() # Instantiate controller tuning and tune controller controller = ROSCO_controller.Controller(controller_params) controller.tune_controller(turbine) # Write parameter input file param_file = 'DISCON.IN' write_DISCON(turbine, controller, param_file=param_file, txt_filename=os.path.join( this_dir, path_params['rotor_performance_filename'])) # Plot rotor performance turbine.Cp.plot_performance() plt.show()
def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): ''' Call ROSCO toolbox to define controller ''' rosco_init_options = self.modeling_options['Level3']['ROSCO'] # Add control tuning parameters to dictionary rosco_init_options['omega_pc'] = inputs['PC_omega'] rosco_init_options['zeta_pc'] = inputs['PC_zeta'] rosco_init_options['omega_vs'] = inputs['VS_omega'] rosco_init_options['zeta_vs'] = inputs['VS_zeta'] if rosco_init_options['Flp_Mode'] > 0: rosco_init_options['omega_flp'] = inputs['Flp_omega'] rosco_init_options['zeta_flp'] = inputs['Flp_zeta'] else: rosco_init_options['omega_flp'] = 0.0 rosco_init_options['zeta_flp'] = 0.0 # rosco_init_options['max_pitch'] = float(inputs['max_pitch']) rosco_init_options['min_pitch'] = float(inputs['min_pitch']) rosco_init_options['vs_minspd'] = float(inputs['vs_minspd']) rosco_init_options['ss_vsgain'] = float(inputs['ss_vsgain']) rosco_init_options['ss_pcgain'] = float(inputs['ss_pcgain']) rosco_init_options['ps_percent'] = float(inputs['ps_percent']) if rosco_init_options['Flp_Mode'] > 0: rosco_init_options['flp_maxpit'] = float(inputs['delta_max_pos']) else: rosco_init_options['flp_maxpit'] = None # rosco_init_options['ss_cornerfreq'] = None rosco_init_options['sd_maxpit'] = None rosco_init_options['sd_cornerfreq'] = None # Define necessary turbine parameters WISDEM_turbine = type('', (), {})() WISDEM_turbine.v_min = float(inputs['v_min']) WISDEM_turbine.J = float(inputs['rotor_inertia']) WISDEM_turbine.rho = float(inputs['rho']) WISDEM_turbine.rotor_radius = float(inputs['R']) WISDEM_turbine.Ng = float(inputs['gear_ratio']) # Incoming value already has gearbox eff included, so have to separate it out WISDEM_turbine.GenEff = float(inputs['generator_efficiency'] / inputs['gearbox_efficiency']) * 100. WISDEM_turbine.GBoxEff = float(inputs['gearbox_efficiency']) * 100. WISDEM_turbine.rated_rotor_speed = float(inputs['rated_rotor_speed']) WISDEM_turbine.rated_power = float(inputs['rated_power']) WISDEM_turbine.rated_torque = float( inputs['rated_torque']) / WISDEM_turbine.Ng * float( inputs['gearbox_efficiency']) WISDEM_turbine.v_rated = float(inputs['v_rated']) WISDEM_turbine.v_min = float(inputs['v_min']) WISDEM_turbine.v_max = float(inputs['v_max']) WISDEM_turbine.max_pitch_rate = float(inputs['max_pitch_rate']) WISDEM_turbine.TSR_operational = float(inputs['tsr_operational']) WISDEM_turbine.max_torque_rate = float(inputs['max_torque_rate']) WISDEM_turbine.TowerHt = float(inputs['TowerHt']) # Floating Feedback Filters WISDEM_turbine.twr_freq = float(inputs['twr_freq']) WISDEM_turbine.ptfm_freq = float(inputs['ptfm_freq']) # Load Cp tables self.Cp_table = inputs['Cp_table'] self.Ct_table = inputs['Ct_table'] self.Cq_table = inputs['Cq_table'] self.pitch_vector = WISDEM_turbine.pitch_initial_rad = inputs[ 'pitch_vector'] self.tsr_vector = WISDEM_turbine.TSR_initial = inputs['tsr_vector'] self.Cp_table = WISDEM_turbine.Cp_table = self.Cp_table.reshape( len(self.pitch_vector), len(self.tsr_vector)) self.Ct_table = WISDEM_turbine.Ct_table = self.Ct_table.reshape( len(self.pitch_vector), len(self.tsr_vector)) self.Cq_table = WISDEM_turbine.Cq_table = self.Cq_table.reshape( len(self.pitch_vector), len(self.tsr_vector)) RotorPerformance = ROSCO_turbine.RotorPerformance WISDEM_turbine.Cp = RotorPerformance(self.Cp_table, self.pitch_vector, self.tsr_vector) WISDEM_turbine.Ct = RotorPerformance(self.Ct_table, self.pitch_vector, self.tsr_vector) WISDEM_turbine.Cq = RotorPerformance(self.Cq_table, self.pitch_vector, self.tsr_vector) # Load blade info to pass to flap controller tuning process if rosco_init_options['Flp_Mode'] >= 1: # Create airfoils af = [None] * self.n_span for i in range(self.n_span): if self.n_tab > 1: ref_tab = int(np.floor(self.n_tab / 2)) af[i] = CCAirfoil(inputs['airfoils_aoa'], inputs['airfoils_Re'], inputs['airfoils_cl'][i, :, :, ref_tab], inputs['airfoils_cd'][i, :, :, ref_tab], inputs['airfoils_cm'][i, :, :, ref_tab]) else: af[i] = CCAirfoil(inputs['airfoils_aoa'], inputs['airfoils_Re'], inputs['airfoils_cl'][i, :, :, 0], inputs['airfoils_cd'][i, :, :, 0], inputs['airfoils_cm'][i, :, :, 0]) # Initialize CCBlade as cc_rotor object WISDEM_turbine.cc_rotor = CCBlade( inputs['r'], inputs['chord'], inputs['theta'], af, inputs['Rhub'], inputs['Rtip'], discrete_inputs['nBlades'], inputs['rho'], inputs['mu'], inputs['precone'], inputs['tilt'], inputs['yaw'], inputs['shearExp'], inputs['hub_height'], discrete_inputs['nSector'], inputs['precurve'], inputs['precurveTip'], inputs['presweep'], inputs['presweepTip'], discrete_inputs['tiploss'], discrete_inputs['hubloss'], discrete_inputs['wakerotation'], discrete_inputs['usecd']) # Load aerodynamic performance data for blades WISDEM_turbine.af_data = [{} for i in range(self.n_span)] for i in range(self.n_span): # Check number of flap positions for each airfoil section if self.n_tab > 1: if inputs['airfoils_Ctrl'][ i, 0, 0] == inputs['airfoils_Ctrl'][i, 0, 1]: n_tabs = 1 # If all Ctrl angles of the flaps are identical then no flaps else: n_tabs = self.n_tab else: n_tabs = 1 # Save data for each flap position for j in range(n_tabs): WISDEM_turbine.af_data[i][j] = {} WISDEM_turbine.af_data[i][j]['NumTabs'] = n_tabs WISDEM_turbine.af_data[i][j]['Ctrl'] = inputs[ 'airfoils_Ctrl'][i, 0, j] WISDEM_turbine.af_data[i][j]['Alpha'] = np.array( inputs['airfoils_aoa']).flatten().tolist() WISDEM_turbine.af_data[i][j]['Cl'] = np.array( inputs['airfoils_cl'][i, :, 0, j]).flatten().tolist() WISDEM_turbine.af_data[i][j]['Cd'] = np.array( inputs['airfoils_cd'][i, :, 0, j]).flatten().tolist() WISDEM_turbine.af_data[i][j]['Cm'] = np.array( inputs['airfoils_cm'][i, :, 0, j]).flatten().tolist() # Save some more airfoil info WISDEM_turbine.span = inputs['r'] WISDEM_turbine.chord = inputs['chord'] WISDEM_turbine.twist = inputs['theta'] WISDEM_turbine.bld_flapwise_freq = float( inputs['flap_freq']) * 2 * np.pi WISDEM_turbine.bld_flapwise_damp = self.modeling_options['Level3'][ 'ROSCO']['Bld_FlpDamp'] # Tune Controller! controller = ROSCO_controller.Controller(rosco_init_options) controller.tune_controller(WISDEM_turbine) # DISCON Parameters # - controller self.modeling_options['openfast']['fst_vt']['DISCON_in'] = {} self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'LoggingLevel'] = controller.LoggingLevel self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'F_LPFType'] = controller.F_LPFType self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'F_NotchType'] = controller.F_NotchType self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'IPC_ControlMode'] = controller.IPC_ControlMode self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'VS_ControlMode'] = controller.VS_ControlMode self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'PC_ControlMode'] = controller.PC_ControlMode self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'Y_ControlMode'] = controller.Y_ControlMode self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'SS_Mode'] = controller.SS_Mode self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'WE_Mode'] = controller.WE_Mode self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'PS_Mode'] = controller.PS_Mode self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'SD_Mode'] = controller.SD_Mode self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'Fl_Mode'] = controller.Fl_Mode self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'Flp_Mode'] = controller.Flp_Mode self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'F_LPFDamping'] = controller.F_LPFDamping self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'F_SSCornerFreq'] = controller.ss_cornerfreq self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'PC_GS_angles'] = controller.pitch_op_pc self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'PC_GS_KP'] = controller.pc_gain_schedule.Kp self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'PC_GS_KI'] = controller.pc_gain_schedule.Ki self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'PC_MaxPit'] = controller.max_pitch self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'PC_MinPit'] = controller.min_pitch self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'IPC_Ki'] = float(inputs['IPC_Ki1p']) self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'VS_MinOMSpd'] = controller.vs_minspd self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'VS_Rgn2K'] = controller.vs_rgn2K self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'VS_RefSpd'] = controller.vs_refspd self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'VS_KP'] = controller.vs_gain_schedule.Kp self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'VS_KI'] = controller.vs_gain_schedule.Ki self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'SS_VSGain'] = controller.ss_vsgain self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'SS_PCGain'] = controller.ss_pcgain self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'WE_FOPoles_N'] = len(controller.v) self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'WE_FOPoles_v'] = controller.v self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'WE_FOPoles'] = controller.A self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'ps_wind_speeds'] = controller.v self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'PS_BldPitchMin'] = controller.ps_min_bld_pitch self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'SD_MaxPit'] = controller.sd_maxpit + 0.1 self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'SD_CornerFreq'] = controller.sd_cornerfreq self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'Fl_Kp'] = controller.Kp_float self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'Flp_Kp'] = controller.Kp_flap self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'Flp_Ki'] = controller.Ki_flap self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'Flp_MaxPit'] = controller.flp_maxpit self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'Flp_Angle'] = 0. # - turbine self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'WE_BladeRadius'] = WISDEM_turbine.rotor_radius self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'v_rated'] = float(inputs['v_rated']) self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'F_FlpCornerFreq'] = [ float(inputs['flap_freq']) * 2 * np.pi / 3., 0.7 ] self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'F_LPFCornerFreq'] = float(inputs['edge_freq']) * 2 * np.pi / 4. self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'F_NotchCornerFreq'] = WISDEM_turbine.twr_freq # inputs(['twr_freq']) # zero for now, fix when floating introduced to WISDEM self.modeling_options['openfast'][ 'fst_vt']['DISCON_in']['F_FlCornerFreq'] = [ WISDEM_turbine.ptfm_freq, 0.707 ] # inputs(['ptfm_freq']) # zero for now, fix when floating introduced to WISDEM self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'PC_MaxRat'] = WISDEM_turbine.max_pitch_rate self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'PC_MinRat'] = -WISDEM_turbine.max_pitch_rate self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'VS_MaxRat'] = WISDEM_turbine.max_torque_rate self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'PC_RefSpd'] = WISDEM_turbine.rated_rotor_speed * WISDEM_turbine.Ng self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'VS_RtPwr'] = WISDEM_turbine.rated_power self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'VS_RtTq'] = WISDEM_turbine.rated_torque self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'VS_MaxTq'] = WISDEM_turbine.rated_torque * 1.1 self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'VS_TSRopt'] = WISDEM_turbine.TSR_operational self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'WE_RhoAir'] = WISDEM_turbine.rho self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'WE_GearboxRatio'] = WISDEM_turbine.Ng self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'WE_Jtot'] = WISDEM_turbine.J self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'Cp_pitch_initial_rad'] = self.pitch_vector self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'Cp_TSR_initial'] = self.tsr_vector self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'Cp_table'] = WISDEM_turbine.Cp_table self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'Ct_table'] = WISDEM_turbine.Ct_table self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'Cq_table'] = WISDEM_turbine.Cq_table self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'Cp'] = WISDEM_turbine.Cp self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'Ct'] = WISDEM_turbine.Ct self.modeling_options['openfast']['fst_vt']['DISCON_in'][ 'Cq'] = WISDEM_turbine.Cq # Outputs if rosco_init_options['Flp_Mode'] >= 1: outputs[ 'flptune_coeff1'] = 2 * WISDEM_turbine.bld_flapwise_damp * WISDEM_turbine.bld_flapwise_freq + controller.kappa[ -1] * WISDEM_turbine.bld_flapwise_freq**2 * controller.Kp_flap[ -1] outputs['flptune_coeff2'] = WISDEM_turbine.bld_flapwise_freq**2 * ( controller.Ki_flap[-1] * controller.kappa[-1] + 1) outputs['PC_Kp'] = controller.pc_gain_schedule.Kp[0] outputs['PC_Ki'] = controller.pc_gain_schedule.Ki[0] outputs['Flp_Kp'] = controller.Kp_flap[-1] outputs['Flp_Ki'] = controller.Ki_flap[-1]
def gen_control_cases(self, input_params, DISCON_params, values, group): ''' Generate control case input dictionary for controller parameters Parameters ---------- input_params: list List of parameters that exist in the controller tuning yaml file that will be modified DISCON_params: list List of parameters in DISCON.IN that will be changed by the paremeters in input_params values: list List with nested lists of floats that correspond to the input_params. - i.e. [[0.1],[0.5]] group: int Group number for case_inputs Returns ------- case_inputs: dict Dictionary of case inputs for WISDEM's CaseGen_General tuning_inputs: dict Dictionary containing yaml input tuning parameters ''' # Load turbine turbine = ROSCO_turbine.Turbine(self.turbine_params) turbine.load_from_fast(self.path_params['FAST_InputFile'], self.path_params['FAST_directory'], dev_branch=True) # if not os.path.exists(self.path_params['rotor_performance_filename']): # R.write_rotor_performance(turbine,txt_filename=path_params['rotor_performance_filename']) # Check for flaps if 'zeta_flp' in input_params or 'omega_flp' in input_params: self.controller_params['Flp_Mode'] = 2 turbine.load_blade_info() # Create tuning value matrix tuning_matrix = list(itertools.product(*values)) # Generate cases case_inputs = {} tuning_inputs = {key: [] for key in input_params} DISCON_vals_list = {key: [] for key in DISCON_params} for tuning_params in tuning_matrix: for inp_ind, inp_p in enumerate(input_params): # Modify controller parameters self.controller_params[inp_p] = tuning_params[inp_ind] # tuning_inputs[inp_p].append(tuning_params[inp_ind]) # Initialize and tune controller controller = ROSCO_controller.Controller(self.controller_params) controller.tune_controller(turbine) # Get DISCON input parameters data_processing = ROSCO_Utilities.DataProcessing() DISCON_inputs = data_processing.DISCON_dict(turbine, controller) # Check for invalid controller inputs if (any(item in ['VS_KP', 'VS_KI'] for item in DISCON_params) and any(DISCON_inputs[DISCON_p][0] > 0 for DISCON_p in DISCON_params)): print( 'WARNING: Control gains cannot be greater than zero and are for {} = {}' .format([param for param in input_params], tuning_params)) elif (any(item in ['Flp_Kp', 'Flp_Ki'] for item in DISCON_params) and any(DISCON_inputs[DISCON_p][0] < 0 for DISCON_p in DISCON_params)): print( 'WARNING: Control gains cannot be less than zero and are for {} = {}' .format([param for param in input_params], tuning_params)) # Save DISCON and tuning inputs else: for DISCON_p in DISCON_params: DISCON_vals = DISCON_inputs[DISCON_p] DISCON_vals_list[DISCON_p].append(DISCON_vals) for inp_ind, inp_p in enumerate(input_params): tuning_inputs[inp_p].append(tuning_params[inp_ind]) # Write case_inputs for DISCON_p in DISCON_params: case_inputs[('DISCON_in', DISCON_p)] = { 'vals': DISCON_vals_list[DISCON_p], 'group': group } return case_inputs, tuning_inputs
def run_PC_sweep(omega, zeta=1.0): # Process inputs, single (omega, zeta) or multiple? # Turbine inputs iec = CaseGen_IEC() iec.Turbine_Class = 'I' # Wind class I, II, III, IV iec.Turbulence_Class = 'B' # Turbulence class 'A', 'B', or 'C' iec.D = 240. # Rotor diameter to size the wind grid iec.z_hub = 150. # Hub height to size the wind grid cut_in = 3. # Cut in wind speed cut_out = 25. # Cut out wind speed n_ws = 3 # Number of wind speed bins TMax = 800. # Length of wind grids and OpenFAST simulations, suggested 720 s Vrated = 10.59 # Rated wind speed Ttrans = max([ 0., TMax - 60. ]) # Start of the transient for DLC with a transient, e.g. DLC 1.4 TStart = max([0., TMax - 600. ]) # Start of the recording of the channels of OpenFAST iec.cores = 1 iec.overwrite = False # Initial conditions to start the OpenFAST runs u_ref = np.arange(3., 26.) # Wind speed pitch_ref = [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.5058525323662666, 5.253759185225932, 7.50413344606208, 9.310153958810268, 10.8972969450052, 12.412247669440042, 13.883219268525659, 15.252012626933068, 16.53735488246438, 17.76456777500061, 18.953261878035104, 20.11055307762722, 21.238680277668898, 22.30705111326602, 23.455462501156205 ] # Pitch values in deg omega_ref = [ 2.019140272160114, 2.8047214918577925, 3.594541645994511, 4.359025795823625, 5.1123509774611025, 5.855691196288371, 6.589281196735111, 7.312788026081227, 7.514186181824161, 7.54665511646938, 7.573823812448151, 7.600476033113538, 7.630243938880304, 7.638301051122195, 7.622050377183605, 7.612285710588359, 7.60743945212863, 7.605865650155881, 7.605792924227456, 7.6062185247519825, 7.607153933765292, 7.613179734210654, 7.606737845170748 ] # Rotor speeds in rpm iec.init_cond = {} iec.init_cond[("ElastoDyn", "RotSpeed")] = {'U': u_ref} iec.init_cond[("ElastoDyn", "RotSpeed")]['val'] = omega_ref iec.init_cond[("ElastoDyn", "BlPitch1")] = {'U': u_ref} iec.init_cond[("ElastoDyn", "BlPitch1")]['val'] = pitch_ref iec.init_cond[("ElastoDyn", "BlPitch2")] = iec.init_cond[("ElastoDyn", "BlPitch1")] iec.init_cond[("ElastoDyn", "BlPitch3")] = iec.init_cond[("ElastoDyn", "BlPitch1")] iec.init_cond[("HydroDyn", "WaveHs")] = { 'U': [3, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 25, 40, 50] } iec.init_cond[("HydroDyn", "WaveHs")]['val'] = [ 1.101917033, 1.101917033, 1.179052649, 1.315715154, 1.536867124, 1.835816514, 2.187994638, 2.598127096, 3.061304068, 3.617035443, 4.027470219, 4.51580671, 4.51580671, 6.98, 10.7 ] iec.init_cond[("HydroDyn", "WaveTp")] = { 'U': [3, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 25, 40, 50] } iec.init_cond[("HydroDyn", "WaveTp")]['val'] = [ 8.515382435, 8.515382435, 8.310063688, 8.006300889, 7.6514231, 7.440581338, 7.460834063, 7.643300307, 8.046899942, 8.521314105, 8.987021024, 9.451641026, 9.451641026, 11.7, 14.2 ] iec.init_cond[("HydroDyn", "PtfmSurge")] = {'U': [3., 15., 25.]} iec.init_cond[("HydroDyn", "PtfmSurge")]['val'] = [4., 15., 10.] iec.init_cond[("HydroDyn", "PtfmPitch")] = {'U': [3., 15., 25.]} iec.init_cond[("HydroDyn", "PtfmPitch")]['val'] = [-1., 3., 1.3] iec.init_cond[("HydroDyn", "PtfmHeave")] = {'U': [3., 25.]} iec.init_cond[("HydroDyn", "PtfmHeave")]['val'] = [0.5, 0.5] # DLC inputs if False: wind_speeds = np.linspace(int(cut_in), int(cut_out), int(n_ws)) iec.dlc_inputs = {} iec.dlc_inputs['DLC'] = [1.1, 1.3, 1.4, 1.5, 5.1, 6.1, 6.3] iec.dlc_inputs['U'] = [ wind_speeds, wind_speeds, [Vrated - 2., Vrated, Vrated + 2.], wind_speeds, [Vrated - 2., Vrated, Vrated + 2., cut_out], [], [] ] iec.dlc_inputs['Seeds'] = [[1], [1], [], [], [1], [1], [1]] # iec.dlc_inputs['Seeds'] = [range(1,7), range(1,7),[],[], range(1,7), range(1,7), range(1,7)] iec.dlc_inputs['Yaw'] = [[], [], [], [], [], [], []] else: wind_speeds = [18] iec.dlc_inputs = {} iec.dlc_inputs['DLC'] = [1.1] iec.dlc_inputs['U'] = [wind_speeds] iec.dlc_inputs['Seeds'] = [[1]] # iec.dlc_inputs['Seeds'] = [range(1,7), range(1,7),[],[], range(1,7), range(1,7), range(1,7)] iec.dlc_inputs['Yaw'] = [[]] iec.PC_MaxRat = 2. iec.TStart = Ttrans iec.TMax = TMax # wind file length iec.transient_dir_change = 'both' # '+','-','both': sign for transient events in EDC, EWS iec.transient_shear_orientation = 'both' # 'v','h','both': vertical or horizontal shear for EWS iec.wind_dir = 'outputs/wind' # Management of parallelization # not using for now, copy from run_DLC.py if needed later iec.parallel_windfile_gen = True iec.cores = 4 iec.run_dir = 'outputs/iea15mw/PC_sweep_play' # Run case generator / wind file writing case_inputs = {} case_inputs[("Fst", "TMax")] = {'vals': [TMax], 'group': 0} case_inputs[("Fst", "TStart")] = {'vals': [TStart], 'group': 0} # case_inputs[("Fst","DT_Out")] = {'vals':[0.01], 'group':0} #0.005 case_inputs[("Fst", "OutFileFmt")] = {'vals': [2], 'group': 0} case_inputs[("Fst", "CompHydro")] = {'vals': [1], 'group': 0} case_inputs[("Fst", "CompSub")] = {'vals': [0], 'group': 0} case_inputs[("InflowWind", "WindType")] = {'vals': [1], 'group': 0} case_inputs[("ElastoDyn", "TwFADOF1")] = {'vals': ["True"], 'group': 0} case_inputs[("ElastoDyn", "TwFADOF2")] = {'vals': ["True"], 'group': 0} case_inputs[("ElastoDyn", "TwSSDOF1")] = {'vals': ["True"], 'group': 0} case_inputs[("ElastoDyn", "TwSSDOF2")] = {'vals': ["True"], 'group': 0} 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", "DrTrDOF")] = {'vals': ["False"], 'group': 0} case_inputs[("ElastoDyn", "GenDOF")] = {'vals': ["True"], 'group': 0} case_inputs[("ElastoDyn", "YawDOF")] = {'vals': ["False"], 'group': 0} case_inputs[("ElastoDyn", "PtfmSgDOF")] = {'vals': ["True"], 'group': 0} case_inputs[("ElastoDyn", "PtfmSwDOF")] = {'vals': ["True"], 'group': 0} case_inputs[("ElastoDyn", "PtfmHvDOF")] = {'vals': ["True"], 'group': 0} case_inputs[("ElastoDyn", "PtfmRDOF")] = {'vals': ["True"], 'group': 0} case_inputs[("ElastoDyn", "PtfmPDOF")] = {'vals': ["True"], 'group': 0} case_inputs[("ElastoDyn", "PtfmYDOF")] = {'vals': ["True"], 'group': 0} case_inputs[("ServoDyn", "PCMode")] = {'vals': [5], 'group': 0} case_inputs[("ServoDyn", "VSContrl")] = {'vals': [5], 'group': 0} run_dir1 = os.path.dirname( os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) + os.sep if platform.system() == 'Windows': path2dll = os.path.join(run_dir1, 'local/lib/libdiscon.dll') elif platform.system() == 'Darwin': path2dll = os.path.join(run_dir1, 'local/lib/libdiscon.dylib') else: path2dll = os.path.join(run_dir1, 'local/lib/libdiscon.so') case_inputs[("ServoDyn", "DLL_FileName")] = { 'vals': [path2dll], 'group': 0 } case_inputs[("AeroDyn15", "TwrAero")] = {'vals': ["True"], 'group': 0} case_inputs[("AeroDyn15", "TwrPotent")] = {'vals': [1], 'group': 0} case_inputs[("AeroDyn15", "TwrShadow")] = {'vals': [1], 'group': 0} case_inputs[("HydroDyn", "WaveMod")] = {'vals': [2], 'group': 0} case_inputs[("HydroDyn", "WvDiffQTF")] = {'vals': ["False"], 'group': 0} channels = {} for var in [ "TipDxc1", "TipDyc1", "TipDzc1", "TipDxb1", "TipDyb1", "TipDxc2", "TipDyc2", "TipDzc2", "TipDxb2", "TipDyb2", "TipDxc3", "TipDyc3", "TipDzc3", "TipDxb3", "TipDyb3", "RootMxc1", "RootMyc1", "RootMzc1", "RootMxb1", "RootMyb1", "RootMxc2", "RootMyc2", "RootMzc2", "RootMxb2", "RootMyb2", "RootMxc3", "RootMyc3", "RootMzc3", "RootMxb3", "RootMyb3", "TwrBsMxt", "TwrBsMyt", "TwrBsMzt", "GenPwr", "GenTq", "RotThrust", "RtAeroCp", "RtAeroCt", "RotSpeed", "BldPitch1", "TTDspSS", "TTDspFA", "NacYaw", "Wind1VelX", "Wind1VelY", "Wind1VelZ", "LSSTipMxa", "LSSTipMya", "LSSTipMza", "LSSTipMxs", "LSSTipMys", "LSSTipMzs", "LSShftFys", "LSShftFzs", "TipRDxr", "TipRDyr", "TipRDzr" ]: channels[var] = True # mass sweep # case_inputs[("ElastoDyn","PtfmMass")] = {'vals': (1.7838E+07*np.array([.7,.8,.9,1,1.1,1.2,1.3])).tolist(), 'group':3} # case_inputs[("ElastoDyn","PtfmRIner")] = {'vals':(1.2507E+10*np.array([.7,.8,.9,1,1.1,1.2,1.3])).tolist(), 'group':3} # case_inputs[("ElastoDyn","PtfmPIner")] = {'vals':(1.2507E+10*np.array([.7,.8,.9,1,1.1,1.2,1.3])).tolist(), 'group':3} # case_inputs[("ElastoDyn","PtfmYIner")] = {'vals':(2.3667E+10*np.array([.7,.8,.9,1,1.1,1.2,1.3])).tolist(), 'group':3} # controller params # load default params print('here') rt_dir = os.path.join( os.path.dirname( os.path.dirname(os.path.dirname(os.path.realpath(__file__)))), 'ROSCO_toolbox') rt_dir = '/Users/dzalkind/Tools/ROSCO_toolbox' weis_dir = os.path.join(rt_dir, 'Tune_Cases') control_param_yaml = os.path.join(rt_dir, 'Tune_Cases', 'IEA15MW.yaml') inps = yaml.safe_load(open(control_param_yaml)) path_params = inps['path_params'] turbine_params = inps['turbine_params'] controller_params = inps['controller_params'] # make default controller, turbine objects for ROSCO_toolbox turbine = ROSCO_turbine.Turbine(turbine_params) turbine.load_from_fast(path_params['FAST_InputFile'], os.path.join(rt_dir, path_params['FAST_directory']), dev_branch=True) controller = ROSCO_controller.Controller(controller_params) # tune default controller controller.tune_controller(turbine) # check if inputs are lists if not isinstance(omega, list): omega = [omega] if not isinstance(zeta, list): zeta = [zeta] # Loop through and make PI gains pc_kp = [] pc_ki = [] omega_zeta = [] # flattened (omega,zeta) pairs for o in omega: for z in zeta: controller.omega_pc = o controller.zeta_pc = z controller.tune_controller(turbine) pc_kp.append(controller.pc_gain_schedule.Kp.tolist()) pc_ki.append(controller.pc_gain_schedule.Ki.tolist()) omega_zeta.append((o, z)) # add control gains to case_list case_inputs[('DISCON_in', 'PC_GS_KP')] = {'vals': pc_kp, 'group': 3} case_inputs[('DISCON_in', 'PC_GS_KI')] = {'vals': pc_ki, 'group': 3} iec.case_name_base = 'pc_play' # generate cases case_list, case_name_list, dlc_list = iec.execute(case_inputs=case_inputs) #for var in var_out+[var_x]: # Run FAST cases fastBatch = runFAST_pywrapper_batch(FAST_ver='OpenFAST', dev_branch=True) # Monopile # fastBatch.FAST_InputFile = 'IEA-15-240-RWT-Monopile.fst' # FAST input file (ext=.fst) # run_dir2 = os.path.dirname( os.path.dirname( os.path.realpath(__file__) ) ) + os.sep # fastBatch.FAST_directory = os.path.join(run_dir2, 'OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-Monopile') # Path to fst directory files fastBatch.channels = channels # fastBatch.FAST_runDirectory = iec.run_dir fastBatch.case_list = case_list fastBatch.case_name_list = case_name_list fastBatch.debug_level = 2 # if MPI: # fastBatch.run_mpi(comm_map_down) # else: # fastBatch.run_serial() # U-Maine semi-sub fastBatch.FAST_InputFile = 'IEA-15-240-RWT-UMaineSemi.fst' # FAST input file (ext=.fst) run_dir2 = os.path.dirname(os.path.realpath(__file__)) + os.sep fastBatch.FAST_directory = os.path.join( run_dir2, 'OpenFAST_models', 'IEA-15-240-RWT', 'IEA-15-240-RWT-UMaineSemi') # Path to fst directory files fastBatch.FAST_runDirectory = iec.run_dir if True: fastBatch.run_multi(cores=4) else: fastBatch.run_serial()
os.path.dirname(os.path.realpath(__file__)), '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)