Exemplo n.º 1
0
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
Exemplo n.º 2
0
    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'])
Exemplo n.º 3
0
        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.]