# Turbine Ontology input fname_schema = "turbine_inputs/IEAontology_schema.yaml" fname_input = "turbine_inputs/nrel5mw_mod_update.yaml" # fname_input = "/mnt/c/Users/egaertne/IEA-15-240-RWT/WISDEM/IEA-15-240-RWT.yaml" # fname_input = "/mnt/c/Users/egaertne/IEA-15-240-RWT/WISDEM/IEA-15-240-RWT_TipShape.yaml" output_folder = "test/" fname_output = output_folder + 'test_out.yaml' Analysis_Level = 0 # 0: Run CCBlade; 1: Update FAST model at each iteration but do not run; 2: Run FAST w/ ElastoDyn; 3: (Not implemented) Run FAST w/ BeamDyn # Initialize blade design refBlade = ReferenceBlade() refBlade.verbose = True refBlade.NINPUT = 8 refBlade.NPTS = 50 refBlade.apply_stall_delay = False refBlade.spar_var = ['Spar_Cap_SS', 'Spar_Cap_PS'] # SS, then PS refBlade.te_var = 'TE_reinforcement' # refBlade.le_var = 'le_reinf' refBlade.validate = False refBlade.fname_schema = fname_schema blade = refBlade.initialize(fname_input) # Set FAST Inputs if Analysis_Level >= 1: # File management FASTpref = {} FASTpref['Analysis_Level'] = Analysis_Level FASTpref['FAST_ver'] = 'OpenFAST' FASTpref['dev_branch'] = True FASTpref[
def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): # initialization point # if discrete_inputs['blade_in_overwrite'] != {}: # blade = copy.deepcopy(discrete_inputs['blade_in_overwrite']) # else: blade = copy.deepcopy(self.refBlade) NINPUT = len(blade['ctrl_pts']['r_in']) # Set inputs to update blade geometry Rhub = inputs['hubFraction'] * inputs['bladeLength'] Rtip = Rhub + inputs['bladeLength'] outputs['Rhub'] = Rhub outputs['Rtip'] = Rtip r_in = blade['ctrl_pts']['r_in'] outputs['r_in'] = Rhub + (Rtip - Rhub) * np.array(r_in) blade['ctrl_pts']['bladeLength'] = inputs['bladeLength'] blade['ctrl_pts']['r_in'] = r_in blade['ctrl_pts']['chord_in'] = inputs['chord_in'] blade['ctrl_pts']['theta_in'] = inputs['theta_in'] blade['ctrl_pts']['precurve_in'] = inputs['precurve_in'] blade['ctrl_pts']['presweep_in'] = inputs['presweep_in'] blade['ctrl_pts']['sparT_in'] = inputs['sparT_in'] blade['ctrl_pts']['teT_in'] = inputs['teT_in'] # blade['ctrl_pts']['leT_in'] = inputs['leT_in'] blade['ctrl_pts']['r_max_chord'] = inputs['r_max_chord'] #check that airfoil positions are increasing correct_af_position = False airfoil_position = copy.deepcopy(inputs['airfoil_position']).tolist() for i in reversed(range(1, len(airfoil_position))): if airfoil_position[i] <= airfoil_position[i - 1]: airfoil_position[i - 1] = airfoil_position[i] - 0.001 correct_af_position = True if correct_af_position: blade['outer_shape_bem']['airfoil_position'][ 'grid'] = airfoil_position warning_corrected_airfoil_position = "Airfoil spanwise positions must be increasing. Changed from: %s to: %s" % ( inputs['airfoil_position'].tolist(), airfoil_position) warnings.warn(warning_corrected_airfoil_position) else: blade['outer_shape_bem']['airfoil_position']['grid'] = inputs[ 'airfoil_position'].tolist() # Update refBlade = ReferenceBlade() refBlade.verbose = False refBlade.NINPUT = len(outputs['r_in']) refBlade.NPTS = len(blade['pf']['s']) refBlade.analysis_level = blade['analysis_level'] refBlade.apply_stall_delay = blade['apply_stall_delay'] refBlade.user_update_routine = self.options['user_update_routine'] if blade['analysis_level'] < 3: refBlade.spar_var = blade['precomp']['spar_var'] refBlade.te_var = blade['precomp']['te_var'] # if 'le_var' in blade['precomp']: # refBlade.le_var = blade['precomp']['le_var'] blade_out = refBlade.update(blade) # Get geometric outputs outputs['hub_diameter'] = 2.0 * Rhub outputs['r'] = Rhub + (Rtip - Rhub) * np.array(blade_out['pf']['s']) outputs['diameter'] = 2.0 * outputs['r'][-1] outputs['chord'] = blade_out['pf']['chord'] outputs['max_chord'] = max(blade_out['pf']['chord']) outputs['theta'] = blade_out['pf']['theta'] outputs['precurve'] = blade_out['pf']['precurve'] outputs['presweep'] = blade_out['pf']['presweep'] outputs['rthick'] = blade_out['pf']['rthick'] outputs['le_location'] = blade_out['pf']['p_le'] # airfoils = blade_out['airfoils'] outputs['airfoils_cl'] = blade_out['airfoils_cl'] outputs['airfoils_cd'] = blade_out['airfoils_cd'] outputs['airfoils_cm'] = blade_out['airfoils_cm'] outputs['airfoils_aoa'] = blade_out['airfoils_aoa'] outputs['airfoils_Re'] = blade_out['airfoils_Re'] upperCS = blade_out['precomp']['upperCS'] lowerCS = blade_out['precomp']['lowerCS'] websCS = blade_out['precomp']['websCS'] profile = blade_out['precomp']['profile'] materials = blade_out['precomp']['materials'] for i in range(len(profile)): outputs['airfoils_coord_x'][:, i] = blade_out['profile'][:, 0, i] outputs['airfoils_coord_y'][:, i] = blade_out['profile'][:, 1, i] # Assumptions: # - if the composite layer is divided into multiple regions (i.e. if the spar cap is split into 3 regions due to the web locations), # the middle region is selected with int(n_reg/2), note for an even number of regions, this rounds up sector_idx_strain_spar_ss = blade_out['precomp'][ 'sector_idx_strain_spar_ss'] sector_idx_strain_spar_ps = blade_out['precomp'][ 'sector_idx_strain_spar_ps'] sector_idx_strain_te_ss = blade_out['precomp'][ 'sector_idx_strain_te_ss'] sector_idx_strain_te_ps = blade_out['precomp'][ 'sector_idx_strain_te_ps'] # Get Beam Properties beam = PreComp(outputs['r'], outputs['chord'], outputs['theta'], outputs['le_location'], outputs['precurve'], outputs['presweep'], profile, materials, upperCS, lowerCS, websCS, sector_idx_strain_spar_ps, sector_idx_strain_spar_ss, sector_idx_strain_te_ps, sector_idx_strain_te_ss) EIxx, EIyy, GJ, EA, EIxy, x_ec, y_ec, rhoA, rhoJ, Tw_iner, flap_iner, edge_iner = beam.sectionProperties( ) outputs['eps_crit_spar'] = beam.panelBucklingStrain( sector_idx_strain_spar_ss) outputs['eps_crit_te'] = beam.panelBucklingStrain( sector_idx_strain_te_ss) xu_strain_spar, xl_strain_spar, yu_strain_spar, yl_strain_spar = beam.criticalStrainLocations( sector_idx_strain_spar_ss, sector_idx_strain_spar_ps) xu_strain_te, xl_strain_te, yu_strain_te, yl_strain_te = beam.criticalStrainLocations( sector_idx_strain_te_ss, sector_idx_strain_te_ps) outputs['z'] = outputs['r'] outputs['EIxx'] = EIxx outputs['EIyy'] = EIyy outputs['GJ'] = GJ outputs['EA'] = EA outputs['EIxy'] = EIxy outputs['x_ec'] = x_ec outputs['y_ec'] = y_ec outputs['rhoA'] = rhoA outputs['rhoJ'] = rhoJ outputs['Tw_iner'] = Tw_iner outputs['flap_iner'] = flap_iner outputs['edge_iner'] = edge_iner outputs['xu_strain_spar'] = xu_strain_spar outputs['xl_strain_spar'] = xl_strain_spar outputs['yu_strain_spar'] = yu_strain_spar outputs['yl_strain_spar'] = yl_strain_spar outputs['xu_strain_te'] = xu_strain_te outputs['xl_strain_te'] = xl_strain_te outputs['yu_strain_te'] = yu_strain_te outputs['yl_strain_te'] = yl_strain_te # Blade cost model bcm = blade_cost_model( options=self.options ) # <------------- options, import blade cost model bcm.name = blade_out['config']['name'] bcm.materials = materials bcm.upperCS = upperCS bcm.lowerCS = lowerCS bcm.websCS = websCS bcm.profile = profile bcm.chord = outputs['chord'] bcm.r = (outputs['r'] - outputs['Rhub']) / ( outputs['Rtip'] - outputs['Rhub']) * float(inputs['bladeLength']) bcm.bladeLength = float(inputs['bladeLength']) bcm.le_location = outputs['le_location'] blade_cost, blade_mass = bcm.execute_blade_cost_model() outputs['total_blade_cost'] = blade_cost outputs['total_blade_mass'] = blade_mass # discrete_outputs['blade_out'] = blade_out outputs['sparT_in_out'] = inputs['sparT_in']