def run_problem(optFlag=False, prob_ref=None): # Initialize blade design refBlade = ReferenceBlade() if rank == 0: refBlade.verbose = True else: refBlade.verbose = False refBlade.NINPUT = 8 Nsection_Tow = 19 refBlade.NPTS = 30 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) Analysis_Level = 0 FASTpref = {} FASTpref['Analysis_Level'] = Analysis_Level fst_vt = {} # Initialize and execute OpenMDAO problem with input data if MPI: num_par_fd = MPI.COMM_WORLD.Get_size() prob = om.Problem(model=om.Group(num_par_fd=num_par_fd)) prob.model.approx_totals(method='fd') prob.model.add_subsystem('comp', Optimize_MonopileTurbine( RefBlade=blade, Nsection_Tow=Nsection_Tow, folder_output=folder_output), promotes=['*']) else: prob = om.Problem() prob.model = Optimize_MonopileTurbine(RefBlade=blade, Nsection_Tow=Nsection_Tow, folder_output=folder_output) prob.model.nonlinear_solver = om.NonlinearRunOnce() prob.model.linear_solver = om.DirectSolver() if optFlag and not prob_ref is None: if MPI: num_par_fd = MPI.COMM_WORLD.Get_size() prob = om.Problem(model=om.Group(num_par_fd=num_par_fd)) prob.model.approx_totals(method='fd') prob.model.add_subsystem('comp', Optimize_MonopileTurbine( RefBlade=blade, Nsection_Tow=Nsection_Tow, folder_output=folder_output), promotes=['*']) else: prob = om.Problem() prob.model = Optimize_MonopileTurbine(RefBlade=blade, Nsection_Tow=Nsection_Tow, folder_output=folder_output) # --- Driver --- prob.driver = om.pyOptSparseDriver() prob.driver.options['optimizer'] = 'CONMIN' prob.driver.opt_settings['ITMAX'] = 15 prob.driver.opt_settings['IPRINT'] = 4 # ---------------------- # --- Objective --- # prob.model.add_objective('lcoe') prob.model.add_objective('AEP', scaler=-1.) #prob.model.add_objective('mass_one_blade') # ---------------------- # --- Design Variables --- indices_no_root = range(2, refBlade.NINPUT) indices_no_root_no_tip = range(2, refBlade.NINPUT - 1) indices_no_max_chord = range(3, refBlade.NINPUT) prob.model.add_design_var('sparT_in', indices=indices_no_root_no_tip, lower=0.001, upper=0.200) prob.model.add_design_var('chord_in', indices=indices_no_max_chord, lower=0.5, upper=7.0) prob.model.add_design_var('theta_in', indices=indices_no_root, lower=-7.5, upper=20.0) prob.model.add_design_var('teT_in', lower=prob_ref['teT_in'] * 0.5, upper=0.1) #prob.model.add_design_var('leT_in', lower=prob_ref['leT_in']*0.5, upper=0.1) # ---------------------- # --- Constraints --- prob.model.add_subsystem('freq_check', blade_freq_check(), promotes=['freq_check_out']) prob.model.connect('freq_curvefem', 'freq_check.freq_curvefem') #, src_indices=[0]) # Rotor prob.model.add_constraint('tip_deflection_ratio', upper=1.0) # prob.model.add_constraint('no_stall_constraint', upper=1.0) prob.model.add_constraint('freq_check_out', lower=1.1) #prob.model.add_constraint('rated_Q', lower=21.4e6, upper=21.6e6) # prob.model.add_constraint('mass_one_blade', upper=prob_ref['mass_one_blade']*1.02) prob.model.add_constraint('AEP', lower=0.99 * prob_ref['AEP']) # ---------------------- # --- Recorder --- filename_opt_log = folder_output + 'log_opt_' + blade['config']['name'] prob.driver.add_recorder(om.SqliteRecorder(filename_opt_log)) prob.driver.recording_options['includes'] = [ 'AEP', 'total_blade_cost', 'lcoe', 'tip_deflection_ratio', 'mass_one_blade', 'theta_in' ] prob.driver.recording_options['record_objectives'] = True prob.driver.recording_options['record_constraints'] = True prob.driver.recording_options['record_desvars'] = True # ---------------------- # Initialize variable inputs prob = initialize_variables(prob, blade, Analysis_Level, fst_vt) # Run initial condition no matter what print('Running at Initial Position:') prob.run_model() print('########################################') print('') print('Control variables') print('Rotor diam: {:8.3f} m'.format(prob['diameter'][0])) print('TSR: {:8.3f} -'.format(prob['control_tsr'][0])) print('Rated vel: {:8.3f} m/s'.format(prob['rated_V'][0])) print('Rated rpm: {:8.3f} rpm'.format(prob['rated_Omega'][0])) print('Rated pitch: {:8.3f} deg'.format(prob['rated_pitch'][0])) print('Rated thrust: {:8.3f} N'.format(prob['rated_T'][0])) print('Rated torque: {:8.3f} N-m'.format(prob['rated_Q'][0])) print('') print('Constraints') print('Max TD: {:8.3f} m'.format(prob['tip_deflection'][0])) print('TD ratio: {:8.3f} -'.format(prob['tip_deflection_ratio'][0])) print('Blade root M: {:8.3f} N-m'.format(prob['root_bending_moment'][0])) print('') print('Objectives') print('AEP: {:8.3f} GWh'.format(prob['AEP'][0])) print('LCoE: {:8.4f} $/MWh'.format(prob['lcoe'][0])) print('') print('Blades') print('Blade mass: {:8.3f} kg'.format(prob['mass_one_blade'][0])) print('Blade cost: {:8.3f} $'.format(prob['total_blade_cost'][0])) print('Blade freq: {:8.3f} Hz'.format(prob['freq_curvefem'][0])) print('3 blade M_of_I: ', prob['I_all_blades'], ' kg-m^2') print('Hub M: ', prob['Mxyz_total'], ' kg-m^2') print('') print('RNA Summary') print('RNA mass: {:8.3f} kg'.format(prob['tow.pre.mass'][0])) print('RNA C_of_G (TT): ', prob['rna_cg'], ' m') print('RNA M_of_I: ', prob['tow.pre.mI'], ' kg-m^2') print('') print('Tower') print('Tower top F: ', prob['tow.pre.rna_F'], ' N') print('Tower top M: ', prob['tow.pre.rna_M'], ' N-m') print('Tower freqs: ', prob['tow.post.structural_frequencies'], ' Hz') print('Tower vel: {:8.3f} kg'.format(prob['tow.wind.Uref'][0])) print('Tower mass: {:8.3f} kg'.format(prob['tower_mass'][0])) print('Tower cost: {:8.3f} $'.format(prob['tower_cost'][0])) print('########################################') # Angle of attack and stall angle faoa, axaoa = plt.subplots(1, 1, figsize=(5.3, 4)) axaoa.plot(prob['r'], prob['nostallconstraint.aoa_along_span'], label='Initial aoa') axaoa.plot(prob['r'], prob['nostallconstraint.stall_angle_along_span'], '.', label='Initial stall') axaoa.legend(fontsize=12) plt.xlabel('Blade Span [m]', fontsize=14, fontweight='bold') plt.ylabel('Angle [deg]', fontsize=14, fontweight='bold') plt.xticks(fontsize=12) plt.yticks(fontsize=12) plt.grid(color=[0.8, 0.8, 0.8], linestyle='--') plt.subplots_adjust(bottom=0.15, left=0.15) fig_name = 'aoa.png' faoa.savefig(folder_output + fig_name) # Complete data dump #prob.model.list_inputs(units=True) #prob.model.list_outputs(units=True) if optFlag: if rank == 0: print('Running Optimization:') print('N design var: ', 2 * len(indices_no_root_no_tip) + len(indices_no_root) + 1) if not MPI: prob.model.approx_totals() prob.run_driver() if rank == 0: # --- Save output .yaml --- refBlade.write_ontology(fname_output, prob['blade_out'], refBlade.wt_ref) # --- Outputs plotting --- print('AEP: \t\t\t %f\t%f GWh \t Difference: %f %%' % (prob_ref['AEP'] * 1e-6, prob['AEP'] * 1e-6, (prob['AEP'] - prob_ref['AEP']) / prob_ref['AEP'] * 100.)) print( 'LCoE: \t\t\t %f\t%f USD/MWh \t Difference: %f %%' % (prob_ref['lcoe'] * 1.e003, prob['lcoe'] * 1.e003, (prob['lcoe'] - prob_ref['lcoe']) / prob_ref['lcoe'] * 100.)) print('Blade cost: \t\t\t %f\t%f USD \t Difference: %f %%' % (prob_ref['total_blade_cost'], prob['total_blade_cost'], (prob['total_blade_cost'] - prob_ref['total_blade_cost']) / prob_ref['total_blade_cost'] * 100.)) print('Blade mass: \t\t\t %f\t%f kg \t Difference: %f %%' % (prob_ref['total_blade_mass'], prob['total_blade_mass'], (prob['total_blade_mass'] - prob_ref['total_blade_mass']) / prob_ref['total_blade_mass'] * 100.)) print('Tower cost: \t\t\t %f\t%f USD \t Difference: %f %%' % (prob_ref['tower_cost'], prob['tower_cost'], (prob['tower_cost'] - prob_ref['tower_cost']) / prob_ref['tower_cost'] * 100.)) print('Tower mass: \t\t\t %f\t%f kg \t Difference: %f %%' % (prob_ref['tower_mass'], prob['tower_mass'], (prob['tower_mass'] - prob_ref['tower_mass']) / prob_ref['tower_mass'] * 100.)) # ---------------------- # Theta ft, axt = plt.subplots(1, 1, figsize=(5.3, 4)) axt.plot(prob_ref['r'], prob_ref['theta'], label='Initial') axt.plot(prob_ref['r_in'], prob_ref['theta_in'], '.') axt.plot(prob['r'], prob['theta'], label='Optimized') axt.plot(prob['r_in'], prob['theta_in'], '.') axt.legend(fontsize=12) plt.xlabel('Blade Span [m]', fontsize=14, fontweight='bold') plt.ylabel('Twist [deg]', fontsize=14, fontweight='bold') plt.xticks(fontsize=12) plt.yticks(fontsize=12) plt.grid(color=[0.8, 0.8, 0.8], linestyle='--') plt.subplots_adjust(bottom=0.15, left=0.15) fig_name = 'theta.png' ft.savefig(folder_output + fig_name) # Angle of attack and stall angle faoa, axaoa = plt.subplots(1, 1, figsize=(5.3, 4)) axaoa.plot(prob_ref['r'], prob_ref['nostallconstraint.aoa_along_span'], label='Initial aoa') axaoa.plot(prob_ref['r'], prob_ref['nostallconstraint.stall_angle_along_span'], '.', label='Initial stall') axaoa.plot(prob['r'], prob['nostallconstraint.aoa_along_span'], label='Optimized aoa') axaoa.plot(prob['r'], prob['nostallconstraint.stall_angle_along_span'], '.', label='Optimized stall') axaoa.legend(fontsize=12) plt.xlabel('Blade Span [m]', fontsize=14, fontweight='bold') plt.ylabel('Angle [deg]', fontsize=14, fontweight='bold') plt.xticks(fontsize=12) plt.yticks(fontsize=12) plt.grid(color=[0.8, 0.8, 0.8], linestyle='--') plt.subplots_adjust(bottom=0.15, left=0.15) fig_name = 'aoa.png' ft.savefig(folder_output + fig_name) plt.show() return prob, blade
rotor = Init_RotorSE_wRefBlade(rotor, blade, Analysis_Level=Analysis_Level, fst_vt=fst_vt) # rotor['chord_in'] = np.array([3.542, 3.54451799, 2.42342374, 2.44521374, 4.69032208, 6.3306303, 4.41245811, 1.419]) # rotor['theta_in'] = np.array([13.30800018, 13.30800018, 0.92624531, 10.41054813, 11.48955724, -0.60858835, -1.41595352, 4.89747605]) # rotor['sparT_in'] = np.array([0.00047, 0.00059925, 0.07363709, 0.13907431, 0.19551095, 0.03357394, 0.12021584, 0.00047]) # rotor['r_in'] = np.array([0., 0.02565783, 0.23892874, 0.39114299, 0.54335725, 0.6955715, 0.84778575, 1.]) # === run and outputs === tt = time.time() rotor.run_driver() #rotor.check_partials(compact_print=True, step=1e-6, form='central') refBlade.write_ontology(fname_output, rotor['blade_out'], refBlade.wt_ref) print('Run Time = ', time.time() - tt) print('AEP =', rotor['AEP']) print('diameter =', rotor['diameter']) print('ratedConditions.V =', rotor['rated_V']) print('ratedConditions.Omega =', rotor['rated_Omega']) print('ratedConditions.pitch =', rotor['rated_pitch']) print('ratedConditions.T =', rotor['rated_T']) print('ratedConditions.Q =', rotor['rated_Q']) print('mass_one_blade =', rotor['mass_one_blade']) print('mass_all_blades =', rotor['mass_all_blades']) print('I_all_blades =', rotor['I_all_blades']) print('freq =', rotor['freq_pbeam']) print('tip_deflection =', rotor['tip_deflection']) print('root_bending_moment =', rotor['root_bending_moment'])
print('LCoE: \t\t\t %f\t%f USD/MWh \t Difference: %f %%' % (prob_ref['lcoe']*1.e003, prob['lcoe']*1.e003, (prob['lcoe']-prob_ref['lcoe'])/prob_ref['lcoe']*100.)) print('Blade cost: \t\t\t %f\t%f USD \t Difference: %f %%' % (prob_ref['total_blade_cost'], prob['total_blade_cost'], (prob['total_blade_cost']-prob_ref['total_blade_cost'])/prob_ref['total_blade_cost']*100.)) print('Blade mass: \t\t\t %f\t%f kg \t Difference: %f %%' % (prob_ref['total_blade_mass'], prob['total_blade_mass'], (prob['total_blade_mass']-prob_ref['total_blade_mass'])/prob_ref['total_blade_mass']*100.)) print('Tower cost: \t\t\t %f\t%f USD \t Difference: %f %%' % (prob_ref['tower_cost'], prob['tower_cost'], (prob['tower_cost']-prob_ref['tower_cost'])/prob_ref['tower_cost']*100.)) print('Tower mass: \t\t\t %f\t%f kg \t Difference: %f %%' % (prob_ref['tower_mass'], prob['tower_mass'], (prob['tower_mass']-prob_ref['tower_mass'])/prob_ref['tower_mass']*100.)) # ---------------------- else: # If not optimizing, plot current design prob = prob_ref show_plots = True flag_write_out = False if flag_write_out: # --- Save output .yaml --- refBlade.write_ontology(fname_output, prob['blade_out'], refBlade.wt_ref) shutil.copyfile(fname_input, folder_output + os.sep + fname_output) def format_save(fig, fig_name): plt.xticks(fontsize=12) plt.yticks(fontsize=12) plt.grid(color=[0.8,0.8,0.8], linestyle='--') plt.subplots_adjust(bottom = 0.15, left = 0.15) fig.savefig(folder_output + os.sep + fig_name+'.pdf', pad_inches=0.1, bbox_inches='tight') fig.savefig(folder_output + os.sep + fig_name+'.png', pad_inches=0.1, bbox_inches='tight') # Problem initialization var_y = ['chord','theta','rthick','p_le','precurve','presweep'] label_y = ['Chord [m]', 'Twist [deg]', 'Relative Thickness [%]', 'Pitch Axis Chord Location [%]', 'Prebend [m]', 'Sweep [m]'] scaling_factor = [1. , 1. , 100. , 100., 1., 1.]