Esempio n. 1
0
def initialize_problem(Analysis_Level):
    
    # Initialize blade design
    refBlade = ReferenceBlade()
    refBlade.verbose  = True
    refBlade.NINPUT       = 200
    Nsection_Tow          = 19
    refBlade.NPTS         = 200
    refBlade.spar_var     = ['Spar_cap_ss', 'Spar_cap_ps'] # SS, then PS
    refBlade.te_var       = 'TE_reinforcement'
    refBlade.validate     = False
    refBlade.fname_schema = fname_schema
    blade = refBlade.initialize(fname_input)
    
    FASTpref                        = {}
    FASTpref['Analysis_Level']      = Analysis_Level
    # Set FAST Inputs
    if Analysis_Level >= 1:
        # File management
        FASTpref['FAST_ver']            = 'OpenFAST'
        FASTpref['dev_branch']          = True
        FASTpref['FAST_exe']            = '~/local/bin/openfast'
        FASTpref['FAST_directory']      = '../OpenFAST'   # Path to fst directory files
        FASTpref['FAST_InputFile']      = 'IEA-15-240-RWT.fst' # FAST input file (ext=.fst)
        FASTpref['Turbsim_exe']         = '~/local/bin/turbsim'
        FASTpref['FAST_namingOut']      = 'IEA-15-240-RWT'
        FASTpref['FAST_runDirectory']   = 'temp/' + FASTpref['FAST_namingOut']
        
        # Run Settings
        FASTpref['cores']               = 1
        FASTpref['debug_level']         = 2 # verbosity: set to 0 for quiet, 1 & 2 for increasing levels of output

        # DLCs
        FASTpref['DLC_gust']            = None      # Max deflection
        # FASTpref['DLC_gust']            = RotorSE_DLC_1_4_Rated       # Max deflection    ### Not in place yet
        FASTpref['DLC_extrm']           = None      # Max strain
        # FASTpref['DLC_extrm']           = RotorSE_DLC_7_1_Steady      # Max strain        ### Not in place yet
        FASTpref['DLC_turbulent']       = None
        # FASTpref['DLC_turbulent']       = RotorSE_DLC_1_1_Turb      # Alternate turbulent case, replacing rated and extreme DLCs for calculating max deflection and strain
        FASTpref['DLC_powercurve']      = None      # AEP
        # FASTpref['DLC_powercurve']      = None      # AEP

        # Initialize, read initial FAST files to avoid doing it iteratively
        fast = InputReader_OpenFAST(FAST_ver=FASTpref['FAST_ver'], dev_branch=FASTpref['dev_branch'])
        fast.FAST_InputFile = FASTpref['FAST_InputFile']
        fast.FAST_directory = FASTpref['FAST_directory']
        fast.execute()
        fst_vt = fast.fst_vt
    else:
        fst_vt = {}

    prob = om.Problem()
    prob.model=MonopileTurbine(RefBlade=blade, Nsection_Tow=Nsection_Tow, VerbosityCosts=False, FASTpref=FASTpref)
    prob.model.nonlinear_solver = om.NonlinearRunOnce()
    prob.model.linear_solver    = om.DirectSolver()

    return prob, blade, fst_vt
Esempio n. 2
0
    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']['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']
        if blade['analysis_level'] < 3:
            refBlade.spar_var = blade['precomp']['spar_var']
            refBlade.te_var = blade['precomp']['te_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']
Esempio n. 3
0
        'hub_height']  # (Float, m): hub height
    rotor['turbine_class'] = blade['config']['turbine_class'].upper(
    )  #TURBINE_CLASS['I']  # (Enum): IEC turbine class

    return rotor


if __name__ == "__main__":

    # Turbine Ontology input
    fname_input = "turbine_inputs/nrel5mw_mod_update.yaml"

    # Initialize blade design
    refBlade = ReferenceBlade()
    refBlade.verbose = True
    refBlade.NINPUT = NINPUT
    refBlade.NPITS = 50
    refBlade.validate = False
    refBlade.fname_schema = "turbine_inputs/IEAontology_schema.yaml"

    refBlade.spar_var = ['Spar_Cap_SS', 'Spar_Cap_PS']
    refBlade.te_var = 'TE_reinforcement'
    blade = refBlade.initialize(fname_input)

    # setup
    rotor = Problem()
    rotor.model = RotorGeometry(RefBlade=blade, topLevelFlag=True)
    rotor.setup()
    rotor = Init_RotorGeometry_wRefBlade(rotor, blade)
    rotor.run_driver()
Esempio n. 4
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
Esempio n. 5
0
    def testAssembly(self):
        # Global inputs and outputs
        fname_schema = mydir + os.sep + 'IEAontology_schema.yaml'
        fname_input = mydir + os.sep + 'IEA-15-240-RWT.yaml'

        # Initialize blade design
        refBlade = ReferenceBlade()
        refBlade.verbose = True
        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.validate = False
        refBlade.fname_schema = fname_schema
        blade = refBlade.initialize(fname_input)
        Analysis_Level = 0

        FASTpref = {}
        FASTpref['Analysis_Level'] = Analysis_Level
        fst_vt = {}

        prob = om.Problem()
        prob.model = MonopileTurbine(RefBlade=blade,
                                     Nsection_Tow=Nsection_Tow,
                                     VerbosityCosts=False,
                                     FASTpref=FASTpref)
        prob.model.nonlinear_solver = om.NonlinearRunOnce()
        prob.model.linear_solver = om.DirectSolver()
        prob.setup()

        prob = Init_RotorSE_wRefBlade(prob,
                                      blade,
                                      Analysis_Level=Analysis_Level,
                                      fst_vt=fst_vt)

        # Environmental parameters for the tower
        prob['significant_wave_height'] = 4.52
        prob['significant_wave_period'] = 9.45
        prob['water_depth'] = 30.
        prob['wind_reference_height'] = prob['hub_height'] = 150.
        prob['shearExp'] = 0.11
        prob['rho'] = 1.225
        prob['mu'] = 1.7934e-5
        prob['water_density'] = 1025.0
        prob['water_viscosity'] = 1.3351e-3
        prob['wind_beta'] = prob['wave_beta'] = 0.0

        # Steel properties for the tower
        prob['material_density'] = 7850.0
        prob['E'] = 210e9
        prob['G'] = 79.3e9
        prob['yield_stress'] = 345e6
        prob['soil_G'] = 140e6
        prob['soil_nu'] = 0.4

        # Design constraints
        prob['max_taper_ratio'] = 0.4
        prob['min_diameter_thickness_ratio'] = 120.0

        # Safety factors
        prob['gamma_fatigue'] = 1.755  # (Float): safety factor for fatigue
        prob['gamma_f'] = 1.35  # (Float): safety factor for loads/stresses
        prob['gamma_m'] = 1.3  # (Float): safety factor for materials
        prob[
            'gamma_freq'] = 1.1  # (Float): safety factor for resonant frequencies
        prob['gamma_n'] = 1.0
        prob['gamma_b'] = 1.1

        # Tower
        prob['tower_buckling_length'] = 30.0
        prob['tower_outfitting_factor'] = 1.07
        prob['foundation_height'] = -30.
        prob['suctionpile_depth'] = 45.
        prob['tower_section_height'] = np.array([
            5., 5., 5., 5., 5., 5., 5., 5., 5., 13., 13., 13., 13., 13., 13.,
            13., 13., 13., 12.58244309
        ])
        prob['tower_outer_diameter'] = np.array([
            10., 10., 10., 10., 10., 10., 10., 10., 10., 10., 10., 9.92647687,
            9.44319282, 8.83283769, 8.15148167, 7.38976138, 6.90908962,
            6.74803581, 6.57231775, 6.5
        ])
        prob['tower_wall_thickness'] = np.array([
            0.05534138, 0.05344902, 0.05150928, 0.04952705, 0.04751736,
            0.04551709, 0.0435267, 0.04224176, 0.04105759, 0.0394965,
            0.03645589, 0.03377851, 0.03219233, 0.03070819, 0.02910109,
            0.02721289, 0.02400931, 0.0208264, 0.02399756
        ])
        prob['tower_buckling_length'] = 15.0
        prob['transition_piece_mass'] = 100e3
        prob['transition_piece_height'] = 15.0

        prob['DC'] = 80.0
        prob['shear'] = True
        prob['geom'] = True
        prob['tower_force_discretization'] = 5.0
        prob['nM'] = 2
        prob['Mmethod'] = 1
        prob['lump'] = 0
        prob['tol'] = 1e-9
        prob['shift'] = 0.0

        # Offshore BOS
        prob['wtiv'] = 'example_wtiv'
        prob['feeder'] = 'future_feeder'
        prob['num_feeders'] = 1
        prob['oss_install_vessel'] = 'example_heavy_lift_vessel'
        prob['site_distance'] = 40.0
        prob['site_distance_to_landfall'] = 40.0
        prob['site_distance_to_interconnection'] = 40.0
        prob['plant_turbine_spacing'] = 7
        prob['plant_row_spacing'] = 7
        prob['plant_substation_distance'] = 1
        prob['tower_deck_space'] = 0.
        prob['nacelle_deck_space'] = 0.
        prob['blade_deck_space'] = 0.
        prob['port_cost_per_month'] = 2e6
        prob['monopile_deck_space'] = 0.
        prob['transition_piece_deck_space'] = 0.
        prob['commissioning_pct'] = 0.01
        prob['decommissioning_pct'] = 0.15
        prob['project_lifetime'] = prob['lifetime'] = 20.0
        prob['number_of_turbines'] = 40
        prob['annual_opex'] = 43.56  # $/kW/yr
        #prob['bos_costs']                      = 1234.5 # $/kW

        prob['tower_add_gravity'] = True

        # For turbine costs
        prob['offshore'] = True
        prob['crane'] = False
        prob['bearing_number'] = 2
        prob['crane_cost'] = 0.0
        prob['labor_cost_rate'] = 3.0
        prob['material_cost_rate'] = 2.0
        prob['painting_cost_rate'] = 28.8

        # Drivetrain
        prob['tilt'] = 6.0
        prob['overhang'] = 11.075
        prob['hub_cm'] = np.array([-10.685, 0.0, 5.471])
        prob['nac_cm'] = np.array([-5.718, 0.0, 4.048])
        prob['hub_I'] = np.array(
            [1382171.187, 2169261.099, 2160636.794, 0.0, 0.0, 0.0])
        prob['nac_I'] = np.array(
            [13442265.552, 21116729.439, 18382414.385, 0.0, 0.0, 0.0])
        prob['hub_mass'] = 190e3
        prob['nac_mass'] = 797.275e3 - 190e3
        prob['hss_mass'] = 0.0
        prob['lss_mass'] = 19.504e3
        prob['cover_mass'] = 0.0
        prob['pitch_system_mass'] = 50e3
        prob['platforms_mass'] = 0.0
        prob['spinner_mass'] = 0.0
        prob['transformer_mass'] = 0.0
        prob['vs_electronics_mass'] = 0.0
        prob['yaw_mass'] = 100e3
        prob['gearbox_mass'] = 0.0
        prob['generator_mass'] = 226.7e3 + 145.25e3
        prob['bedplate_mass'] = 39.434e3
        prob['main_bearing_mass'] = 4.699e3

        prob.run_model()
        # Make sure we get here
        self.assertTrue(True)