示例#1
0
def configure_turbine_with_jacket(assembly,
                                  with_new_nacelle=False,
                                  flexible_blade=False,
                                  with_3pt_drive=False):
    """a stand-alone configure method to allow for flatter assemblies

    Parameters
    ----------
    assembly : Assembly
        an openmdao assembly to be configured
    with_new_nacelle : bool
        False uses the default implementation, True uses an experimental implementation designed
        to smooth out discontinities making in amenable for gradient-based optimization
    flexible_blade : bool
        if True, internally solves the coupled aero/structural deflection using fixed point iteration.
        Note that the coupling is currently only in the flapwise deflection, and is primarily
        only important for highly flexible blades.  If False, the aero loads are passed
        to the structure but there is no further iteration.
    """

    # --- general turbine configuration inputs---
    assembly.add(
        'rho',
        Float(1.225,
              iotype='in',
              units='kg/m**3',
              desc='density of air',
              deriv_ignore=True))
    assembly.add(
        'mu',
        Float(1.81206e-5,
              iotype='in',
              units='kg/m/s',
              desc='dynamic viscosity of air',
              deriv_ignore=True))
    assembly.add(
        'shear_exponent',
        Float(0.2, iotype='in', desc='shear exponent', deriv_ignore=True))
    assembly.add('hub_height',
                 Float(90.0, iotype='in', units='m', desc='hub height'))
    assembly.add(
        'turbine_class',
        Enum('I', ('I', 'II', 'III'), iotype='in', desc='IEC turbine class'))
    assembly.add(
        'turbulence_class',
        Enum('B', ('A', 'B', 'C'),
             iotype='in',
             desc='IEC turbulence class class'))
    assembly.add(
        'g',
        Float(9.81,
              iotype='in',
              units='m/s**2',
              desc='acceleration of gravity',
              deriv_ignore=True))
    assembly.add(
        'cdf_reference_height_wind_speed',
        Float(
            90.0,
            iotype='in',
            desc=
            'reference hub height for IEC wind speed (used in CDF calculation)'
        ))
    assembly.add('downwind',
                 Bool(False, iotype='in', desc='flag if rotor is downwind'))
    assembly.add('tower_dt',
                 Float(iotype='in', units='m',
                       desc='tower top diameter'))  # update for jacket
    assembly.add('generator_speed',
                 Float(iotype='in', units='rpm', desc='generator speed'))
    assembly.add(
        'machine_rating',
        Float(5000.0, units='kW', iotype='in', desc='machine rated power'))
    assembly.add(
        'rna_weightM',
        Bool(True,
             iotype='in',
             desc='flag to consider or not the RNA weight effect on Moment'))

    assembly.add('rotor', RotorSE())
    if with_new_nacelle:
        assembly.add('hub', HubSE())
        if with_3pt_drive:
            assembly.add('nacelle', Drive3pt())
        else:
            assembly.add('nacelle', Drive4pt())
    else:
        assembly.add('nacelle', DriveWPACT())
        assembly.add('hub', HubWPACT())
    assembly.add('rna', RNAMass())
    assembly.add('rotorloads1', RotorLoads())
    assembly.add('rotorloads2', RotorLoads())
    assembly.add('jacket', JacketSE())
    assembly.add('maxdeflection', MaxTipDeflection())

    if flexible_blade:
        assembly.add('fpi', FixedPointIterator())

        assembly.fpi.workflow.add(['rotor'])
        assembly.fpi.add_parameter('rotor.delta_precurve_sub',
                                   low=-1.e99,
                                   high=1.e99)
        assembly.fpi.add_parameter('rotor.delta_bladeLength',
                                   low=-1.e99,
                                   high=1.e99)
        assembly.fpi.add_constraint(
            'rotor.delta_precurve_sub = rotor.delta_precurve_sub_out')
        assembly.fpi.add_constraint(
            'rotor.delta_bladeLength = rotor.delta_bladeLength_out')
        assembly.fpi.max_iteration = 20
        assembly.fpi.tolerance = 1e-8

        assembly.driver.workflow.add(['fpi'])

    else:
        assembly.driver.workflow.add(['rotor'])

    assembly.driver.workflow.add([
        'hub', 'nacelle', 'jacket', 'maxdeflection', 'rna', 'rotorloads1',
        'rotorloads2'
    ])

    # TODO: rotor drivetrain design should be connected to nacelle drivetrain design

    # connections to rotor
    assembly.connect('machine_rating', 'rotor.control.ratedPower')
    assembly.connect('rho', 'rotor.rho')
    assembly.connect('mu', 'rotor.mu')
    assembly.connect('shear_exponent', 'rotor.shearExp')
    assembly.connect('hub_height', 'rotor.hubHt')
    assembly.connect('turbine_class', 'rotor.turbine_class')
    assembly.connect('turbulence_class', 'rotor.turbulence_class')
    assembly.connect('g', 'rotor.g')
    assembly.connect('cdf_reference_height_wind_speed',
                     'rotor.cdf_reference_height_wind_speed')

    # connections to hub
    assembly.connect('rotor.mass_one_blade', 'hub.blade_mass')
    assembly.connect('rotor.root_bending_moment', 'hub.rotor_bending_moment')
    assembly.connect('rotor.diameter', 'hub.rotor_diameter')
    assembly.connect('rotor.hub_diameter', 'hub.blade_root_diameter')
    assembly.connect('rotor.nBlades', 'hub.blade_number')
    if with_new_nacelle:
        assembly.connect('nacelle.MB1_location', 'hub.MB1_location')
        assembly.connect('rotor.tilt', 'hub.gamma')
        assembly.connect('nacelle.L_rb', 'hub.L_rb')

    # connections to nacelle #TODO: fatigue option variables
    assembly.connect('rotor.diameter', 'nacelle.rotor_diameter')
    if not with_new_nacelle:
        assembly.connect(
            'rotor.mass_all_blades + hub.hub_system_mass', 'nacelle.rotor_mass'
        )  #DODO: circular dependency if using DriveSE (nacelle csm --> hub, hub mass --> nacelle)
    if with_new_nacelle:
        assembly.connect('rotor.nBlades', 'nacelle.blade_number')
        assembly.connect('rotor.tilt', 'nacelle.shaft_angle')
        assembly.connect('333.3 * machine_rating / 1000.0',
                         'nacelle.shrink_disc_mass')
    assembly.connect('1.5 * rotor.ratedConditions.Q', 'nacelle.rotor_torque')
    assembly.connect('rotor.ratedConditions.T', 'nacelle.rotor_thrust')
    assembly.connect('rotor.ratedConditions.Omega', 'nacelle.rotor_speed')
    assembly.connect('machine_rating', 'nacelle.machine_rating')
    assembly.connect('rotor.root_bending_moment',
                     'nacelle.rotor_bending_moment')
    assembly.connect('generator_speed/rotor.ratedConditions.Omega',
                     'nacelle.gear_ratio')
    '''if  with_new_nacelle:
        assembly.connect('rotor.g', 'nacelle.g')''' # Only drive smooth taking g from rotor; TODO: update when drive_smooth is updated
    assembly.connect(
        'tower_dt', 'nacelle.tower_top_diameter'
    )  # OpenMDAO circular dependency issue # update for jacket input

    # connections to rna
    assembly.connect('rotor.mass_all_blades', 'rna.blades_mass')
    assembly.connect('rotor.I_all_blades', 'rna.blades_I')
    assembly.connect('hub.hub_system_mass', 'rna.hub_mass')
    assembly.connect('hub.hub_system_cm', 'rna.hub_cm')
    assembly.connect('hub.hub_system_I', 'rna.hub_I')
    assembly.connect('nacelle.nacelle_mass', 'rna.nac_mass')
    assembly.connect('nacelle.nacelle_cm', 'rna.nac_cm')
    assembly.connect('nacelle.nacelle_I', 'rna.nac_I')

    # connections to rotorloads1
    assembly.connect('downwind', 'rotorloads1.downwind')
    assembly.connect('rna_weightM', 'rotorloads1.rna_weightM')
    assembly.connect('1.8 * rotor.ratedConditions.T', 'rotorloads1.F[0]')
    assembly.connect('rotor.ratedConditions.Q', 'rotorloads1.M[0]')
    assembly.connect('hub.hub_system_cm', 'rotorloads1.r_hub')
    assembly.connect('rna.rna_cm', 'rotorloads1.rna_cm')
    assembly.connect('rotor.tilt', 'rotorloads1.tilt')
    assembly.connect('g', 'rotorloads1.g')
    assembly.connect('rna.rna_mass', 'rotorloads1.m_RNA')

    # connections to rotorloads2
    assembly.connect('downwind', 'rotorloads2.downwind')
    assembly.connect('rna_weightM', 'rotorloads2.rna_weightM')
    assembly.connect('rotor.T_extreme', 'rotorloads2.F[0]')
    assembly.connect('rotor.Q_extreme', 'rotorloads2.M[0]')
    assembly.connect('hub.hub_system_cm', 'rotorloads2.r_hub')
    assembly.connect('rna.rna_cm', 'rotorloads2.rna_cm')
    assembly.connect('rotor.tilt', 'rotorloads2.tilt')
    assembly.connect('g', 'rotorloads2.g')
    assembly.connect('rna.rna_mass', 'rotorloads2.m_RNA')

    # connections to jacket
    assembly.connect('rho', 'jacket.Windinputs.rho')  # jacket input
    assembly.connect('mu', 'jacket.Windinputs.mu')  # jacket input
    assembly.connect('-g', 'jacket.FrameAuxIns.gvector[2]')  # jacket input
    assembly.connect('hub_height', 'jacket.Windinputs.HH')  # jacket input
    assembly.connect('tower_dt', 'jacket.Twrinputs.Dt')  # jacket input
    assembly.connect('rotor.yaw', 'jacket.RNAinputs.yawangle')  # jacket input
    #assembly.connect('hub_height - nacelle.nacelle_cm[2]', 'jacket.Twrinputs.Htwr') # jacket input; TODO: probably irrelevant for this purpose, tower length is now determined in jacket
    assembly.connect('rna.rna_mass', 'jacket.RNAinputs.mass')  # jacket input
    assembly.connect('rna.rna_cm', 'jacket.RNAinputs.CMoff')  # jacket input
    assembly.connect('rna.rna_I_TT', 'jacket.RNAinputs.I')  # jacket input
    # Rated rotor loads (Option 1)
    assembly.connect('rotor.ratedConditions.V',
                     'jacket.Windinputs.U50HH')  # jacket input
    assembly.connect('rotorloads1.top_F', 'jacket.RNA_F[0:3]')  # jacket input
    assembly.connect('rotorloads1.top_M', 'jacket.RNA_F[3:6]')  # jacket input
    # Survival rotor loads (Option 2)
    #assembly.connect('rotor.V_extreme', 'tower.Windinputs.U50HH') # jacket input
    #assembly.connect('rotorloads2.top_F', 'jacket.RNA_F') # jacket input
    #assembly.connect('rotorloads2.top_M', 'jacket.RNA_M') # jacket input

    # connections to maxdeflection
    assembly.connect('rotor.Rtip', 'maxdeflection.Rtip')
    assembly.connect('rotor.precurveTip', 'maxdeflection.precurveTip')
    assembly.connect('rotor.presweepTip', 'maxdeflection.presweepTip')
    assembly.connect('rotor.precone', 'maxdeflection.precone')
    assembly.connect('rotor.tilt', 'maxdeflection.tilt')
    assembly.connect('hub.hub_system_cm', 'maxdeflection.hub_tt')
    assembly.connect(
        'jacket.Twrouts.nodes[2,:]', 'maxdeflection.tower_z'
    )  # jacket input, had to make array dimensions explicit on instantiation for this connect to work ---THIS is the z at CMzoff, not necessarily the top flange
    assembly.connect('jacket.Twrouts', 'maxdeflection.Twrouts'
                     )  # TODO: jacket input - doesnt recognize logobj
    assembly.connect('jacket.Twrouts.Htwr',
                     'maxdeflection.towerHt')  # jacket input
示例#2
0
from fusedwind.interface import implement_base
from commonse.UtilizationSupplement import fatigue, hoopStressEurocode, shellBucklingEurocode, \
    bucklingGL, vonMisesStressUtilization

import matplotlib.pyplot as plt

import frame3dd

################################################################################
### 1. Aerodynamic and structural performance using RotorSE

BladeLength = 34
HubHeight = 65

ReferenceBladeLength = 68;
rotor = RotorSE()
# -------------------

# === blade grid ===
# (Array): initial aerodynamic grid on unit radius
rotor.initial_aero_grid = np.array([0.02222276, 0.06666667, 0.11111057, \
	0.16666667, 0.23333333, 0.3, 0.36666667, 0.43333333, 0.5, 0.56666667, \
	0.63333333, 0.7, 0.76666667, 0.83333333, 0.88888943, 0.93333333, \
    0.97777724]) 

 # (Array): initial structural grid on unit radius
rotor.initial_str_grid = np.array([0.0, 0.00492790457512, 0.00652942887106, 
	0.00813095316699, 0.00983257273154, 0.0114340970275, 0.0130356213234, 
	0.02222276, 0.024446481932, 0.026048006228, 0.06666667, 0.089508406455,
    0.11111057, 0.146462614229, 0.16666667, 0.195309105255, 0.23333333, 
    0.276686558545, 0.3, 0.333640766319,0.36666667, 0.400404310407, 0.43333333, 
    def __init__(self, nSection):
        super(FloatingTurbine, self).__init__()

        self.add('hub_height', IndepVarComp('hub_height', 0.0), promotes=['*'])

        # TODO:
        #Weibull/Rayleigh CDF

        # Rotor
        self.add(
            'rotor',
            RotorSE(),
            promotes=[
                'idx_cylinder_aero', 'idx_cylinder_str', 'hubFraction',
                'nBlades', 'turbine_class', 'sparT', 'teT', 'r_max_chord',
                'chord_sub', 'theta_sub', 'precurve_sub', 'bladeLength',
                'precone', 'tilt', 'yaw', 'turbulence_class', 'gust_stddev',
                'VfactorPC', 'shape_parameter', 'Rtip', 'precurveTip',
                'presweepTip', 'control:Vin', 'control:Vout', 'machine_rating',
                'control:minOmega', 'control:maxOmega', 'control:tsr',
                'control:pitch', 'pitch_extreme', 'azimuth_extreme',
                'drivetrainType', 'rstar_damage', 'Mxb_damage', 'Myb_damage',
                'strain_ult_spar', 'strain_ult_te', 'm_damage', 'nSector',
                'tiploss', 'hubloss', 'wakerotation', 'usecd',
                'AEP_loss_factor', 'tip_deflection',
                'dynamic_amplication_tip_deflection'
            ])

        # RNA
        self.add('rna', RNA(1))

        # Tower and substructure
        myfloat = FloatingSE(nSection)
        self.add(
            'sm',
            myfloat,
            promotes=[
                'radius_to_auxiliary_column', 'fairlead',
                'fairlead_offset_from_shell', 'base_freeboard',
                'base_section_height', 'base_outer_diameter',
                'base_wall_thickness', 'auxiliary_freeboard',
                'auxiliary_section_height', 'auxiliary_outer_diameter',
                'auxiliary_wall_thickness', 'scope_ratio', 'anchor_radius',
                'mooring_diameter', 'number_of_mooring_lines', 'mooring_type',
                'anchor_type', 'drag_embedment_extra_length',
                'mooring_max_offset', 'mooring_max_heel', 'mooring_cost_rate',
                'permanent_ballast_density', 'base_stiffener_web_height',
                'base_stiffener_web_thickness', 'base_stiffener_flange_width',
                'base_stiffener_flange_thickness', 'base_stiffener_spacing',
                'base_bulkhead_nodes', 'base_permanent_ballast_height',
                'auxiliary_stiffener_web_height',
                'auxiliary_stiffener_web_thickness',
                'auxiliary_stiffener_flange_width',
                'auxiliary_stiffener_flange_thickness',
                'auxiliary_stiffener_spacing', 'auxiliary_bulkhead_nodes',
                'auxiliary_permanent_ballast_height', 'bulkhead_mass_factor',
                'ring_mass_factor', 'shell_mass_factor', 'column_mass_factor',
                'outfitting_mass_fraction', 'ballast_cost_rate',
                'tapered_col_cost_rate', 'outfitting_cost_rate',
                'number_of_auxiliary_columns', 'pontoon_outer_diameter',
                'pontoon_wall_thickness', 'cross_attachment_pontoons',
                'lower_attachment_pontoons', 'upper_attachment_pontoons',
                'lower_ring_pontoons', 'upper_ring_pontoons',
                'outer_cross_pontoons', 'pontoon_cost_rate',
                'connection_ratio_max', 'base_pontoon_attach_upper',
                'base_pontoon_attach_lower', 'tower_section_height',
                'tower_outer_diameter', 'tower_wall_thickness',
                'tower_outfitting_factor', 'tower_buckling_length',
                'tower_mass', 'loading', 'min_diameter_thickness_ratio',
                'min_taper_ratio'
            ])

        # Turbine constraints
        self.add('tcons',
                 TurbineConstraints(myfloat.nFull),
                 promotes=[
                     'blade_number', 'Rtip', 'precurveTip', 'presweepTip',
                     'precone', 'tilt', 'tip_deflection'
                 ])

        # Turbine costs
        self.add('tcost', Turbine_CostsSE_2015(), promotes=['*'])

        # Balance of station
        self.add('wobos', WindOBOS(), promotes=['tax_rate'])

        # LCOE Calculation
        self.add('lcoe', PlantFinance(), promotes=['*'])

        # Define all input variables from all models
        self.add('offshore',
                 IndepVarComp('offshore', True, pass_by_obj=True),
                 promotes=['*'])
        self.add('crane',
                 IndepVarComp('crane', False, pass_by_obj=True),
                 promotes=['*'])

        # Tower
        #self.add('stress_standard_value',          IndepVarComp('stress_standard_value', 0.0), promotes=['*'])
        #self.add('fatigue_parameters',             IndepVarComp('fatigue_parameters', np.zeros(nDEL)), promotes=['*'])
        #self.add('fatigue_z',                      IndepVarComp('fatigue_z', np.zeros(nDEL)), promotes=['*'])
        #self.add('frame3dd_matrix_method',         IndepVarComp('frame3dd_matrix_method', 0, pass_by_obj=True), promotes=['*'])
        #self.add('compute_stiffnes',               IndepVarComp('compute_stiffnes', False, pass_by_obj=True), promotes=['*'])
        self.add('project_lifetime',
                 IndepVarComp('project_lifetime', 0.0),
                 promotes=['*'])
        #self.add('lumped_mass_matrix',             IndepVarComp('lumped_mass_matrix', 0, pass_by_obj=True), promotes=['*'])
        #self.add('slope_SN',                       IndepVarComp('slope_SN', 0, pass_by_obj=True), promotes=['*'])
        self.add('number_of_modes',
                 IndepVarComp('number_of_modes', 0, pass_by_obj=True),
                 promotes=['*'])
        #self.add('compute_shear',                  IndepVarComp('compute_shear', True, pass_by_obj=True), promotes=['*'])
        #self.add('shift_value',                    IndepVarComp('shift_value', 0.0), promotes=['*'])
        #self.add('frame3dd_convergence_tolerance', IndepVarComp('frame3dd_convergence_tolerance', 1e-9), promotes=['*'])

        # TODO: Multiple load cases
        # Environment
        self.add('air_density',
                 IndepVarComp('air_density', 0.0),
                 promotes=['*'])
        self.add('air_viscosity',
                 IndepVarComp('air_viscosity', 0.0),
                 promotes=['*'])
        self.add('wind_reference_speed',
                 IndepVarComp('wind_reference_speed', 0.0),
                 promotes=['*'])
        self.add('wind_reference_height',
                 IndepVarComp('wind_reference_height', 0.0),
                 promotes=['*'])
        self.add('shearExp', IndepVarComp('shearExp', 0.0), promotes=['*'])
        self.add('wind_bottom_height',
                 IndepVarComp('wind_bottom_height', 0.0),
                 promotes=['*'])
        self.add('wind_beta', IndepVarComp('wind_beta', 0.0), promotes=['*'])
        self.add('cd_usr', IndepVarComp('cd_usr', np.inf), promotes=['*'])

        # Environment
        self.add('water_depth',
                 IndepVarComp('water_depth', 0.0),
                 promotes=['*'])
        self.add('water_density',
                 IndepVarComp('water_density', 0.0),
                 promotes=['*'])
        self.add('water_viscosity',
                 IndepVarComp('water_viscosity', 0.0),
                 promotes=['*'])
        self.add('wave_height',
                 IndepVarComp('wave_height', 0.0),
                 promotes=['*'])
        self.add('wave_period',
                 IndepVarComp('wave_period', 0.0),
                 promotes=['*'])
        self.add('mean_current_speed',
                 IndepVarComp('mean_current_speed', 0.0),
                 promotes=['*'])
        #self.add('wave_beta',                  IndepVarComp('wave_beta', 0.0), promotes=['*'])
        #self.add('wave_velocity_z0',           IndepVarComp('wave_velocity_z0', 0.0), promotes=['*'])
        #self.add('wave_acceleration_z0',       IndepVarComp('wave_acceleration_z0', 0.0), promotes=['*'])

        # Design standards
        self.add('safety_factor_frequency',
                 IndepVarComp('safety_factor_frequency', 0.0),
                 promotes=['*'])
        self.add('safety_factor_stress',
                 IndepVarComp('safety_factor_stress', 0.0),
                 promotes=['*'])
        self.add('safety_factor_materials',
                 IndepVarComp('safety_factor_materials', 0.0),
                 promotes=['*'])
        self.add('safety_factor_buckling',
                 IndepVarComp('safety_factor_buckling', 0.0),
                 promotes=['*'])
        self.add('safety_factor_fatigue',
                 IndepVarComp('safety_factor_fatigue', 0.0),
                 promotes=['*'])
        self.add('safety_factor_consequence',
                 IndepVarComp('safety_factor_consequence', 0.0),
                 promotes=['*'])

        # RNA
        self.add('dummy_mass', IndepVarComp('dummy_mass', 0.0), promotes=['*'])
        self.add('hub_mass', IndepVarComp('hub_mass', 0.0), promotes=['*'])
        self.add('nac_mass', IndepVarComp('nac_mass', 0.0), promotes=['*'])
        self.add('hub_cm',
                 IndepVarComp('hub_cm', np.zeros((3, ))),
                 promotes=['*'])
        self.add('nac_cm',
                 IndepVarComp('nac_cm', np.zeros((3, ))),
                 promotes=['*'])
        self.add('hub_I', IndepVarComp('hub_I', np.zeros(6)), promotes=['*'])
        self.add('nac_I', IndepVarComp('nac_I', np.zeros(6)), promotes=['*'])
        self.add('downwind',
                 IndepVarComp('downwind', False, pass_by_obj=True),
                 promotes=['*'])
        self.add('rna_weightM',
                 IndepVarComp('rna_weightM', True, pass_by_obj=True),
                 promotes=['*'])

        # Column
        self.add('morison_mass_coefficient',
                 IndepVarComp('morison_mass_coefficient', 0.0),
                 promotes=['*'])
        self.add('material_density',
                 IndepVarComp('material_density', 0.0),
                 promotes=['*'])
        self.add('E', IndepVarComp('E', 0.0), promotes=['*'])
        self.add('nu', IndepVarComp('nu', 0.0), promotes=['*'])
        self.add('yield_stress',
                 IndepVarComp('yield_stress', 0.0),
                 promotes=['*'])

        # Pontoons
        self.add('G', IndepVarComp('G', 0.0), promotes=['*'])

        # Offshore BOS
        # Turbine / Plant parameters, ,
        self.add('nacelleL', IndepVarComp('nacelleL', 0.0), promotes=['*'])
        self.add('nacelleW', IndepVarComp('nacelleW', 0.0), promotes=['*'])
        self.add('distShore', IndepVarComp('distShore', 0.0),
                 promotes=['*'])  #90.0
        self.add('distPort', IndepVarComp('distPort', 0.0),
                 promotes=['*'])  #90.0
        self.add('distPtoA', IndepVarComp('distPtoA', 0.0),
                 promotes=['*'])  #90.0
        self.add('distAtoS', IndepVarComp('distAtoS', 0.0),
                 promotes=['*'])  #90.0
        self.add('substructure',
                 IndepVarComp('substructure',
                              'SEMISUBMERSIBLE',
                              pass_by_obj=True),
                 promotes=['*'])
        self.add('anchor',
                 IndepVarComp('anchor', 'DRAGEMBEDMENT', pass_by_obj=True),
                 promotes=['*'])
        self.add('turbInstallMethod',
                 IndepVarComp('turbInstallMethod',
                              'INDIVIDUAL',
                              pass_by_obj=True),
                 promotes=['*'])
        self.add('towerInstallMethod',
                 IndepVarComp('towerInstallMethod',
                              'ONEPIECE',
                              pass_by_obj=True),
                 promotes=['*'])
        self.add('installStrategy',
                 IndepVarComp('installStrategy',
                              'PRIMARYVESSEL',
                              pass_by_obj=True),
                 promotes=['*'])
        self.add('cableOptimizer',
                 IndepVarComp('cableOptimizer', False, pass_by_obj=True),
                 promotes=['*'])
        self.add('buryDepth', IndepVarComp('buryDepth', 0.0),
                 promotes=['*'])  #2.0
        self.add('arrayY', IndepVarComp('arrayY', 0.0), promotes=['*'])  #9.0
        self.add('arrayX', IndepVarComp('arrayX', 0.0), promotes=['*'])  #9.0
        self.add('substructCont',
                 IndepVarComp('substructCont', 0.0),
                 promotes=['*'])  #0.30
        self.add('turbCont', IndepVarComp('turbCont', 0.0),
                 promotes=['*'])  #0.30
        self.add('elecCont', IndepVarComp('elecCont', 0.0),
                 promotes=['*'])  #0.30
        self.add('interConVolt',
                 IndepVarComp('interConVolt', 0.0),
                 promotes=['*'])  #345.0
        self.add('distInterCon',
                 IndepVarComp('distInterCon', 0.0),
                 promotes=['*'])  #3.0
        self.add('scrapVal', IndepVarComp('scrapVal', 0.0),
                 promotes=['*'])  #0.0
        #General', ,
        self.add('inspectClear',
                 IndepVarComp('inspectClear', 0.0),
                 promotes=['*'])  #2.0
        self.add('plantComm', IndepVarComp('plantComm', 0.0),
                 promotes=['*'])  #0.01
        self.add('procurement_contingency',
                 IndepVarComp('procurement_contingency', 0.0),
                 promotes=['*'])  #0.05
        self.add('install_contingency',
                 IndepVarComp('install_contingency', 0.0),
                 promotes=['*'])  #0.30
        self.add('construction_insurance',
                 IndepVarComp('construction_insurance', 0.0),
                 promotes=['*'])  #0.01
        self.add('capital_cost_year_0',
                 IndepVarComp('capital_cost_year_0', 0.0),
                 promotes=['*'])  #0.20
        self.add('capital_cost_year_1',
                 IndepVarComp('capital_cost_year_1', 0.0),
                 promotes=['*'])  #0.60
        self.add('capital_cost_year_2',
                 IndepVarComp('capital_cost_year_2', 0.0),
                 promotes=['*'])  #0.10
        self.add('capital_cost_year_3',
                 IndepVarComp('capital_cost_year_3', 0.0),
                 promotes=['*'])  #0.10
        self.add('capital_cost_year_4',
                 IndepVarComp('capital_cost_year_4', 0.0),
                 promotes=['*'])  #0.0
        self.add('capital_cost_year_5',
                 IndepVarComp('capital_cost_year_5', 0.0),
                 promotes=['*'])  #0.0
        self.add('tax_rate', IndepVarComp('tax_rate', 0.0),
                 promotes=['*'])  #0.40
        self.add('interest_during_construction',
                 IndepVarComp('interest_during_construction', 0.0),
                 promotes=['*'])  #0.08
        #Substructure & Foundation', ,
        self.add('mpileCR', IndepVarComp('mpileCR', 0.0),
                 promotes=['*'])  #2250.0
        self.add('mtransCR', IndepVarComp('mtransCR', 0.0),
                 promotes=['*'])  #3230.0
        self.add('mpileD', IndepVarComp('mpileD', 0.0), promotes=['*'])  #0.0
        self.add('mpileL', IndepVarComp('mpileL', 0.0), promotes=['*'])  #0.0
        self.add('mpEmbedL', IndepVarComp('mpEmbedL', 0.0),
                 promotes=['*'])  #30.0
        self.add('jlatticeCR', IndepVarComp('jlatticeCR', 0.0),
                 promotes=['*'])  #4680.0
        self.add('jtransCR', IndepVarComp('jtransCR', 0.0),
                 promotes=['*'])  #4500.0
        self.add('jpileCR', IndepVarComp('jpileCR', 0.0),
                 promotes=['*'])  #2250.0
        self.add('jlatticeA', IndepVarComp('jlatticeA', 0.0),
                 promotes=['*'])  #26.0
        self.add('jpileL', IndepVarComp('jpileL', 0.0), promotes=['*'])  #47.50
        self.add('jpileD', IndepVarComp('jpileD', 0.0), promotes=['*'])  #1.60
        self.add('ssHeaveCR', IndepVarComp('ssHeaveCR', 0.0),
                 promotes=['*'])  #6250.0
        self.add('scourMat', IndepVarComp('scourMat', 0.0),
                 promotes=['*'])  #250000.0
        self.add('number_install_seasons',
                 IndepVarComp('number_install_seasons', 0, pass_by_obj=True),
                 promotes=['*'])  #1
        #Electrical Infrastructure', ,
        self.add('pwrFac', IndepVarComp('pwrFac', 0.0), promotes=['*'])  #0.95
        self.add('buryFac', IndepVarComp('buryFac', 0.0),
                 promotes=['*'])  #0.10
        self.add('catLengFac', IndepVarComp('catLengFac', 0.0),
                 promotes=['*'])  #0.04
        self.add('exCabFac', IndepVarComp('exCabFac', 0.0),
                 promotes=['*'])  #0.10
        self.add('subsTopFab', IndepVarComp('subsTopFab', 0.0),
                 promotes=['*'])  #14500.0
        self.add('subsTopDes', IndepVarComp('subsTopDes', 0.0),
                 promotes=['*'])  #4500000.0
        self.add('topAssemblyFac',
                 IndepVarComp('topAssemblyFac', 0.0),
                 promotes=['*'])  #0.075
        self.add('subsJackCR', IndepVarComp('subsJackCR', 0.0),
                 promotes=['*'])  #6250.0
        self.add('subsPileCR', IndepVarComp('subsPileCR', 0.0),
                 promotes=['*'])  #2250.0
        self.add('dynCabFac', IndepVarComp('dynCabFac', 0.0),
                 promotes=['*'])  #2.0
        self.add('shuntCR', IndepVarComp('shuntCR', 0.0),
                 promotes=['*'])  #35000.0
        self.add('highVoltSG', IndepVarComp('highVoltSG', 0.0),
                 promotes=['*'])  #950000.0
        self.add('medVoltSG', IndepVarComp('medVoltSG', 0.0),
                 promotes=['*'])  #500000.0
        self.add('backUpGen', IndepVarComp('backUpGen', 0.0),
                 promotes=['*'])  #1000000.0
        self.add('workSpace', IndepVarComp('workSpace', 0.0),
                 promotes=['*'])  #2000000.0
        self.add('otherAncillary',
                 IndepVarComp('otherAncillary', 0.0),
                 promotes=['*'])  #3000000.0
        self.add('mptCR', IndepVarComp('mptCR', 0.0), promotes=['*'])  #12500.0
        self.add('arrVoltage', IndepVarComp('arrVoltage', 0.0),
                 promotes=['*'])  #33.0
        self.add('cab1CR', IndepVarComp('cab1CR', 0.0),
                 promotes=['*'])  #185.889
        self.add('cab2CR', IndepVarComp('cab2CR', 0.0),
                 promotes=['*'])  #202.788
        self.add('cab1CurrRating',
                 IndepVarComp('cab1CurrRating', 0.0),
                 promotes=['*'])  #300.0
        self.add('cab2CurrRating',
                 IndepVarComp('cab2CurrRating', 0.0),
                 promotes=['*'])  #340.0
        self.add('arrCab1Mass',
                 IndepVarComp('arrCab1Mass', 0.0),
                 promotes=['*'])  #20.384
        self.add('arrCab2Mass',
                 IndepVarComp('arrCab2Mass', 0.0),
                 promotes=['*'])  #21.854
        self.add('cab1TurbInterCR',
                 IndepVarComp('cab1TurbInterCR', 0.0),
                 promotes=['*'])  #8410.0
        self.add('cab2TurbInterCR',
                 IndepVarComp('cab2TurbInterCR', 0.0),
                 promotes=['*'])  #8615.0
        self.add('cab2SubsInterCR',
                 IndepVarComp('cab2SubsInterCR', 0.0),
                 promotes=['*'])  #19815.0
        self.add('expVoltage', IndepVarComp('expVoltage', 0.0),
                 promotes=['*'])  #220.0
        self.add('expCurrRating',
                 IndepVarComp('expCurrRating', 0.0),
                 promotes=['*'])  #530.0
        self.add('expCabMass', IndepVarComp('expCabMass', 0.0),
                 promotes=['*'])  #71.90
        self.add('expCabCR', IndepVarComp('expCabCR', 0.0),
                 promotes=['*'])  #495.411
        self.add('expSubsInterCR',
                 IndepVarComp('expSubsInterCR', 0.0),
                 promotes=['*'])  #57500.0
        # Vector inputs
        #self.add('arrayCables',                  IndepVarComp('arrayCables', [33, 66], pass_by_obj=True), promotes=['*'])
        #self.add('exportCables',                 IndepVarComp('exportCables', [132, 220], pass_by_obj=True), promotes=['*'])
        #Assembly & Installation',
        self.add('moorTimeFac',
                 IndepVarComp('moorTimeFac', 0.0),
                 promotes=['*'])  #0.005
        self.add('moorLoadout',
                 IndepVarComp('moorLoadout', 0.0),
                 promotes=['*'])  #5.0
        self.add('moorSurvey', IndepVarComp('moorSurvey', 0.0),
                 promotes=['*'])  #4.0
        self.add('prepAA', IndepVarComp('prepAA', 0.0), promotes=['*'])  #168.0
        self.add('prepSpar', IndepVarComp('prepSpar', 0.0),
                 promotes=['*'])  #18.0
        self.add('upendSpar', IndepVarComp('upendSpar', 0.0),
                 promotes=['*'])  #36.0
        self.add('prepSemi', IndepVarComp('prepSemi', 0.0),
                 promotes=['*'])  #12.0
        self.add('turbFasten', IndepVarComp('turbFasten', 0.0),
                 promotes=['*'])  #8.0
        self.add('boltTower', IndepVarComp('boltTower', 0.0),
                 promotes=['*'])  #7.0
        self.add('boltNacelle1',
                 IndepVarComp('boltNacelle1', 0.0),
                 promotes=['*'])  #7.0
        self.add('boltNacelle2',
                 IndepVarComp('boltNacelle2', 0.0),
                 promotes=['*'])  #7.0
        self.add('boltNacelle3',
                 IndepVarComp('boltNacelle3', 0.0),
                 promotes=['*'])  #7.0
        self.add('boltBlade1', IndepVarComp('boltBlade1', 0.0),
                 promotes=['*'])  #3.50
        self.add('boltBlade2', IndepVarComp('boltBlade2', 0.0),
                 promotes=['*'])  #3.50
        self.add('boltRotor', IndepVarComp('boltRotor', 0.0),
                 promotes=['*'])  #7.0
        self.add('vesselPosTurb',
                 IndepVarComp('vesselPosTurb', 0.0),
                 promotes=['*'])  #2.0
        self.add('vesselPosJack',
                 IndepVarComp('vesselPosJack', 0.0),
                 promotes=['*'])  #8.0
        self.add('vesselPosMono',
                 IndepVarComp('vesselPosMono', 0.0),
                 promotes=['*'])  #3.0
        self.add('subsVessPos',
                 IndepVarComp('subsVessPos', 0.0),
                 promotes=['*'])  #6.0
        self.add('monoFasten', IndepVarComp('monoFasten', 0.0),
                 promotes=['*'])  #12.0
        self.add('jackFasten', IndepVarComp('jackFasten', 0.0),
                 promotes=['*'])  #20.0
        self.add('prepGripperMono',
                 IndepVarComp('prepGripperMono', 0.0),
                 promotes=['*'])  #1.50
        self.add('prepGripperJack',
                 IndepVarComp('prepGripperJack', 0.0),
                 promotes=['*'])  #8.0
        self.add('placePiles', IndepVarComp('placePiles', 0.0),
                 promotes=['*'])  #12.0
        self.add('prepHamMono',
                 IndepVarComp('prepHamMono', 0.0),
                 promotes=['*'])  #2.0
        self.add('prepHamJack',
                 IndepVarComp('prepHamJack', 0.0),
                 promotes=['*'])  #2.0
        self.add('removeHamMono',
                 IndepVarComp('removeHamMono', 0.0),
                 promotes=['*'])  #2.0
        self.add('removeHamJack',
                 IndepVarComp('removeHamJack', 0.0),
                 promotes=['*'])  #4.0
        self.add('placeTemplate',
                 IndepVarComp('placeTemplate', 0.0),
                 promotes=['*'])  #4.0
        self.add('placeJack', IndepVarComp('placeJack', 0.0),
                 promotes=['*'])  #12.0
        self.add('levJack', IndepVarComp('levJack', 0.0),
                 promotes=['*'])  #24.0
        self.add('hamRate', IndepVarComp('hamRate', 0.0),
                 promotes=['*'])  #20.0
        self.add('placeMP', IndepVarComp('placeMP', 0.0), promotes=['*'])  #3.0
        self.add('instScour', IndepVarComp('instScour', 0.0),
                 promotes=['*'])  #6.0
        self.add('placeTP', IndepVarComp('placeTP', 0.0), promotes=['*'])  #3.0
        self.add('groutTP', IndepVarComp('groutTP', 0.0), promotes=['*'])  #8.0
        self.add('tpCover', IndepVarComp('tpCover', 0.0),
                 promotes=['*'])  #1.50
        self.add('prepTow', IndepVarComp('prepTow', 0.0),
                 promotes=['*'])  #12.0
        self.add('spMoorCon', IndepVarComp('spMoorCon', 0.0),
                 promotes=['*'])  #20.0
        self.add('ssMoorCon', IndepVarComp('ssMoorCon', 0.0),
                 promotes=['*'])  #22.0
        self.add('spMoorCheck',
                 IndepVarComp('spMoorCheck', 0.0),
                 promotes=['*'])  #16.0
        self.add('ssMoorCheck',
                 IndepVarComp('ssMoorCheck', 0.0),
                 promotes=['*'])  #12.0
        self.add('ssBall', IndepVarComp('ssBall', 0.0), promotes=['*'])  #6.0
        self.add('surfLayRate',
                 IndepVarComp('surfLayRate', 0.0),
                 promotes=['*'])  #375.0
        self.add('cabPullIn', IndepVarComp('cabPullIn', 0.0),
                 promotes=['*'])  #5.50
        self.add('cabTerm', IndepVarComp('cabTerm', 0.0),
                 promotes=['*'])  #5.50
        self.add('cabLoadout', IndepVarComp('cabLoadout', 0.0),
                 promotes=['*'])  #14.0
        self.add('buryRate', IndepVarComp('buryRate', 0.0),
                 promotes=['*'])  #125.0
        self.add('subsPullIn', IndepVarComp('subsPullIn', 0.0),
                 promotes=['*'])  #48.0
        self.add('shorePullIn',
                 IndepVarComp('shorePullIn', 0.0),
                 promotes=['*'])  #96.0
        self.add('landConstruct',
                 IndepVarComp('landConstruct', 0.0),
                 promotes=['*'])  #7.0
        self.add('expCabLoad', IndepVarComp('expCabLoad', 0.0),
                 promotes=['*'])  #24.0
        self.add('subsLoad', IndepVarComp('subsLoad', 0.0),
                 promotes=['*'])  #60.0
        self.add('placeTop', IndepVarComp('placeTop', 0.0),
                 promotes=['*'])  #24.0
        self.add('pileSpreadDR',
                 IndepVarComp('pileSpreadDR', 0.0),
                 promotes=['*'])  #2500.0
        self.add('pileSpreadMob',
                 IndepVarComp('pileSpreadMob', 0.0),
                 promotes=['*'])  #750000.0
        self.add('groutSpreadDR',
                 IndepVarComp('groutSpreadDR', 0.0),
                 promotes=['*'])  #3000.0
        self.add('groutSpreadMob',
                 IndepVarComp('groutSpreadMob', 0.0),
                 promotes=['*'])  #1000000.0
        self.add('seaSpreadDR',
                 IndepVarComp('seaSpreadDR', 0.0),
                 promotes=['*'])  #165000.0
        self.add('seaSpreadMob',
                 IndepVarComp('seaSpreadMob', 0.0),
                 promotes=['*'])  #4500000.0
        self.add('compRacks', IndepVarComp('compRacks', 0.0),
                 promotes=['*'])  #1000000.0
        self.add('cabSurveyCR',
                 IndepVarComp('cabSurveyCR', 0.0),
                 promotes=['*'])  #240.0
        self.add('cabDrillDist',
                 IndepVarComp('cabDrillDist', 0.0),
                 promotes=['*'])  #500.0
        self.add('cabDrillCR', IndepVarComp('cabDrillCR', 0.0),
                 promotes=['*'])  #3200.0
        self.add('mpvRentalDR',
                 IndepVarComp('mpvRentalDR', 0.0),
                 promotes=['*'])  #72000.0
        self.add('diveTeamDR', IndepVarComp('diveTeamDR', 0.0),
                 promotes=['*'])  #3200.0
        self.add('winchDR', IndepVarComp('winchDR', 0.0),
                 promotes=['*'])  #1000.0
        self.add('civilWork', IndepVarComp('civilWork', 0.0),
                 promotes=['*'])  #40000.0
        self.add('elecWork', IndepVarComp('elecWork', 0.0),
                 promotes=['*'])  #25000.0
        #Port & Staging', ,
        self.add('nCrane600',
                 IndepVarComp('nCrane600', 0, pass_by_obj=True),
                 promotes=['*'])  #0
        self.add('nCrane1000',
                 IndepVarComp('nCrane1000', 0, pass_by_obj=True),
                 promotes=['*'])  #0
        self.add('crane600DR', IndepVarComp('crane600DR', 0.0),
                 promotes=['*'])  #5000.0
        self.add('crane1000DR',
                 IndepVarComp('crane1000DR', 0.0),
                 promotes=['*'])  #8000.0
        self.add('craneMobDemob',
                 IndepVarComp('craneMobDemob', 0.0),
                 promotes=['*'])  #150000.0
        self.add('entranceExitRate',
                 IndepVarComp('entranceExitRate', 0.0),
                 promotes=['*'])  #0.525
        self.add('dockRate', IndepVarComp('dockRate', 0.0),
                 promotes=['*'])  #3000.0
        self.add('wharfRate', IndepVarComp('wharfRate', 0.0),
                 promotes=['*'])  #2.75
        self.add('laydownCR', IndepVarComp('laydownCR', 0.0),
                 promotes=['*'])  #0.25
        #Engineering & Management', ,
        self.add('estEnMFac', IndepVarComp('estEnMFac', 0.0),
                 promotes=['*'])  #0.04
        #Development', ,
        self.add('preFEEDStudy',
                 IndepVarComp('preFEEDStudy', 0.0),
                 promotes=['*'])  #5000000.0
        self.add('feedStudy', IndepVarComp('feedStudy', 0.0),
                 promotes=['*'])  #10000000.0
        self.add('stateLease', IndepVarComp('stateLease', 0.0),
                 promotes=['*'])  #250000.0
        self.add('outConShelfLease',
                 IndepVarComp('outConShelfLease', 0.0),
                 promotes=['*'])  #1000000.0
        self.add('saPlan', IndepVarComp('saPlan', 0.0),
                 promotes=['*'])  #500000.0
        self.add('conOpPlan', IndepVarComp('conOpPlan', 0.0),
                 promotes=['*'])  #1000000.0
        self.add('nepaEisMet', IndepVarComp('nepaEisMet', 0.0),
                 promotes=['*'])  #2000000.0
        self.add('physResStudyMet',
                 IndepVarComp('physResStudyMet', 0.0),
                 promotes=['*'])  #1500000.0
        self.add('bioResStudyMet',
                 IndepVarComp('bioResStudyMet', 0.0),
                 promotes=['*'])  #1500000.0
        self.add('socEconStudyMet',
                 IndepVarComp('socEconStudyMet', 0.0),
                 promotes=['*'])  #500000.0
        self.add('navStudyMet',
                 IndepVarComp('navStudyMet', 0.0),
                 promotes=['*'])  #500000.0
        self.add('nepaEisProj',
                 IndepVarComp('nepaEisProj', 0.0),
                 promotes=['*'])  #5000000.0
        self.add('physResStudyProj',
                 IndepVarComp('physResStudyProj', 0.0),
                 promotes=['*'])  #500000.0
        self.add('bioResStudyProj',
                 IndepVarComp('bioResStudyProj', 0.0),
                 promotes=['*'])  #500000.0
        self.add('socEconStudyProj',
                 IndepVarComp('socEconStudyProj', 0.0),
                 promotes=['*'])  #200000.0
        self.add('navStudyProj',
                 IndepVarComp('navStudyProj', 0.0),
                 promotes=['*'])  #250000.0
        self.add('coastZoneManAct',
                 IndepVarComp('coastZoneManAct', 0.0),
                 promotes=['*'])  #100000.0
        self.add('rivsnHarbsAct',
                 IndepVarComp('rivsnHarbsAct', 0.0),
                 promotes=['*'])  #100000.0
        self.add('cleanWatAct402',
                 IndepVarComp('cleanWatAct402', 0.0),
                 promotes=['*'])  #100000.0
        self.add('cleanWatAct404',
                 IndepVarComp('cleanWatAct404', 0.0),
                 promotes=['*'])  #100000.0
        self.add('faaPlan', IndepVarComp('faaPlan', 0.0),
                 promotes=['*'])  #10000.0
        self.add('endSpecAct', IndepVarComp('endSpecAct', 0.0),
                 promotes=['*'])  #500000.0
        self.add('marMamProtAct',
                 IndepVarComp('marMamProtAct', 0.0),
                 promotes=['*'])  #500000.0
        self.add('migBirdAct', IndepVarComp('migBirdAct', 0.0),
                 promotes=['*'])  #500000.0
        self.add('natHisPresAct',
                 IndepVarComp('natHisPresAct', 0.0),
                 promotes=['*'])  #250000.0
        self.add('addLocPerm', IndepVarComp('addLocPerm', 0.0),
                 promotes=['*'])  #200000.0
        self.add('metTowCR', IndepVarComp('metTowCR', 0.0),
                 promotes=['*'])  #11518.0
        self.add('decomDiscRate',
                 IndepVarComp('decomDiscRate', 0.0),
                 promotes=['*'])  #0.03

        # LCOE
        self.add('number_of_turbines',
                 IndepVarComp('number_of_turbines', 0, pass_by_obj=True),
                 promotes=['*'])
        self.add('annual_opex',
                 IndepVarComp('annual_opex', 0.0),
                 promotes=['*'])  # TODO: Replace with output connection
        self.add('fixed_charge_rate',
                 IndepVarComp('fixed_charge_rate', 0.0),
                 promotes=['*'])
        self.add('discount_rate',
                 IndepVarComp('discount_rate', 0.0),
                 promotes=['*'])

        # Connect all input variables from all models
        self.connect('water_depth',
                     ['sm.water_depth', 'wobos.waterD', 'sea_depth'])
        self.connect('hub_height',
                     ['rotor.hub_height', 'sm.hub_height', 'wobos.hubH'])
        self.connect('tower_outer_diameter', 'wobos.towerD', src_indices=[0])

        self.connect('wind_beta', 'sm.beta')
        self.connect('cd_usr', 'sm.cd_usr')
        #self.connect('wave_beta', 'sm.waveLoads.beta')
        self.connect('yaw', 'sm.yaw')
        self.connect('mean_current_speed', 'sm.Uc')

        self.connect('project_lifetime',
                     ['rotor.struc.lifetime', 'wobos.projLife'])
        #self.connect('slope_SN', 'sm.m_SN')
        #self.connect('compute_shear', 'sm.shear')
        #self.connect('compute_stiffnes', 'sm.geom')
        #self.connect('frame3dd_matrix_method', 'sm.Mmethod')
        #self.connect('shift_value', 'sm.shift')
        # TODO:
        #self.connect('number_of_modes', ['sm.nM', 'rotor.nF'])
        self.connect('number_of_modes', 'rotor.nF')
        #self.connect('frame3dd_convergence_tolerance', 'sm.tol')
        #self.connect('lumped_mass_matrix', 'sm.lump')
        #self.connect('stress_standard_value', 'sm.DC')

        self.connect('safety_factor_frequency',
                     ['rotor.gamma_freq', 'tcons.gamma_freq'])
        self.connect('safety_factor_stress', ['sm.gamma_f', 'rotor.gamma_f'])
        self.connect('safety_factor_materials',
                     ['sm.gamma_m', 'rotor.gamma_m', 'tcons.gamma_m'])
        self.connect('safety_factor_buckling', 'sm.gamma_b')
        self.connect('safety_factor_fatigue',
                     ['rotor.gamma_fatigue', 'sm.gamma_fatigue'])
        self.connect('safety_factor_consequence', 'sm.gamma_n')
        self.connect('rna.loads.top_F', 'sm.rna_force')
        self.connect('rna.loads.top_M', 'sm.rna_moment')
        self.connect('rna.rna_I_TT', 'sm.rna_I')
        self.connect('rna.rna_mass', ['wobos.rnaM', 'sm.rna_mass'])
        self.connect('rna.rna_cm', 'sm.rna_cg')
        self.connect('rotor.mass_all_blades', 'rna.blades_mass')
        self.connect('rotor.I_all_blades', 'rna.blades_I')
        self.connect('hub_mass', 'rna.hub_mass')
        self.connect('nac_mass', 'rna.nac_mass')
        self.connect('hub_cm', ['rna.hub_cm', 'tcons.hub_tt'])
        self.connect('nac_cm', 'rna.nac_cm')
        self.connect('hub_I', 'rna.hub_I')
        self.connect('nac_I', 'rna.nac_I')
        self.connect('tilt', 'rna.tilt')
        self.connect('rotor.Fxyz_total', 'rna.loads.F')
        self.connect('rotor.Mxyz_total', 'rna.loads.M')
        self.connect('downwind', 'rna.downwind')
        self.connect('rna_weightM', 'rna.rna_weightM')

        self.connect('air_density',
                     ['sm.base.windLoads.rho', 'rotor.analysis.rho'])
        self.connect('air_viscosity',
                     ['sm.base.windLoads.mu', 'rotor.analysis.mu'])
        self.connect('water_density', 'sm.water_density')
        self.connect('water_viscosity', 'sm.base.waveLoads.mu')
        self.connect('wave_height', 'sm.hmax')
        self.connect('wave_period', 'sm.T')
        self.connect('wind_reference_speed', 'sm.Uref')
        self.connect('wind_reference_height', ['sm.zref', 'rotor.wind.zref'])
        self.connect('wind_bottom_height', ['sm.z0', 'rotor.wind.z0'])
        self.connect('shearExp', ['sm.shearExp', 'rotor.wind.shearExp'])
        self.connect('morison_mass_coefficient', 'sm.cm')
        self.connect('material_density', 'sm.material_density')
        self.connect('E', 'sm.E')
        self.connect('G', 'sm.G')
        self.connect('nu', 'sm.nu')
        self.connect('yield_stress', 'sm.yield_stress')

        self.connect('anchor', 'wobos.anchor')
        self.connect('ballast_cost_rate', 'wobos.ballCR')
        self.connect('drag_embedment_extra_length', 'wobos.deaFixLeng')
        self.connect('mooring_cost_rate', 'wobos.moorCR')
        self.connect('sm.mm.mooring_cost', 'wobos.moorCost')
        self.connect('mooring_diameter', 'wobos.moorDia')
        self.connect('number_of_mooring_lines', 'wobos.moorLines')
        self.connect('outfitting_cost_rate', 'wobos.sSteelCR')
        self.connect(
            'tapered_col_cost_rate',
            ['wobos.spStifColCR', 'wobos.spTapColCR', 'wobos.ssStifColCR'])
        self.connect('pontoon_cost_rate', 'wobos.ssTrussCR')

        self.connect('nBlades', 'blade_number')
        self.connect('rotor.mass_one_blade', 'blade_mass')
        self.connect('control:maxOmega', 'tcons.rotor_omega')
        self.connect('sm.load.f1', 'tcons.tower_f1')
        self.connect('sm.load.f2', 'tcons.tower_f2')
        self.connect('sm.tow.z_full', 'tcons.tower_z')
        self.connect('sm.tow.d_full', 'tcons.tower_d')

        self.connect('turbine_cost_kW', 'wobos.turbCapEx')
        self.connect('machine_rating', 'wobos.turbR')
        self.connect('rotor.diameter', 'wobos.rotorD')
        self.connect('bladeLength', 'wobos.bladeL')
        self.connect('rotor.max_chord', 'wobos.chord')
        self.connect('rotor.hub_diameter', 'wobos.hubD')
        self.connect('nacelleL',
                     'wobos.nacelleL')  # TODO: RotorSE, remove variable
        self.connect('nacelleW',
                     'wobos.nacelleW')  # TODO: RotorSE, remove variable
        self.connect('distShore', 'wobos.distShore')
        self.connect('distPort', 'wobos.distPort')
        self.connect('distPtoA', 'wobos.distPtoA')
        self.connect('distAtoS', 'wobos.distAtoS')
        self.connect('substructure', 'wobos.substructure')
        self.connect('turbInstallMethod', 'wobos.turbInstallMethod')
        self.connect('towerInstallMethod', 'wobos.towerInstallMethod')
        self.connect('installStrategy', 'wobos.installStrategy')
        self.connect('cableOptimizer', 'wobos.cableOptimizer')
        self.connect('buryDepth', 'wobos.buryDepth')
        self.connect('arrayY',
                     'wobos.arrayY')  # TODO: Plant_EnergySE, remove variable
        self.connect('arrayX',
                     'wobos.arrayX')  # TODO: Plant_EnergySE, remove variable
        self.connect('substructCont', 'wobos.substructCont')
        self.connect('turbCont', 'wobos.turbCont')
        self.connect('elecCont', 'wobos.elecCont')
        self.connect('interConVolt', 'wobos.interConVolt')
        self.connect('distInterCon', 'wobos.distInterCon')
        self.connect('scrapVal', 'wobos.scrapVal')
        self.connect('inspectClear', 'wobos.inspectClear')
        self.connect('plantComm', 'wobos.plantComm')
        self.connect('procurement_contingency',
                     'wobos.procurement_contingency')
        self.connect('install_contingency', 'wobos.install_contingency')
        self.connect('construction_insurance', 'wobos.construction_insurance')
        self.connect('capital_cost_year_0', 'wobos.capital_cost_year_0')
        self.connect('capital_cost_year_1', 'wobos.capital_cost_year_1')
        self.connect('capital_cost_year_2', 'wobos.capital_cost_year_2')
        self.connect('capital_cost_year_3', 'wobos.capital_cost_year_3')
        self.connect('capital_cost_year_4', 'wobos.capital_cost_year_4')
        self.connect('capital_cost_year_5', 'wobos.capital_cost_year_5')
        self.connect('interest_during_construction',
                     'wobos.interest_during_construction')
        self.connect('mpileCR',
                     'wobos.mpileCR')  # TODO: JacketSE, remove variable
        self.connect('mtransCR',
                     'wobos.mtransCR')  # TODO: JacketSE, remove variable
        self.connect('mpileD',
                     'wobos.mpileD')  # TODO: JacketSE, remove variable
        self.connect('mpileL',
                     'wobos.mpileL')  # TODO: JacketSE, remove variable
        self.connect('mpEmbedL',
                     'wobos.mpEmbedL')  # TODO: JacketSE, remove variable
        self.connect('jlatticeCR',
                     'wobos.jlatticeCR')  # TODO: JacketSE, remove variable
        self.connect('jtransCR',
                     'wobos.jtransCR')  # TODO: JacketSE, remove variable
        self.connect('jpileCR',
                     'wobos.jpileCR')  # TODO: JacketSE, remove variable
        self.connect('jlatticeA',
                     'wobos.jlatticeA')  # TODO: JacketSE, remove variable
        self.connect('jpileL',
                     'wobos.jpileL')  # TODO: JacketSE, remove variable
        self.connect('jpileD',
                     'wobos.jpileD')  # TODO: JacketSE, remove variable
        self.connect('ssHeaveCR', 'wobos.ssHeaveCR')
        self.connect('scourMat', 'wobos.scourMat')
        self.connect('number_install_seasons', 'wobos.number_install_seasons')
        self.connect('pwrFac', 'wobos.pwrFac')
        self.connect('buryFac', 'wobos.buryFac')
        self.connect('catLengFac', 'wobos.catLengFac')
        self.connect('exCabFac', 'wobos.exCabFac')
        self.connect('subsTopFab', 'wobos.subsTopFab')
        self.connect('subsTopDes', 'wobos.subsTopDes')
        self.connect('topAssemblyFac', 'wobos.topAssemblyFac')
        self.connect('subsJackCR', 'wobos.subsJackCR')
        self.connect('subsPileCR', 'wobos.subsPileCR')
        self.connect('dynCabFac', 'wobos.dynCabFac')
        self.connect('shuntCR', 'wobos.shuntCR')
        self.connect('highVoltSG', 'wobos.highVoltSG')
        self.connect('medVoltSG', 'wobos.medVoltSG')
        self.connect('backUpGen', 'wobos.backUpGen')
        self.connect('workSpace', 'wobos.workSpace')
        self.connect('otherAncillary', 'wobos.otherAncillary')
        self.connect('mptCR', 'wobos.mptCR')
        self.connect('arrVoltage', 'wobos.arrVoltage')
        self.connect('cab1CR', 'wobos.cab1CR')
        self.connect('cab2CR', 'wobos.cab2CR')
        self.connect('cab1CurrRating', 'wobos.cab1CurrRating')
        self.connect('cab2CurrRating', 'wobos.cab2CurrRating')
        self.connect('arrCab1Mass', 'wobos.arrCab1Mass')
        self.connect('arrCab2Mass', 'wobos.arrCab2Mass')
        self.connect('cab1TurbInterCR', 'wobos.cab1TurbInterCR')
        self.connect('cab2TurbInterCR', 'wobos.cab2TurbInterCR')
        self.connect('cab2SubsInterCR', 'wobos.cab2SubsInterCR')
        self.connect('expVoltage', 'wobos.expVoltage')
        self.connect('expCurrRating', 'wobos.expCurrRating')
        self.connect('expCabMass', 'wobos.expCabMass')
        self.connect('expCabCR', 'wobos.expCabCR')
        self.connect('expSubsInterCR', 'wobos.expSubsInterCR')
        #self.connect('arrayCables', 'wobos.arrayCables')
        #self.connect('exportCables', 'wobos.exportCables')
        self.connect('moorTimeFac', 'wobos.moorTimeFac')
        self.connect('moorLoadout', 'wobos.moorLoadout')
        self.connect('moorSurvey', 'wobos.moorSurvey')
        self.connect('prepAA', 'wobos.prepAA')
        self.connect('prepSpar', 'wobos.prepSpar')
        self.connect('upendSpar', 'wobos.upendSpar')
        self.connect('prepSemi', 'wobos.prepSemi')
        self.connect('turbFasten', 'wobos.turbFasten')
        self.connect('boltTower', 'wobos.boltTower')
        self.connect('boltNacelle1', 'wobos.boltNacelle1')
        self.connect('boltNacelle2', 'wobos.boltNacelle2')
        self.connect('boltNacelle3', 'wobos.boltNacelle3')
        self.connect('boltBlade1', 'wobos.boltBlade1')
        self.connect('boltBlade2', 'wobos.boltBlade2')
        self.connect('boltRotor', 'wobos.boltRotor')
        self.connect('vesselPosTurb', 'wobos.vesselPosTurb')
        self.connect('vesselPosJack', 'wobos.vesselPosJack')
        self.connect('vesselPosMono', 'wobos.vesselPosMono')
        self.connect('subsVessPos', 'wobos.subsVessPos')
        self.connect('monoFasten', 'wobos.monoFasten')
        self.connect('jackFasten', 'wobos.jackFasten')
        self.connect('prepGripperMono', 'wobos.prepGripperMono')
        self.connect('prepGripperJack', 'wobos.prepGripperJack')
        self.connect('placePiles', 'wobos.placePiles')
        self.connect('prepHamMono', 'wobos.prepHamMono')
        self.connect('prepHamJack', 'wobos.prepHamJack')
        self.connect('removeHamMono', 'wobos.removeHamMono')
        self.connect('removeHamJack', 'wobos.removeHamJack')
        self.connect('placeTemplate', 'wobos.placeTemplate')
        self.connect('placeJack', 'wobos.placeJack')
        self.connect('levJack', 'wobos.levJack')
        self.connect('hamRate', 'wobos.hamRate')
        self.connect('placeMP', 'wobos.placeMP')
        self.connect('instScour', 'wobos.instScour')
        self.connect('placeTP', 'wobos.placeTP')
        self.connect('groutTP', 'wobos.groutTP')
        self.connect('tpCover', 'wobos.tpCover')
        self.connect('prepTow', 'wobos.prepTow')
        self.connect('spMoorCon', 'wobos.spMoorCon')
        self.connect('ssMoorCon', 'wobos.ssMoorCon')
        self.connect('spMoorCheck', 'wobos.spMoorCheck')
        self.connect('ssMoorCheck', 'wobos.ssMoorCheck')
        self.connect('ssBall', 'wobos.ssBall')
        self.connect('surfLayRate', 'wobos.surfLayRate')
        self.connect('cabPullIn', 'wobos.cabPullIn')
        self.connect('cabTerm', 'wobos.cabTerm')
        self.connect('cabLoadout', 'wobos.cabLoadout')
        self.connect('buryRate', 'wobos.buryRate')
        self.connect('subsPullIn', 'wobos.subsPullIn')
        self.connect('shorePullIn', 'wobos.shorePullIn')
        self.connect('landConstruct', 'wobos.landConstruct')
        self.connect('expCabLoad', 'wobos.expCabLoad')
        self.connect('subsLoad', 'wobos.subsLoad')
        self.connect('placeTop', 'wobos.placeTop')
        self.connect('pileSpreadDR', 'wobos.pileSpreadDR')
        self.connect('pileSpreadMob', 'wobos.pileSpreadMob')
        self.connect('groutSpreadDR', 'wobos.groutSpreadDR')
        self.connect('groutSpreadMob', 'wobos.groutSpreadMob')
        self.connect('seaSpreadDR', 'wobos.seaSpreadDR')
        self.connect('seaSpreadMob', 'wobos.seaSpreadMob')
        self.connect('compRacks', 'wobos.compRacks')
        self.connect('cabSurveyCR', 'wobos.cabSurveyCR')
        self.connect('cabDrillDist', 'wobos.cabDrillDist')
        self.connect('cabDrillCR', 'wobos.cabDrillCR')
        self.connect('mpvRentalDR', 'wobos.mpvRentalDR')
        self.connect('diveTeamDR', 'wobos.diveTeamDR')
        self.connect('winchDR', 'wobos.winchDR')
        self.connect('civilWork', 'wobos.civilWork')
        self.connect('elecWork', 'wobos.elecWork')
        self.connect('nCrane600', 'wobos.nCrane600')
        self.connect('nCrane1000', 'wobos.nCrane1000')
        self.connect('crane600DR', 'wobos.crane600DR')
        self.connect('crane1000DR', 'wobos.crane1000DR')
        self.connect('craneMobDemob', 'wobos.craneMobDemob')
        self.connect('entranceExitRate', 'wobos.entranceExitRate')
        self.connect('dockRate', 'wobos.dockRate')
        self.connect('wharfRate', 'wobos.wharfRate')
        self.connect('laydownCR', 'wobos.laydownCR')
        self.connect('estEnMFac', 'wobos.estEnMFac')
        self.connect('preFEEDStudy', 'wobos.preFEEDStudy')
        self.connect('feedStudy', 'wobos.feedStudy')
        self.connect('stateLease', 'wobos.stateLease')
        self.connect('outConShelfLease', 'wobos.outConShelfLease')
        self.connect('saPlan', 'wobos.saPlan')
        self.connect('conOpPlan', 'wobos.conOpPlan')
        self.connect('nepaEisMet', 'wobos.nepaEisMet')
        self.connect('physResStudyMet', 'wobos.physResStudyMet')
        self.connect('bioResStudyMet', 'wobos.bioResStudyMet')
        self.connect('socEconStudyMet', 'wobos.socEconStudyMet')
        self.connect('navStudyMet', 'wobos.navStudyMet')
        self.connect('nepaEisProj', 'wobos.nepaEisProj')
        self.connect('physResStudyProj', 'wobos.physResStudyProj')
        self.connect('bioResStudyProj', 'wobos.bioResStudyProj')
        self.connect('socEconStudyProj', 'wobos.socEconStudyProj')
        self.connect('navStudyProj', 'wobos.navStudyProj')
        self.connect('coastZoneManAct', 'wobos.coastZoneManAct')
        self.connect('rivsnHarbsAct', 'wobos.rivsnHarbsAct')
        self.connect('cleanWatAct402', 'wobos.cleanWatAct402')
        self.connect('cleanWatAct404', 'wobos.cleanWatAct404')
        self.connect('faaPlan', 'wobos.faaPlan')
        self.connect('endSpecAct', 'wobos.endSpecAct')
        self.connect('marMamProtAct', 'wobos.marMamProtAct')
        self.connect('migBirdAct', 'wobos.migBirdAct')
        self.connect('natHisPresAct', 'wobos.natHisPresAct')
        self.connect('addLocPerm', 'wobos.addLocPerm')
        self.connect('metTowCR', 'wobos.metTowCR')
        self.connect('decomDiscRate', 'wobos.decomDiscRate')

        # Link outputs from one model to inputs to another
        self.connect('tower_mass', 'wobos.towerM')
        self.connect('dummy_mass', 'sm.aux.stack_mass_in')

        self.connect('sm.total_cost', 'wobos.subTotCost')
        self.connect('sm.total_mass', 'wobos.subTotM')
        self.connect('wobos.total_bos_cost', 'bos_costs')

        self.connect('number_of_turbines', ['wobos.nTurb', 'turbine_number'])
        self.connect('annual_opex', 'avg_annual_opex')
        self.connect('rotor.AEP', 'net_aep')
        self.connect('wobos.totInstTime', 'construction_time')

        # Use complex number finite differences
        typeStr = 'fd'
        formStr = 'central'
        stepVal = 1e-5
        stepStr = 'relative'

        self.deriv_options['type'] = typeStr
        self.deriv_options['form'] = formStr
        self.deriv_options['step_size'] = stepVal
        self.deriv_options['step_calc'] = stepStr
示例#4
0
    def execute(self):

        # --- Import Modules
        import numpy as np
        import os
        from openmdao.api import IndepVarComp, Component, Group, Problem, Brent, ScipyGMRES, ScipyOptimizer, DumpRecorder
        from rotorse.rotor_aeropower import RotorAeroPower
        from rotorse.rotor_geometry import RotorGeometry, NREL5MW, DTU10MW, NINPUT
        from rotorse import RPM2RS, RS2RPM, TURBULENCE_CLASS, DRIVETRAIN_TYPE
        from rotorse.rotor import RotorSE

        myref = DTU10MW()

        rotor = Problem()
        npts_coarse_power_curve = 20  # (Int): number of points to evaluate aero analysis at
        npts_spline_power_curve = 200  # (Int): number of points to use in fitting spline to power curve

        rotor.root = RotorSE(myref, npts_coarse_power_curve,
                             npts_spline_power_curve)
        rotor.setup()

        # ---
        # === blade grid ===
        rotor[
            'hubFraction'] = myref.hubFraction  #0.023785  # (Float): hub location as fraction of radius
        rotor[
            'bladeLength'] = myref.bladeLength  #96.7  # (Float, m): blade length (if not precurved or swept) otherwise length of blade before curvature
        rotor['precone'] = myref.precone  #4.  # (Float, deg): precone angle
        rotor['tilt'] = myref.tilt  #6.0  # (Float, deg): shaft tilt
        rotor['yaw'] = 0.0  # (Float, deg): yaw error
        rotor['nBlades'] = myref.nBlades  #3  # (Int): number of blades
        # ---

        # === blade geometry ===
        rotor[
            'r_max_chord'] = myref.r_max_chord  # 0.2366 #(Float): location of max chord on unit radius
        rotor[
            'chord_in'] = myref.chord  # np.array([4.6, 4.869795, 5.990629, 3.00785428, 0.0962])  # (Array, m): chord at control points. defined at hub, then at linearly spaced locations from r_max_chord to tip
        rotor[
            'theta_in'] = myref.theta  # np.array([14.5, 12.874, 6.724, -0.03388039, -0.037]) # (Array, deg): twist at control points.  defined at linearly spaced locations from r[idx_cylinder] to tip
        rotor[
            'precurve_in'] = myref.precurve  #np.array([-0., -0.054497, -0.175303, -0.84976143, -6.206217])  # (Array, m): precurve at control points.  defined at same locations at chord, starting at 2nd control point (root must be zero precurve)
        rotor[
            'presweep_in'] = myref.presweep  #np.array([0., 0., 0., 0., 0.])  # (Array, m): precurve at control points.  defined at same locations at chord, starting at 2nd control point (root must be zero precurve)
        rotor[
            'sparT_in'] = myref.spar_thickness  # np.array([0.03200042 0.07038508 0.08515644 0.07777004 0.01181032])  # (Array, m): spar cap thickness parameters
        rotor[
            'teT_in'] = myref.te_thickness  # np.array([0.04200055 0.08807739 0.05437378 0.01610219 0.00345225])  # (Array, m): trailing-edge thickness parameters
        # ---

        # === atmosphere ===
        rotor['analysis.rho'] = 1.225  # (Float, kg/m**3): density of air
        rotor[
            'analysis.mu'] = 1.81206e-5  # (Float, kg/m/s): dynamic viscosity of air
        rotor['wind.shearExp'] = 0.25  # (Float): shear exponent
        rotor[
            'hub_height'] = myref.hub_height  #119.0  # (Float, m): hub height
        rotor[
            'turbine_class'] = myref.turbine_class  #TURBINE_CLASS['I']  # (Enum): IEC turbine class
        rotor['turbulence_class'] = TURBULENCE_CLASS[
            'B']  # (Enum): IEC turbulence class class
        rotor[
            'wind.zref'] = myref.hub_height  #119.0  # (Float): reference hub height for IEC wind speed (used in CDF calculation)
        rotor['gust_stddev'] = 3
        # ---

        # === control ===
        rotor[
            'control_Vin'] = myref.control_Vin  #4.0  # (Float, m/s): cut-in wind speed
        rotor[
            'control_Vout'] = myref.control_Vout  #25.0  # (Float, m/s): cut-out wind speed
        rotor[
            'control_minOmega'] = myref.control_minOmega  #6.0  # (Float, rpm): minimum allowed rotor rotation speed
        rotor[
            'control_maxOmega'] = myref.control_maxOmega  #8.88766  # (Float, rpm): maximum allowed rotor rotation speed
        rotor[
            'control_tsr'] = myref.control_tsr  #10.58  # (Float): tip-speed ratio in Region 2 (should be optimized externally)
        rotor[
            'control_pitch'] = myref.control_pitch  #0.0  # (Float, deg): pitch angle in region 2 (and region 3 for fixed pitch machines)
        rotor[
            'machine_rating'] = myref.rating  #10e6  # (Float, W): rated power
        rotor[
            'pitch_extreme'] = 0.0  # (Float, deg): worst-case pitch at survival wind condition
        rotor[
            'azimuth_extreme'] = 0.0  # (Float, deg): worst-case azimuth at survival wind condition
        rotor[
            'VfactorPC'] = 0.7  # (Float): fraction of rated speed at which the deflection is assumed to representative throughout the power curve calculation
        # ---

        # === aero and structural analysis options ===
        rotor[
            'nSector'] = 4  # (Int): number of sectors to divide rotor face into in computing thrust and power
        rotor[
            'AEP_loss_factor'] = 1.0  # (Float): availability and other losses (soiling, array, etc.)
        rotor[
            'drivetrainType'] = myref.drivetrain  #DRIVETRAIN_TYPE['GEARED']  # (Enum)
        rotor[
            'dynamic_amplication_tip_deflection'] = 1.35  # (Float): a dynamic amplification factor to adjust the static deflection calculation
        # ---

        # === fatigue ===
        r_aero = np.array([
            0.02222276, 0.06666667, 0.11111057, 0.2, 0.23333333, 0.3,
            0.36666667, 0.43333333, 0.5, 0.56666667, 0.63333333, 0.64, 0.7,
            0.83333333, 0.88888943, 0.93333333, 0.97777724
        ])  # (Array): new aerodynamic grid on unit radius
        rstar_damage = np.array(
            [
                0.000, 0.022, 0.067, 0.111, 0.167, 0.233, 0.300, 0.367, 0.433,
                0.500, 0.567, 0.633, 0.700, 0.767, 0.833, 0.889, 0.933, 0.978
            ]
        )  # (Array): nondimensional radial locations of damage equivalent moments
        Mxb_damage = 1e3 * np.array([
            2.3743E+003, 2.0834E+003, 1.8108E+003, 1.5705E+003, 1.3104E+003,
            1.0488E+003, 8.2367E+002, 6.3407E+002, 4.7727E+002, 3.4804E+002,
            2.4458E+002, 1.6339E+002, 1.0252E+002, 5.7842E+001, 2.7349E+001,
            1.1262E+001, 3.8549E+000, 4.4738E-001
        ])  # (Array, N*m): damage equivalent moments about blade c.s. x-direction
        Myb_damage = 1e3 * np.array([
            2.7732E+003, 2.8155E+003, 2.6004E+003, 2.3933E+003, 2.1371E+003,
            1.8459E+003, 1.5582E+003, 1.2896E+003, 1.0427E+003, 8.2015E+002,
            6.2449E+002, 4.5229E+002, 3.0658E+002, 1.8746E+002, 9.6475E+001,
            4.2677E+001, 1.5409E+001, 1.8426E+000
        ])  # (Array, N*m): damage equivalent moments about blade c.s. y-direction
        xp = np.r_[0.0, r_aero]
        xx = np.r_[0.0, myref.r]
        rotor['rstar_damage'] = np.interp(xx, xp, rstar_damage)
        rotor['Mxb_damage'] = np.interp(xx, xp, Mxb_damage)
        rotor['Myb_damage'] = np.interp(xx, xp, Myb_damage)
        rotor[
            'strain_ult_spar'] = 1.0e-2  # (Float): ultimate strain in spar cap
        rotor[
            'strain_ult_te'] = 2500 * 1e-6 * 2  # (Float): uptimate strain in trailing-edge panels, note that I am putting a factor of two for the damage part only.
        rotor['gamma_fatigue'] = 1.755  # (Float): safety factor for fatigue
        rotor['gamma_f'] = 1.35  # (Float): safety factor for loads/stresses
        rotor['gamma_m'] = 1.1  # (Float): safety factor for materials
        rotor[
            'gamma_freq'] = 1.1  # (Float): safety factor for resonant frequencies
        rotor[
            'm_damage'] = 10.0  # (Float): slope of S-N curve for fatigue analysis
        rotor[
            'struc.lifetime'] = 20.0  # (Float): number of cycles used in fatigue analysis  TODO: make function of rotation speed
        # ----------------

        # === run and outputs ===
        rotor.run()

        print 'AEP =', rotor['AEP']
        print 'diameter =', rotor['diameter']
        print 'rated_V =', rotor['rated_V']
        print 'rated_Omega =', rotor['rated_Omega']
        print 'rated_pitch =', rotor['rated_pitch']
        print 'rated_T =', rotor['rated_T']
        print 'rated_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']
        print 'tip_deflection =', rotor['tip_deflection']
        print 'root_bending_moment =', rotor['root_bending_moment']

        outpath = '..\..\..\docs\images'
        import matplotlib.pyplot as plt
        plt.figure()
        plt.plot(rotor['V'], rotor['P'] / 1e6)
        plt.xlabel('wind speed (m/s)')
        plt.xlabel('power (W)')

        plt.figure()

        plt.plot(rotor['r_pts'], rotor['strainU_spar'], label='suction')
        plt.plot(rotor['r_pts'], rotor['strainL_spar'], label='pressure')
        plt.plot(rotor['r_pts'], rotor['eps_crit_spar'], label='critical')
        # plt.ylim([-6e-3, 6e-3])
        plt.xlabel('r')
        plt.ylabel('strain')
        plt.legend()
        plt.savefig(
            os.path.abspath(os.path.join(outpath, 'strain_spar_dtu10mw.png')))
        plt.savefig(
            os.path.abspath(os.path.join(outpath, 'strain_spar_dtu10mw.pdf')))

        plt.figure()

        plt.plot(rotor['r_pts'], rotor['strainU_te'], label='suction')
        plt.plot(rotor['r_pts'], rotor['strainL_te'], label='pressure')
        plt.plot(rotor['r_pts'], rotor['eps_crit_te'], label='critical')
        # plt.ylim([-5e-3, 5e-3])
        plt.xlabel('r')
        plt.ylabel('strain')
        plt.legend()
        plt.savefig(
            os.path.abspath(os.path.join(outpath, 'strain_te_dtu10mw.png')))
        plt.savefig(
            os.path.abspath(os.path.join(outpath, 'strain_te_dtu10mw.pdf')))

        plt.show()
示例#5
0
from fusedwind.interface import implement_base
from commonse.UtilizationSupplement import fatigue, hoopStressEurocode, shellBucklingEurocode, \
    bucklingGL, vonMisesStressUtilization

import matplotlib.pyplot as plt

import frame3dd

################################################################################
### 1. Aerodynamic and structural performance using RotorSE

BladeLength = 34
HubHeight = 65

ReferenceBladeLength = 68
rotor = RotorSE()
# -------------------

# === blade grid ===
# (Array): initial aerodynamic grid on unit radius
rotor.initial_aero_grid = np.array([0.02222276, 0.06666667, 0.11111057, \
 0.16666667, 0.23333333, 0.3, 0.36666667, 0.43333333, 0.5, 0.56666667, \
 0.63333333, 0.7, 0.76666667, 0.83333333, 0.88888943, 0.93333333, \
    0.97777724])

# (Array): initial structural grid on unit radius
rotor.initial_str_grid = np.array([
    0.0, 0.00492790457512, 0.00652942887106, 0.00813095316699,
    0.00983257273154, 0.0114340970275, 0.0130356213234, 0.02222276,
    0.024446481932, 0.026048006228, 0.06666667, 0.089508406455, 0.11111057,
    0.146462614229, 0.16666667, 0.195309105255, 0.23333333, 0.276686558545,
def EvaluateLCOE(BladeLength, HubHeight, MaximumRotSpeed,Verbose=False):

	############################################################################
	# Define baseline paremeters used for scaling
	ReferenceBladeLength = 35;
	ReferenceTowerHeight = 95
	WindReferenceHeight = 50
	WindReferenceMeanVelocity = 3
	WeibullShapeFactor = 2.0
	ShearFactor = 0.25

	RatedPower = 1.5e6

	# Years used for analysis
	Years = 25
	DiscountRate = 0.08
	############################################################################


	############################################################################
	### 1. Aerodynamic and structural performance using RotorSE
	rotor = RotorSE()
	# -------------------

	# === blade grid ===
	# (Array): initial aerodynamic grid on unit radius
	rotor.initial_aero_grid = np.array([0.02222276, 0.06666667, 0.11111057, \
		0.16666667, 0.23333333, 0.3, 0.36666667, 0.43333333, 0.5, 0.56666667, \
		0.63333333, 0.7, 0.76666667, 0.83333333, 0.88888943, 0.93333333, \
	    0.97777724]) 

	 # (Array): initial structural grid on unit radius
	rotor.initial_str_grid = np.array([0.0, 0.00492790457512, 0.00652942887106, 
		0.00813095316699, 0.00983257273154, 0.0114340970275, 0.0130356213234, 
		0.02222276, 0.024446481932, 0.026048006228, 0.06666667, 0.089508406455,
	    0.11111057, 0.146462614229, 0.16666667, 0.195309105255, 0.23333333, 
	    0.276686558545, 0.3, 0.333640766319,0.36666667, 0.400404310407, 0.43333333, 
	    0.5, 0.520818918408, 0.56666667, 0.602196371696, 0.63333333,
	    0.667358391486, 0.683573824984, 0.7, 0.73242031601, 0.76666667, 0.83333333, 
	    0.88888943, 0.93333333, 0.97777724, 1.0]) 

	# (Int): first idx in r_aero_unit of non-cylindrical section, 
	# constant twist inboard of here
	rotor.idx_cylinder_aero = 3  

	# (Int): first idx in r_str_unit of non-cylindrical section
	rotor.idx_cylinder_str = 14  

	# (Float): hub location as fraction of radius
	rotor.hubFraction = 0.025  
	# ------------------

	# === blade geometry ===
	# (Array): new aerodynamic grid on unit radius
	rotor.r_aero = np.array([0.02222276, 0.06666667, 0.11111057, 0.2, 0.23333333, 
		0.3, 0.36666667, 0.43333333, 0.5, 0.56666667, 0.63333333, 0.64, 0.7, 
		0.83333333, 0.88888943, 0.93333333, 0.97777724])  

	# (Float): location of max chord on unit radius
	rotor.r_max_chord = 0.23577

	# (Array, m): chord at control points. defined at hub, then at linearly spaced
	# locations from r_max_chord to tip
	ReferenceChord = [3.2612, 4.5709, 3.3178, 1.4621]
	rotor.chord_sub = [x * np.true_divide(BladeLength,ReferenceBladeLength) \
		for x in ReferenceChord]

	# (Array, deg): twist at control points.  defined at linearly spaced locations 
	# from r[idx_cylinder] to tip
	rotor.theta_sub = [13.2783, 7.46036, 2.89317, -0.0878099]  

	# (Array, m): precurve at control points.  defined at same locations at chord, 
	# starting at 2nd control point (root must be zero precurve)
	rotor.precurve_sub = [0.0, 0.0, 0.0] 

	# (Array, m): adjustment to precurve to account for curvature from loading
	rotor.delta_precurve_sub = [0.0, 0.0, 0.0]  

	# (Array, m): spar cap thickness parameters
	rotor.sparT = [0.05, 0.047754, 0.045376, 0.031085, 0.0061398] 

	# (Array, m): trailing-edge thickness parameters
	rotor.teT = [0.1, 0.09569, 0.06569, 0.02569, 0.00569]  

	# (Float, m): blade length (if not precurved or swept) 
	# otherwise length of blade before curvature
	rotor.bladeLength = BladeLength  

	# (Float, m): adjustment to blade length to account for curvature from 
	# loading
	rotor.delta_bladeLength = 0.0  
	rotor.precone = 2.5  # (Float, deg): precone angle
	rotor.tilt = 5.0  # (Float, deg): shaft tilt
	rotor.yaw = 0.0  # (Float, deg): yaw error
	rotor.nBlades = 3  # (Int): number of blades
	# ------------------

	# === airfoil files ===
	basepath = os.path.join(os.path.dirname(\
		os.path.realpath(__file__)), '5MW_AFFiles')

	# load all airfoils
	airfoil_types = [0]*8
	airfoil_types[0] = os.path.join(basepath, 'Cylinder1.dat')
	airfoil_types[1] = os.path.join(basepath, 'Cylinder2.dat')
	airfoil_types[2] = os.path.join(basepath, 'DU40_A17.dat')
	airfoil_types[3] = os.path.join(basepath, 'DU35_A17.dat')
	airfoil_types[4] = os.path.join(basepath, 'DU30_A17.dat')
	airfoil_types[5] = os.path.join(basepath, 'DU25_A17.dat')
	airfoil_types[6] = os.path.join(basepath, 'DU21_A17.dat')
	airfoil_types[7] = os.path.join(basepath, 'NACA64_A17.dat')

	# place at appropriate radial stations
	af_idx = [0, 0, 1, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7]

	n = len(af_idx)
	af = [0]*n
	for i in range(n):
	    af[i] = airfoil_types[af_idx[i]]
	rotor.airfoil_files = af  # (List): names of airfoil file
	# ----------------------

	# === atmosphere ===
	rotor.rho = 1.225  # (Float, kg/m**3): density of air
	rotor.mu = 1.81206e-5  # (Float, kg/m/s): dynamic viscosity of air
	rotor.shearExp = 0.25  # (Float): shear exponent
	rotor.hubHt = HubHeight  # (Float, m): hub height
	rotor.turbine_class = 'I'  # (Enum): IEC turbine class
	rotor.turbulence_class = 'B'  # (Enum): IEC turbulence class class
	rotor.cdf_reference_height_wind_speed = 30.0 
	rotor.g = 9.81  # (Float, m/s**2): acceleration of gravity
	# ----------------------

	# === control ===
	rotor.control.Vin = 3.0  # (Float, m/s): cut-in wind speed
	rotor.control.Vout = 26.0  # (Float, m/s): cut-out wind speed
	rotor.control.ratedPower = RatedPower  # (Float, W): rated power
	
	# (Float, rpm): minimum allowed rotor rotation speed

	# (Float, rpm): maximum allowed rotor rotation speed
	rotor.control.minOmega = 0.0  
	rotor.control.maxOmega = MaximumRotSpeed

	# (Float): tip-speed ratio in Region 2 (should be optimized externally)
	rotor.control.tsr = 7
	# (Float, deg): pitch angle in region 2 (and region 3 for fixed pitch machines)
	rotor.control.pitch = 0.0  
	# (Float, deg): worst-case pitch at survival wind condition
	rotor.pitch_extreme = 0.0  

	# (Float, deg): worst-case azimuth at survival wind condition
	rotor.azimuth_extreme = 0.0  

	# (Float): fraction of rated speed at which the deflection is assumed to 
	# representative throughout the power curve calculation
	rotor.VfactorPC = 0.7  
	# ----------------------

	# === aero and structural analysis options ===

	# (Int): number of sectors to divide rotor face into in computing thrust and power
	rotor.nSector = 4 

	# (Int): number of points to evaluate aero analysis at
	rotor.npts_coarse_power_curve = 20  

	# (Int): number of points to use in fitting spline to power curve
	rotor.npts_spline_power_curve = 200  

	# (Float): availability and other losses (soiling, array, etc.)
	rotor.AEP_loss_factor = 1.0 
	rotor.drivetrainType = 'geared'  # (Enum)

	# (Int): number of natural frequencies to compute
	rotor.nF = 5 

	# (Float): a dynamic amplification factor to adjust the static deflection 
	# calculation
	rotor.dynamic_amplication_tip_deflection = 1.35 
	# ----------------------

	# === materials and composite layup  ===
	basepath = os.path.join(os.path.dirname(os.path.realpath(__file__)), \
		'5MW_PrecompFiles')

	materials = Orthotropic2DMaterial.listFromPreCompFile(os.path.join(basepath,\
	 'materials.inp'))

	ncomp = len(rotor.initial_str_grid)
	upper = [0]*ncomp
	lower = [0]*ncomp
	webs = [0]*ncomp
	profile = [0]*ncomp

	# (Array): array of leading-edge positions from a reference blade axis 
	# (usually blade pitch axis). locations are normalized by the local chord 
	# length. e.g. leLoc[i] = 0.2 means leading edge is 0.2*chord[i] from reference 
	# axis.  positive in -x direction for airfoil-aligned coordinate system
	rotor.leLoc = np.array([0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.498, 0.497, 
		0.465, 0.447, 0.43, 0.411, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 
		0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4])  

	# (Array): index of sector for spar (PreComp definition of sector)
	rotor.sector_idx_strain_spar = [2]*ncomp  

	# (Array): index of sector for trailing-edge (PreComp definition of sector)
	rotor.sector_idx_strain_te = [3]*ncomp  

	web1 = np.array([-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 0.4114, 0.4102, 
		0.4094, 0.3876, 0.3755, 0.3639, 0.345, 0.3342, 0.3313, 0.3274, 0.323, 
		0.3206, 0.3172, 0.3138, 0.3104, 0.307, 0.3003, 0.2982, 0.2935, 0.2899, 
		0.2867, 0.2833, 0.2817, 0.2799, 0.2767, 0.2731, 0.2664, 0.2607, 0.2562, 
		0.1886, -1.0])

	web2 = np.array([-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 0.5886, 0.5868, 
		0.5854, 0.5508, 0.5315, 0.5131, 0.4831, 0.4658, 0.4687, 0.4726, 0.477, 
		0.4794, 0.4828, 0.4862, 0.4896, 0.493, 0.4997, 0.5018, 0.5065, 0.5101, 
		0.5133, 0.5167, 0.5183, 0.5201, 0.5233, 0.5269, 0.5336, 0.5393, 0.5438, 
		0.6114, -1.0])
	web3 = np.array([-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 
		-1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 
		1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 
		-1.0, -1.0])

	# (Array, m): chord distribution for reference section, thickness of structural 
	# layup scaled with reference thickness (fixed t/c for this case)
	rotor.chord_str_ref = np.array([3.2612, 3.3100915356, 3.32587052924, 
		3.34159388653, 3.35823798667, 3.37384375335, 3.38939112914, 3.4774055542, 
		3.49839685, 3.51343645709, 3.87017220335, 4.04645623801, 4.19408216643,
	    4.47641008477, 4.55844487985, 4.57383098262, 4.57285771934, 4.51914315648, 
	    4.47677655262, 4.40075650022, 4.31069949379, 4.20483735936, 4.08985563932, 
	    3.82931757126, 3.74220276467, 3.54415796922, 3.38732428502, 3.24931446473, 
	    3.23421422609, 3.22701537997, 3.21972125648, 3.08979310611, 2.95152261813, 
	    2.330753331, 2.05553464181, 1.82577817774, 1.5860853279, 1.4621])* \
		np.true_divide(BladeLength,ReferenceBladeLength)


	for i in range(ncomp):
	    webLoc = []
	    if web1[i] != -1:
	        webLoc.append(web1[i])
	    if web2[i] != -1:
	        webLoc.append(web2[i])
	    if web3[i] != -1:
	        webLoc.append(web3[i])

	    upper[i], lower[i], webs[i] = CompositeSection.initFromPreCompLayupFile\
	    (os.path.join(basepath, 'layup_' + str(i+1) + '.inp'), webLoc, materials)
	    profile[i] = Profile.initFromPreCompFile(os.path.join(basepath, 'shape_' \
	    	+ str(i+1) + '.inp'))

	# (List): list of all Orthotropic2DMaterial objects used in 
	# defining the geometry
	rotor.materials = materials 

	# (List): list of CompositeSection objections defining the properties for 
	# upper surface
	rotor.upperCS = upper  

	# (List): list of CompositeSection objections defining the properties for 
	# lower surface
	rotor.lowerCS = lower  

	# (List): list of CompositeSection objections defining the properties for 
	# shear webs
	rotor.websCS = webs  

	# (List): airfoil shape at each radial position
	rotor.profile = profile  
	# --------------------------------------


	# === fatigue ===

	# (Array): nondimensional radial locations of damage equivalent moments
	rotor.rstar_damage = np.array([0.000, 0.022, 0.067, 0.111, 0.167, 0.233, 0.300,
	 0.367, 0.433, 0.500, 0.567, 0.633, 0.700, 0.767, 0.833, 0.889, 0.933, 0.978]) 


	# (Array, N*m): damage equivalent moments about blade c.s. x-direction
	rotor.Mxb_damage = 1e3*np.array([2.3743E+003, 2.0834E+003, 1.8108E+003, 
		1.5705E+003, 1.3104E+003, 1.0488E+003, 8.2367E+002, 6.3407E+002, 
		4.7727E+002, 3.4804E+002, 2.4458E+002, 1.6339E+002, 1.0252E+002,
		 5.7842E+001, 2.7349E+001, 1.1262E+001, 3.8549E+000, 4.4738E-001])  

	# (Array, N*m): damage equivalent moments about blade c.s. y-direction
	rotor.Myb_damage = 1e3*np.array([2.7732E+003, 2.8155E+003, 2.6004E+003, 
		2.3933E+003, 2.1371E+003, 1.8459E+003, 1.5582E+003, 1.2896E+003, 
		1.0427E+003, 8.2015E+002, 6.2449E+002, 4.5229E+002, 3.0658E+002, 
		1.8746E+002, 9.6475E+001, 4.2677E+001, 1.5409E+001, 1.8426E+000])  

	rotor.strain_ult_spar = 1.0e-2  # (Float): ultimate strain in spar cap

	# (Float): uptimate strain in trailing-edge panels, note that I am putting a 
	# factor of two for the damage part only.
	rotor.strain_ult_te = 2500*1e-6 * 2  
	rotor.eta_damage = 1.35*1.3*1.0  # (Float): safety factor for fatigue
	rotor.m_damage = 10.0  # (Float): slope of S-N curve for fatigue analysis

	# (Float): number of cycles used in fatigue analysis  
	rotor.N_damage = 365*24*3600*20.0  
	# ----------------

	# from myutilities import plt

	# === run and outputs ===
	rotor.run()

	# Evaluate AEP Using Lewis' Functions
	# Weibull Wind Parameters
	WindReferenceHeight = 50
	WindReferenceMeanVelocity = 7.5
	WeibullShapeFactor = 2.0
	ShearFactor = 0.25

	PowerCurve = rotor.P/1e6
	PowerCurveVelocity = rotor.V

	HubHeight = rotor.hubHt

	AEP,WeibullScale = CalculateAEPWeibull(PowerCurve,PowerCurveVelocity, HubHeight, \
	  	BladeLength,WeibullShapeFactor, WindReferenceHeight, \
	  	WindReferenceMeanVelocity, ShearFactor)

	NamePlateCapacity = EstimateCapacity(PowerCurve,PowerCurveVelocity, \
		rotor.ratedConditions.V)

	# AEP At Constant 7.5m/s Wind used for benchmarking...
	#AEP = CalculateAEPConstantWind(PowerCurve, PowerCurveVelocity, 7.5)

	if (Verbose ==True):
		print '###################     ROTORSE   ######################'
		print 'AEP = %d MWH' %(AEP)
		print 'NamePlateCapacity = %fMW' %(NamePlateCapacity)
		print 'diameter =', rotor.diameter
		print 'ratedConditions.V =', rotor.ratedConditions.V
		print 'ratedConditions.Omega =', rotor.ratedConditions.Omega
		print 'ratedConditions.pitch =', rotor.ratedConditions.pitch
		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
		print 'tip_deflection =', rotor.tip_deflection
		print 'root_bending_moment =', rotor.root_bending_moment
		print '#########################################################'

	#############################################################################
	### 2. Hub Sizing 
	# Specify hub parameters based off rotor

	# Load default hub model
	hubS = HubSE()
	hubS.rotor_diameter = rotor.Rtip*2 # m
	hubS.blade_number  = rotor.nBlades
	hubS.blade_root_diameter = rotor.chord_sub[0]*1.25
	hubS.L_rb = rotor.hubFraction*rotor.diameter
	hubS.MB1_location = np.array([-0.5, 0.0, 0.0])
	hubS.machine_rating = rotor.control.ratedPower
	hubS.blade_mass = rotor.mass_one_blade
	hubS.rotor_bending_moment = rotor.root_bending_moment

	hubS.run()

	RotorTotalWeight = rotor.mass_all_blades + hubS.spinner.mass + \
	hubS.hub.mass + hubS.pitchSystem.mass

	if (Verbose==True):
		print '##################### Hub SE ############################'
		print "Estimate of Hub Component Sizes:"
		print "Hub Components"
		print '  Hub: {0:8.1f} kg'.format(hubS.hub.mass)
		print '  Pitch system: {0:8.1f} kg'.format(hubS.pitchSystem.mass) 
		print '  Nose cone: {0:8.1f} kg'.format(hubS.spinner.mass)
		print 'Rotor Total Weight = %d kg' %RotorTotalWeight
		print '#########################################################'


	############################################################################
	### 3. Drive train + Nacelle Mass estimation
	nace = Drive4pt()
	nace.rotor_diameter = rotor.Rtip *2 # m
	nace.rotor_speed = rotor.ratedConditions.Omega # #rpm m/s
	nace.machine_rating = hubS.machine_rating/1000
	nace.DrivetrainEfficiency = 0.95

	 # 6.35e6 #4365248.74 # Nm
	nace.rotor_torque =  rotor.ratedConditions.Q
	nace.rotor_thrust = rotor.ratedConditions.T # N
	nace.rotor_mass = 0.0 #accounted for in F_z # kg

	nace.rotor_bending_moment_x = rotor.Mxyz_0[0]
	nace.rotor_bending_moment_y = rotor.Mxyz_0[1]
	nace.rotor_bending_moment_z = rotor.Mxyz_0[2]

	nace.rotor_force_x = rotor.Fxyz_0[0] # N
	nace.rotor_force_y = rotor.Fxyz_0[1]
	nace.rotor_force_z = rotor.Fxyz_0[2] # N

	# geared 3-stage Gearbox with induction generator machine
	nace.drivetrain_design = 'geared' 
	nace.gear_ratio = 96.76 # 97:1 as listed in the 5 MW reference document
	nace.gear_configuration = 'eep' # epicyclic-epicyclic-parallel

	nace.crane = True # onboard crane present
	nace.shaft_angle = 5.0 #deg
	nace.shaft_ratio = 0.10
	nace.Np = [3,3,1]
	nace.ratio_type = 'optimal'
	nace.shaft_type = 'normal'
	nace.uptower_transformer=False
	nace.shrink_disc_mass = 333.3*nace.machine_rating/1000.0 # estimated
	nace.mb1Type = 'CARB'
	nace.mb2Type = 'SRB'
	nace.flange_length = 0.5 #m
	nace.overhang = 5.0
	nace.gearbox_cm = 0.1
	nace.hss_length = 1.5

	#0 if no fatigue check, 1 if parameterized fatigue check, 
	#2 if known loads inputs
	nace.check_fatigue = 0 
	nace.blade_number=rotor.nBlades
	nace.cut_in=rotor.control.Vin #cut-in m/s
	nace.cut_out=rotor.control.Vout #cut-out m/s
	nace.Vrated=rotor.ratedConditions.V #rated windspeed m/s
	nace.weibull_k = WeibullShapeFactor # windepeed distribution shape parameter

	# windspeed distribution scale parameter
	nace.weibull_A = WeibullScale  

	nace.T_life=20. #design life in years
	nace.IEC_Class_Letter = 'B'

	# length from hub center to main bearing, leave zero if unknown
	nace.L_rb = hubS.L_rb 

	# NREL 5 MW Tower Variables
	nace.tower_top_diameter = 3.78 # m

	nace.run()

	if (Verbose==True):
		print '##################### Drive SE ############################'
		print "Estimate of Nacelle Component Sizes"
		print 'Low speed shaft: {0:8.1f} kg'.format(nace.lowSpeedShaft.mass)
		print 'Main bearings: {0:8.1f} kg'.format(\
			nace.mainBearing.mass + nace.secondBearing.mass)
		print 'Gearbox: {0:8.1f} kg'.format(nace.gearbox.mass)
		print 'High speed shaft & brakes: {0:8.1f} kg'.format\
			(nace.highSpeedSide.mass)
		print 'Generator: {0:8.1f} kg'.format(nace.generator.mass)
		print 'Variable speed electronics: {0:8.1f} kg'.format(\
			nace.above_yaw_massAdder.vs_electronics_mass)
		print 'Overall mainframe:{0:8.1f} kg'.format(\
			nace.above_yaw_massAdder.mainframe_mass)
		print '     Bedplate: {0:8.1f} kg'.format(nace.bedplate.mass)
		print 'Electrical connections: {0:8.1f} kg'.format(\
			nace.above_yaw_massAdder.electrical_mass)
		print 'HVAC system: {0:8.1f} kg'.format(\
			nace.above_yaw_massAdder.hvac_mass )
		print 'Nacelle cover: {0:8.1f} kg'.format(\
			nace.above_yaw_massAdder.cover_mass)
		print 'Yaw system: {0:8.1f} kg'.format(nace.yawSystem.mass)
		print 'Overall nacelle: {0:8.1f} kg'.format(nace.nacelle_mass, \
			nace.nacelle_cm[0], nace.nacelle_cm[1], nace.nacelle_cm[2], \
			nace.nacelle_I[0], nace.nacelle_I[1], nace.nacelle_I[2])  
		print '#########################################################'


	############################################################################
	### 4. Tower Mass

	# --- tower setup ------
	from commonse.environment import PowerWind

	tower = set_as_top(TowerSE())

	# ---- tower ------
	tower.replace('wind1', PowerWind())
	tower.replace('wind2', PowerWind())
	# onshore (no waves)

	# --- geometry ----
	tower.z_param = [0.0, HubHeight*0.5, HubHeight]
	TowerRatio = np.true_divide(HubHeight,ReferenceTowerHeight)

	tower.d_param = [6.0*TowerRatio, 4.935*TowerRatio, 3.87*TowerRatio]
	tower.t_param = [0.027*1.3*TowerRatio, 0.023*1.3*TowerRatio, \
	0.019*1.3*TowerRatio]
	n = 10

	tower.z_full = np.linspace(0.0, HubHeight, n)
	tower.L_reinforced = 15.0*np.ones(n)  # [m] buckling length
	tower.theta_stress = 0.0*np.ones(n)
	tower.yaw = 0.0

	# --- material props ---
	tower.E = 210e9*np.ones(n)
	tower.G = 80.8e9*np.ones(n)
	tower.rho = 8500.0*np.ones(n)
	tower.sigma_y = 450.0e6*np.ones(n)

	# --- spring reaction data.  Use float('inf') for rigid constraints. ---
	tower.kidx = [0]  # applied at base
	tower.kx = [float('inf')]
	tower.ky = [float('inf')]
	tower.kz = [float('inf')]
	tower.ktx = [float('inf')]
	tower.kty = [float('inf')]
	tower.ktz = [float('inf')]

	# --- extra mass ----
	tower.midx = [n-1]  # RNA mass at top
	tower.m = [0.8]
	tower.mIxx = [1.14930678e+08]
	tower.mIyy = [2.20354030e+07]
	tower.mIzz = [1.87597425e+07]
	tower.mIxy = [0.00000000e+00]
	tower.mIxz = [5.03710467e+05]
	tower.mIyz = [0.00000000e+00]
	tower.mrhox = [-1.13197635]
	tower.mrhoy = [0.]
	tower.mrhoz = [0.50875268]
	tower.addGravityLoadForExtraMass = False
	# -----------

	# --- wind ---
	tower.wind_zref = 90.0
	tower.wind_z0 = 0.0
	tower.wind1.shearExp = 0.14
	tower.wind2.shearExp = 0.14
	# ---------------

	# # --- loading case 1: max Thrust ---
	tower.wind_Uref1 = 11.73732
	tower.plidx1 = [n-1]  # at tower top
	tower.Fx1 = [0.19620519]
	tower.Fy1 = [0.]
	tower.Fz1 = [-2914124.84400512]
	tower.Mxx1 = [3963732.76208099]
	tower.Myy1 = [-2275104.79420872]
	tower.Mzz1 = [-346781.68192839]
	# # ---------------

	# # --- loading case 2: max wind speed ---
	tower.wind_Uref2 = 70.0
	tower.plidx1 = [n-1]  # at tower top
	tower.Fx1 = [930198.60063279]
	tower.Fy1 = [0.]
	tower.Fz1 = [-2883106.12368949]
	tower.Mxx1 = [-1683669.22411597]
	tower.Myy1 = [-2522475.34625363]
	tower.Mzz1 = [147301.97023764]
	# # ---------------

	# # --- run ---
	tower.run()

	if (Verbose==True):
		print '##################### Tower SE ##########################'
		print 'mass (kg) =', tower.mass
		print 'f1 (Hz) =', tower.f1
		print 'f2 (Hz) =', tower.f2
		print 'top_deflection1 (m) =', tower.top_deflection1
		print 'top_deflection2 (m) =', tower.top_deflection2
		print '#########################################################'


	############################################################################
	## 5. Turbine captial costs analysis
	turbine = Turbine_CostsSE()

	# NREL 5 MW turbine component masses based on Sunderland model approach
	# Rotor
	# inline with the windpact estimates
	turbine.blade_mass = rotor.mass_one_blade  
	turbine.hub_mass = hubS.hub.mass
	turbine.pitch_system_mass = hubS.pitchSystem.mass
	turbine.spinner_mass = hubS.spinner.mass

	# Drivetrain and Nacelle
	turbine.low_speed_shaft_mass = nace.lowSpeedShaft.mass
	turbine.main_bearing_mass=nace.mainBearing.mass 
	turbine.second_bearing_mass = nace.secondBearing.mass
	turbine.gearbox_mass = nace.gearbox.mass
	turbine.high_speed_side_mass = nace.highSpeedSide.mass
	turbine.generator_mass = nace.generator.mass
	turbine.bedplate_mass = nace.bedplate.mass
	turbine.yaw_system_mass = nace.yawSystem.mass

	# Tower
	turbine.tower_mass = tower.mass*0.5

	# Additional non-mass cost model input variables
	turbine.machine_rating = hubS.machine_rating/1000
	turbine.advanced = False
	turbine.blade_number = rotor.nBlades
	turbine.drivetrain_design = 'geared'
	turbine.crane = False
	turbine.offshore = False

	# Target year for analysis results
	turbine.year = 2010
	turbine.month =  12

	turbine.run()

	if (Verbose==True):
		print '##################### TurbinePrice SE ####################'
		print "Overall rotor cost with 3 advanced blades is ${0:.2f} USD"\
			.format(turbine.rotorCC.cost)
		print "Blade cost is ${0:.2f} USD".format(turbine.rotorCC.bladeCC.cost)
		print "Hub cost is ${0:.2f} USD".format(turbine.rotorCC.hubCC.cost)
		print "Pitch system cost is ${0:.2f} USD".format(turbine.rotorCC.pitchSysCC.cost)
		print "Spinner cost is ${0:.2f} USD".format(turbine.rotorCC.spinnerCC.cost)
		print
		print "Overall nacelle cost is ${0:.2f} USD".format(turbine.nacelleCC.cost)
		print "LSS cost is ${0:.2f} USD".format(turbine.nacelleCC.lssCC.cost)
		print "Main bearings cost is ${0:.2f} USD".format(turbine.nacelleCC.bearingsCC.cost)
		print "Gearbox cost is ${0:.2f} USD".format(turbine.nacelleCC.gearboxCC.cost)
		print "Hight speed side cost is ${0:.2f} USD".format(turbine.nacelleCC.hssCC.cost)
		print "Generator cost is ${0:.2f} USD".format(turbine.nacelleCC.generatorCC.cost)
		print "Bedplate cost is ${0:.2f} USD".format(turbine.nacelleCC.bedplateCC.cost)
		print "Yaw system cost is ${0:.2f} USD".format(turbine.nacelleCC.yawSysCC.cost)
		print
		print "Tower cost is ${0:.2f} USD".format(turbine.towerCC.cost)
		print
		print "The overall turbine cost is ${0:.2f} USD".format(turbine.turbine_cost)
		print '#########################################################'

	############################################################################
	## 6. Operating Expenses

	# A simple test of nrel_csm_bos model
	bos = bos_csm_assembly()

	# Set input parameters
	bos = bos_csm_assembly()
	bos.machine_rating = hubS.machine_rating/1000
	bos.rotor_diameter = rotor.diameter
	bos.turbine_cost = turbine.turbine_cost
	bos.hub_height = HubHeight
	bos.turbine_number = 1
	bos.sea_depth = 0
	bos.year = 2009
	bos.month = 12
	bos.multiplier = 1.0
	bos.run()

	om = opex_csm_assembly()

	om.machine_rating = rotor.control.ratedPower/1000  
	# Need to manipulate input or underlying component will not execute
	om.net_aep = AEP*10e4
	om.sea_depth = 0
	om.year = 2009
	om.month = 12
	om.turbine_number = 100

	om.run()

	if (Verbose==True):
		print '##################### Operating Costs ####################'
		print "BOS cost per turbine: ${0:.2f} USD".format(bos.bos_costs / \
			bos.turbine_number)
		print "Average annual operational expenditures"
		print "OPEX on shore with 100 turbines ${:.2f}: USD".format(\
			om.avg_annual_opex)
		print "Preventative OPEX by turbine: ${:.2f} USD".format(\
			om.opex_breakdown.preventative_opex / om.turbine_number)
		print "Corrective OPEX by turbine: ${:.2f} USD".format(\
			om.opex_breakdown.corrective_opex / om.turbine_number)
		print "Land Lease OPEX by turbine: ${:.2f} USD".format(\
			om.opex_breakdown.lease_opex / om.turbine_number)
		print '#########################################################'

	CapitalCost = turbine.turbine_cost + bos.bos_costs / bos.turbine_number
	OperatingCost = om.opex_breakdown.preventative_opex / om.turbine_number + \
	om.opex_breakdown.lease_opex / om.turbine_number + \
	om.opex_breakdown.corrective_opex / om.turbine_number

	LCOE = ComputeLCOE(AEP, CapitalCost, OperatingCost, DiscountRate, Years)

	print '######################***********************###################'
	print "Levelized Cost of Energy over %d years \
	is $%f/kWH" %(Years,LCOE/1000)
	print '######################***********************###################'

	return LCOE/1000
def EvaluateLCOE(BladeLength, HubHeight, MaximumRotSpeed, Verbose=False):

    ############################################################################
    # Define baseline paremeters used for scaling
    ReferenceBladeLength = 35
    ReferenceTowerHeight = 95
    WindReferenceHeight = 50
    WindReferenceMeanVelocity = 3
    WeibullShapeFactor = 2.0
    ShearFactor = 0.25

    RatedPower = 1.5e6

    # Years used for analysis
    Years = 25
    DiscountRate = 0.08
    ############################################################################

    ############################################################################
    ### 1. Aerodynamic and structural performance using RotorSE
    rotor = RotorSE()
    # -------------------

    # === blade grid ===
    # (Array): initial aerodynamic grid on unit radius
    rotor.initial_aero_grid = np.array([0.02222276, 0.06666667, 0.11111057, \
     0.16666667, 0.23333333, 0.3, 0.36666667, 0.43333333, 0.5, 0.56666667, \
     0.63333333, 0.7, 0.76666667, 0.83333333, 0.88888943, 0.93333333, \
        0.97777724])

    # (Array): initial structural grid on unit radius
    rotor.initial_str_grid = np.array([
        0.0, 0.00492790457512, 0.00652942887106, 0.00813095316699,
        0.00983257273154, 0.0114340970275, 0.0130356213234, 0.02222276,
        0.024446481932, 0.026048006228, 0.06666667, 0.089508406455, 0.11111057,
        0.146462614229, 0.16666667, 0.195309105255, 0.23333333, 0.276686558545,
        0.3, 0.333640766319, 0.36666667, 0.400404310407, 0.43333333, 0.5,
        0.520818918408, 0.56666667, 0.602196371696, 0.63333333, 0.667358391486,
        0.683573824984, 0.7, 0.73242031601, 0.76666667, 0.83333333, 0.88888943,
        0.93333333, 0.97777724, 1.0
    ])

    # (Int): first idx in r_aero_unit of non-cylindrical section,
    # constant twist inboard of here
    rotor.idx_cylinder_aero = 3

    # (Int): first idx in r_str_unit of non-cylindrical section
    rotor.idx_cylinder_str = 14

    # (Float): hub location as fraction of radius
    rotor.hubFraction = 0.025
    # ------------------

    # === blade geometry ===
    # (Array): new aerodynamic grid on unit radius
    rotor.r_aero = np.array([
        0.02222276, 0.06666667, 0.11111057, 0.2, 0.23333333, 0.3, 0.36666667,
        0.43333333, 0.5, 0.56666667, 0.63333333, 0.64, 0.7, 0.83333333,
        0.88888943, 0.93333333, 0.97777724
    ])

    # (Float): location of max chord on unit radius
    rotor.r_max_chord = 0.23577

    # (Array, m): chord at control points. defined at hub, then at linearly spaced
    # locations from r_max_chord to tip
    ReferenceChord = [3.2612, 4.5709, 3.3178, 1.4621]
    rotor.chord_sub = [x * np.true_divide(BladeLength,ReferenceBladeLength) \
     for x in ReferenceChord]

    # (Array, deg): twist at control points.  defined at linearly spaced locations
    # from r[idx_cylinder] to tip
    rotor.theta_sub = [13.2783, 7.46036, 2.89317, -0.0878099]

    # (Array, m): precurve at control points.  defined at same locations at chord,
    # starting at 2nd control point (root must be zero precurve)
    rotor.precurve_sub = [0.0, 0.0, 0.0]

    # (Array, m): adjustment to precurve to account for curvature from loading
    rotor.delta_precurve_sub = [0.0, 0.0, 0.0]

    # (Array, m): spar cap thickness parameters
    rotor.sparT = [0.05, 0.047754, 0.045376, 0.031085, 0.0061398]

    # (Array, m): trailing-edge thickness parameters
    rotor.teT = [0.1, 0.09569, 0.06569, 0.02569, 0.00569]

    # (Float, m): blade length (if not precurved or swept)
    # otherwise length of blade before curvature
    rotor.bladeLength = BladeLength

    # (Float, m): adjustment to blade length to account for curvature from
    # loading
    rotor.delta_bladeLength = 0.0
    rotor.precone = 2.5  # (Float, deg): precone angle
    rotor.tilt = 5.0  # (Float, deg): shaft tilt
    rotor.yaw = 0.0  # (Float, deg): yaw error
    rotor.nBlades = 3  # (Int): number of blades
    # ------------------

    # === airfoil files ===
    basepath = os.path.join(os.path.dirname(\
     os.path.realpath(__file__)), '5MW_AFFiles')

    # load all airfoils
    airfoil_types = [0] * 8
    airfoil_types[0] = os.path.join(basepath, 'Cylinder1.dat')
    airfoil_types[1] = os.path.join(basepath, 'Cylinder2.dat')
    airfoil_types[2] = os.path.join(basepath, 'DU40_A17.dat')
    airfoil_types[3] = os.path.join(basepath, 'DU35_A17.dat')
    airfoil_types[4] = os.path.join(basepath, 'DU30_A17.dat')
    airfoil_types[5] = os.path.join(basepath, 'DU25_A17.dat')
    airfoil_types[6] = os.path.join(basepath, 'DU21_A17.dat')
    airfoil_types[7] = os.path.join(basepath, 'NACA64_A17.dat')

    # place at appropriate radial stations
    af_idx = [0, 0, 1, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7]

    n = len(af_idx)
    af = [0] * n
    for i in range(n):
        af[i] = airfoil_types[af_idx[i]]
    rotor.airfoil_files = af  # (List): names of airfoil file
    # ----------------------

    # === atmosphere ===
    rotor.rho = 1.225  # (Float, kg/m**3): density of air
    rotor.mu = 1.81206e-5  # (Float, kg/m/s): dynamic viscosity of air
    rotor.shearExp = 0.25  # (Float): shear exponent
    rotor.hubHt = HubHeight  # (Float, m): hub height
    rotor.turbine_class = 'I'  # (Enum): IEC turbine class
    rotor.turbulence_class = 'B'  # (Enum): IEC turbulence class class
    rotor.cdf_reference_height_wind_speed = 30.0
    rotor.g = 9.81  # (Float, m/s**2): acceleration of gravity
    # ----------------------

    # === control ===
    rotor.control.Vin = 3.0  # (Float, m/s): cut-in wind speed
    rotor.control.Vout = 26.0  # (Float, m/s): cut-out wind speed
    rotor.control.ratedPower = RatedPower  # (Float, W): rated power

    # (Float, rpm): minimum allowed rotor rotation speed

    # (Float, rpm): maximum allowed rotor rotation speed
    rotor.control.minOmega = 0.0
    rotor.control.maxOmega = MaximumRotSpeed

    # (Float): tip-speed ratio in Region 2 (should be optimized externally)
    rotor.control.tsr = 7
    # (Float, deg): pitch angle in region 2 (and region 3 for fixed pitch machines)
    rotor.control.pitch = 0.0
    # (Float, deg): worst-case pitch at survival wind condition
    rotor.pitch_extreme = 0.0

    # (Float, deg): worst-case azimuth at survival wind condition
    rotor.azimuth_extreme = 0.0

    # (Float): fraction of rated speed at which the deflection is assumed to
    # representative throughout the power curve calculation
    rotor.VfactorPC = 0.7
    # ----------------------

    # === aero and structural analysis options ===

    # (Int): number of sectors to divide rotor face into in computing thrust and power
    rotor.nSector = 4

    # (Int): number of points to evaluate aero analysis at
    rotor.npts_coarse_power_curve = 20

    # (Int): number of points to use in fitting spline to power curve
    rotor.npts_spline_power_curve = 200

    # (Float): availability and other losses (soiling, array, etc.)
    rotor.AEP_loss_factor = 1.0
    rotor.drivetrainType = 'geared'  # (Enum)

    # (Int): number of natural frequencies to compute
    rotor.nF = 5

    # (Float): a dynamic amplification factor to adjust the static deflection
    # calculation
    rotor.dynamic_amplication_tip_deflection = 1.35
    # ----------------------

    # === materials and composite layup  ===
    basepath = os.path.join(os.path.dirname(os.path.realpath(__file__)), \
     '5MW_PrecompFiles')

    materials = Orthotropic2DMaterial.listFromPreCompFile(os.path.join(basepath,\
     'materials.inp'))

    ncomp = len(rotor.initial_str_grid)
    upper = [0] * ncomp
    lower = [0] * ncomp
    webs = [0] * ncomp
    profile = [0] * ncomp

    # (Array): array of leading-edge positions from a reference blade axis
    # (usually blade pitch axis). locations are normalized by the local chord
    # length. e.g. leLoc[i] = 0.2 means leading edge is 0.2*chord[i] from reference
    # axis.  positive in -x direction for airfoil-aligned coordinate system
    rotor.leLoc = np.array([
        0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.498, 0.497, 0.465, 0.447,
        0.43, 0.411, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4,
        0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4
    ])

    # (Array): index of sector for spar (PreComp definition of sector)
    rotor.sector_idx_strain_spar = [2] * ncomp

    # (Array): index of sector for trailing-edge (PreComp definition of sector)
    rotor.sector_idx_strain_te = [3] * ncomp

    web1 = np.array([
        -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 0.4114, 0.4102, 0.4094,
        0.3876, 0.3755, 0.3639, 0.345, 0.3342, 0.3313, 0.3274, 0.323, 0.3206,
        0.3172, 0.3138, 0.3104, 0.307, 0.3003, 0.2982, 0.2935, 0.2899, 0.2867,
        0.2833, 0.2817, 0.2799, 0.2767, 0.2731, 0.2664, 0.2607, 0.2562, 0.1886,
        -1.0
    ])

    web2 = np.array([
        -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 0.5886, 0.5868, 0.5854,
        0.5508, 0.5315, 0.5131, 0.4831, 0.4658, 0.4687, 0.4726, 0.477, 0.4794,
        0.4828, 0.4862, 0.4896, 0.493, 0.4997, 0.5018, 0.5065, 0.5101, 0.5133,
        0.5167, 0.5183, 0.5201, 0.5233, 0.5269, 0.5336, 0.5393, 0.5438, 0.6114,
        -1.0
    ])
    web3 = np.array([
        -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0,
        -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
        1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0
    ])

    # (Array, m): chord distribution for reference section, thickness of structural
    # layup scaled with reference thickness (fixed t/c for this case)
    rotor.chord_str_ref = np.array([3.2612, 3.3100915356, 3.32587052924,
     3.34159388653, 3.35823798667, 3.37384375335, 3.38939112914, 3.4774055542,
     3.49839685, 3.51343645709, 3.87017220335, 4.04645623801, 4.19408216643,
        4.47641008477, 4.55844487985, 4.57383098262, 4.57285771934, 4.51914315648,
        4.47677655262, 4.40075650022, 4.31069949379, 4.20483735936, 4.08985563932,
        3.82931757126, 3.74220276467, 3.54415796922, 3.38732428502, 3.24931446473,
        3.23421422609, 3.22701537997, 3.21972125648, 3.08979310611, 2.95152261813,
        2.330753331, 2.05553464181, 1.82577817774, 1.5860853279, 1.4621])* \
     np.true_divide(BladeLength,ReferenceBladeLength)

    for i in range(ncomp):
        webLoc = []
        if web1[i] != -1:
            webLoc.append(web1[i])
        if web2[i] != -1:
            webLoc.append(web2[i])
        if web3[i] != -1:
            webLoc.append(web3[i])

        upper[i], lower[i], webs[i] = CompositeSection.initFromPreCompLayupFile\
        (os.path.join(basepath, 'layup_' + str(i+1) + '.inp'), webLoc, materials)
        profile[i] = Profile.initFromPreCompFile(os.path.join(basepath, 'shape_' \
         + str(i+1) + '.inp'))

    # (List): list of all Orthotropic2DMaterial objects used in
    # defining the geometry
    rotor.materials = materials

    # (List): list of CompositeSection objections defining the properties for
    # upper surface
    rotor.upperCS = upper

    # (List): list of CompositeSection objections defining the properties for
    # lower surface
    rotor.lowerCS = lower

    # (List): list of CompositeSection objections defining the properties for
    # shear webs
    rotor.websCS = webs

    # (List): airfoil shape at each radial position
    rotor.profile = profile
    # --------------------------------------

    # === fatigue ===

    # (Array): nondimensional radial locations of damage equivalent moments
    rotor.rstar_damage = np.array([
        0.000, 0.022, 0.067, 0.111, 0.167, 0.233, 0.300, 0.367, 0.433, 0.500,
        0.567, 0.633, 0.700, 0.767, 0.833, 0.889, 0.933, 0.978
    ])

    # (Array, N*m): damage equivalent moments about blade c.s. x-direction
    rotor.Mxb_damage = 1e3 * np.array([
        2.3743E+003, 2.0834E+003, 1.8108E+003, 1.5705E+003, 1.3104E+003,
        1.0488E+003, 8.2367E+002, 6.3407E+002, 4.7727E+002, 3.4804E+002,
        2.4458E+002, 1.6339E+002, 1.0252E+002, 5.7842E+001, 2.7349E+001,
        1.1262E+001, 3.8549E+000, 4.4738E-001
    ])

    # (Array, N*m): damage equivalent moments about blade c.s. y-direction
    rotor.Myb_damage = 1e3 * np.array([
        2.7732E+003, 2.8155E+003, 2.6004E+003, 2.3933E+003, 2.1371E+003,
        1.8459E+003, 1.5582E+003, 1.2896E+003, 1.0427E+003, 8.2015E+002,
        6.2449E+002, 4.5229E+002, 3.0658E+002, 1.8746E+002, 9.6475E+001,
        4.2677E+001, 1.5409E+001, 1.8426E+000
    ])

    rotor.strain_ult_spar = 1.0e-2  # (Float): ultimate strain in spar cap

    # (Float): uptimate strain in trailing-edge panels, note that I am putting a
    # factor of two for the damage part only.
    rotor.strain_ult_te = 2500 * 1e-6 * 2
    rotor.eta_damage = 1.35 * 1.3 * 1.0  # (Float): safety factor for fatigue
    rotor.m_damage = 10.0  # (Float): slope of S-N curve for fatigue analysis

    # (Float): number of cycles used in fatigue analysis
    rotor.N_damage = 365 * 24 * 3600 * 20.0
    # ----------------

    # from myutilities import plt

    # === run and outputs ===
    rotor.run()

    # Evaluate AEP Using Lewis' Functions
    # Weibull Wind Parameters
    WindReferenceHeight = 50
    WindReferenceMeanVelocity = 7.5
    WeibullShapeFactor = 2.0
    ShearFactor = 0.25

    PowerCurve = rotor.P / 1e6
    PowerCurveVelocity = rotor.V

    HubHeight = rotor.hubHt

    AEP,WeibullScale = CalculateAEPWeibull(PowerCurve,PowerCurveVelocity, HubHeight, \
       BladeLength,WeibullShapeFactor, WindReferenceHeight, \
       WindReferenceMeanVelocity, ShearFactor)

    NamePlateCapacity = EstimateCapacity(PowerCurve,PowerCurveVelocity, \
     rotor.ratedConditions.V)

    # AEP At Constant 7.5m/s Wind used for benchmarking...
    #AEP = CalculateAEPConstantWind(PowerCurve, PowerCurveVelocity, 7.5)

    if (Verbose == True):
        print '###################     ROTORSE   ######################'
        print 'AEP = %d MWH' % (AEP)
        print 'NamePlateCapacity = %fMW' % (NamePlateCapacity)
        print 'diameter =', rotor.diameter
        print 'ratedConditions.V =', rotor.ratedConditions.V
        print 'ratedConditions.Omega =', rotor.ratedConditions.Omega
        print 'ratedConditions.pitch =', rotor.ratedConditions.pitch
        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
        print 'tip_deflection =', rotor.tip_deflection
        print 'root_bending_moment =', rotor.root_bending_moment
        print '#########################################################'

    #############################################################################
    ### 2. Hub Sizing
    # Specify hub parameters based off rotor

    # Load default hub model
    hubS = HubSE()
    hubS.rotor_diameter = rotor.Rtip * 2  # m
    hubS.blade_number = rotor.nBlades
    hubS.blade_root_diameter = rotor.chord_sub[0] * 1.25
    hubS.L_rb = rotor.hubFraction * rotor.diameter
    hubS.MB1_location = np.array([-0.5, 0.0, 0.0])
    hubS.machine_rating = rotor.control.ratedPower
    hubS.blade_mass = rotor.mass_one_blade
    hubS.rotor_bending_moment = rotor.root_bending_moment

    hubS.run()

    RotorTotalWeight = rotor.mass_all_blades + hubS.spinner.mass + \
    hubS.hub.mass + hubS.pitchSystem.mass

    if (Verbose == True):
        print '##################### Hub SE ############################'
        print "Estimate of Hub Component Sizes:"
        print "Hub Components"
        print '  Hub: {0:8.1f} kg'.format(hubS.hub.mass)
        print '  Pitch system: {0:8.1f} kg'.format(hubS.pitchSystem.mass)
        print '  Nose cone: {0:8.1f} kg'.format(hubS.spinner.mass)
        print 'Rotor Total Weight = %d kg' % RotorTotalWeight
        print '#########################################################'

    ############################################################################
    ### 3. Drive train + Nacelle Mass estimation
    nace = Drive4pt()
    nace.rotor_diameter = rotor.Rtip * 2  # m
    nace.rotor_speed = rotor.ratedConditions.Omega  # #rpm m/s
    nace.machine_rating = hubS.machine_rating / 1000
    nace.DrivetrainEfficiency = 0.95

    # 6.35e6 #4365248.74 # Nm
    nace.rotor_torque = rotor.ratedConditions.Q
    nace.rotor_thrust = rotor.ratedConditions.T  # N
    nace.rotor_mass = 0.0  #accounted for in F_z # kg

    nace.rotor_bending_moment_x = rotor.Mxyz_0[0]
    nace.rotor_bending_moment_y = rotor.Mxyz_0[1]
    nace.rotor_bending_moment_z = rotor.Mxyz_0[2]

    nace.rotor_force_x = rotor.Fxyz_0[0]  # N
    nace.rotor_force_y = rotor.Fxyz_0[1]
    nace.rotor_force_z = rotor.Fxyz_0[2]  # N

    # geared 3-stage Gearbox with induction generator machine
    nace.drivetrain_design = 'geared'
    nace.gear_ratio = 96.76  # 97:1 as listed in the 5 MW reference document
    nace.gear_configuration = 'eep'  # epicyclic-epicyclic-parallel

    nace.crane = True  # onboard crane present
    nace.shaft_angle = 5.0  #deg
    nace.shaft_ratio = 0.10
    nace.Np = [3, 3, 1]
    nace.ratio_type = 'optimal'
    nace.shaft_type = 'normal'
    nace.uptower_transformer = False
    nace.shrink_disc_mass = 333.3 * nace.machine_rating / 1000.0  # estimated
    nace.mb1Type = 'CARB'
    nace.mb2Type = 'SRB'
    nace.flange_length = 0.5  #m
    nace.overhang = 5.0
    nace.gearbox_cm = 0.1
    nace.hss_length = 1.5

    #0 if no fatigue check, 1 if parameterized fatigue check,
    #2 if known loads inputs
    nace.check_fatigue = 0
    nace.blade_number = rotor.nBlades
    nace.cut_in = rotor.control.Vin  #cut-in m/s
    nace.cut_out = rotor.control.Vout  #cut-out m/s
    nace.Vrated = rotor.ratedConditions.V  #rated windspeed m/s
    nace.weibull_k = WeibullShapeFactor  # windepeed distribution shape parameter

    # windspeed distribution scale parameter
    nace.weibull_A = WeibullScale

    nace.T_life = 20.  #design life in years
    nace.IEC_Class_Letter = 'B'

    # length from hub center to main bearing, leave zero if unknown
    nace.L_rb = hubS.L_rb

    # NREL 5 MW Tower Variables
    nace.tower_top_diameter = 3.78  # m

    nace.run()

    if (Verbose == True):
        print '##################### Drive SE ############################'
        print "Estimate of Nacelle Component Sizes"
        print 'Low speed shaft: {0:8.1f} kg'.format(nace.lowSpeedShaft.mass)
        print 'Main bearings: {0:8.1f} kg'.format(\
         nace.mainBearing.mass + nace.secondBearing.mass)
        print 'Gearbox: {0:8.1f} kg'.format(nace.gearbox.mass)
        print 'High speed shaft & brakes: {0:8.1f} kg'.format\
         (nace.highSpeedSide.mass)
        print 'Generator: {0:8.1f} kg'.format(nace.generator.mass)
        print 'Variable speed electronics: {0:8.1f} kg'.format(\
         nace.above_yaw_massAdder.vs_electronics_mass)
        print 'Overall mainframe:{0:8.1f} kg'.format(\
         nace.above_yaw_massAdder.mainframe_mass)
        print '     Bedplate: {0:8.1f} kg'.format(nace.bedplate.mass)
        print 'Electrical connections: {0:8.1f} kg'.format(\
         nace.above_yaw_massAdder.electrical_mass)
        print 'HVAC system: {0:8.1f} kg'.format(\
         nace.above_yaw_massAdder.hvac_mass )
        print 'Nacelle cover: {0:8.1f} kg'.format(\
         nace.above_yaw_massAdder.cover_mass)
        print 'Yaw system: {0:8.1f} kg'.format(nace.yawSystem.mass)
        print 'Overall nacelle: {0:8.1f} kg'.format(nace.nacelle_mass, \
         nace.nacelle_cm[0], nace.nacelle_cm[1], nace.nacelle_cm[2], \
         nace.nacelle_I[0], nace.nacelle_I[1], nace.nacelle_I[2])
        print '#########################################################'

    ############################################################################
    ### 4. Tower Mass

    # --- tower setup ------
    from commonse.environment import PowerWind

    tower = set_as_top(TowerSE())

    # ---- tower ------
    tower.replace('wind1', PowerWind())
    tower.replace('wind2', PowerWind())
    # onshore (no waves)

    # --- geometry ----
    tower.z_param = [0.0, HubHeight * 0.5, HubHeight]
    TowerRatio = np.true_divide(HubHeight, ReferenceTowerHeight)

    tower.d_param = [6.0 * TowerRatio, 4.935 * TowerRatio, 3.87 * TowerRatio]
    tower.t_param = [0.027*1.3*TowerRatio, 0.023*1.3*TowerRatio, \
    0.019*1.3*TowerRatio]
    n = 10

    tower.z_full = np.linspace(0.0, HubHeight, n)
    tower.L_reinforced = 15.0 * np.ones(n)  # [m] buckling length
    tower.theta_stress = 0.0 * np.ones(n)
    tower.yaw = 0.0

    # --- material props ---
    tower.E = 210e9 * np.ones(n)
    tower.G = 80.8e9 * np.ones(n)
    tower.rho = 8500.0 * np.ones(n)
    tower.sigma_y = 450.0e6 * np.ones(n)

    # --- spring reaction data.  Use float('inf') for rigid constraints. ---
    tower.kidx = [0]  # applied at base
    tower.kx = [float('inf')]
    tower.ky = [float('inf')]
    tower.kz = [float('inf')]
    tower.ktx = [float('inf')]
    tower.kty = [float('inf')]
    tower.ktz = [float('inf')]

    # --- extra mass ----
    tower.midx = [n - 1]  # RNA mass at top
    tower.m = [0.8]
    tower.mIxx = [1.14930678e+08]
    tower.mIyy = [2.20354030e+07]
    tower.mIzz = [1.87597425e+07]
    tower.mIxy = [0.00000000e+00]
    tower.mIxz = [5.03710467e+05]
    tower.mIyz = [0.00000000e+00]
    tower.mrhox = [-1.13197635]
    tower.mrhoy = [0.]
    tower.mrhoz = [0.50875268]
    tower.addGravityLoadForExtraMass = False
    # -----------

    # --- wind ---
    tower.wind_zref = 90.0
    tower.wind_z0 = 0.0
    tower.wind1.shearExp = 0.14
    tower.wind2.shearExp = 0.14
    # ---------------

    # # --- loading case 1: max Thrust ---
    tower.wind_Uref1 = 11.73732
    tower.plidx1 = [n - 1]  # at tower top
    tower.Fx1 = [0.19620519]
    tower.Fy1 = [0.]
    tower.Fz1 = [-2914124.84400512]
    tower.Mxx1 = [3963732.76208099]
    tower.Myy1 = [-2275104.79420872]
    tower.Mzz1 = [-346781.68192839]
    # # ---------------

    # # --- loading case 2: max wind speed ---
    tower.wind_Uref2 = 70.0
    tower.plidx1 = [n - 1]  # at tower top
    tower.Fx1 = [930198.60063279]
    tower.Fy1 = [0.]
    tower.Fz1 = [-2883106.12368949]
    tower.Mxx1 = [-1683669.22411597]
    tower.Myy1 = [-2522475.34625363]
    tower.Mzz1 = [147301.97023764]
    # # ---------------

    # # --- run ---
    tower.run()

    if (Verbose == True):
        print '##################### Tower SE ##########################'
        print 'mass (kg) =', tower.mass
        print 'f1 (Hz) =', tower.f1
        print 'f2 (Hz) =', tower.f2
        print 'top_deflection1 (m) =', tower.top_deflection1
        print 'top_deflection2 (m) =', tower.top_deflection2
        print '#########################################################'

    ############################################################################
    ## 5. Turbine captial costs analysis
    turbine = Turbine_CostsSE()

    # NREL 5 MW turbine component masses based on Sunderland model approach
    # Rotor
    # inline with the windpact estimates
    turbine.blade_mass = rotor.mass_one_blade
    turbine.hub_mass = hubS.hub.mass
    turbine.pitch_system_mass = hubS.pitchSystem.mass
    turbine.spinner_mass = hubS.spinner.mass

    # Drivetrain and Nacelle
    turbine.low_speed_shaft_mass = nace.lowSpeedShaft.mass
    turbine.main_bearing_mass = nace.mainBearing.mass
    turbine.second_bearing_mass = nace.secondBearing.mass
    turbine.gearbox_mass = nace.gearbox.mass
    turbine.high_speed_side_mass = nace.highSpeedSide.mass
    turbine.generator_mass = nace.generator.mass
    turbine.bedplate_mass = nace.bedplate.mass
    turbine.yaw_system_mass = nace.yawSystem.mass

    # Tower
    turbine.tower_mass = tower.mass * 0.5

    # Additional non-mass cost model input variables
    turbine.machine_rating = hubS.machine_rating / 1000
    turbine.advanced = False
    turbine.blade_number = rotor.nBlades
    turbine.drivetrain_design = 'geared'
    turbine.crane = False
    turbine.offshore = False

    # Target year for analysis results
    turbine.year = 2010
    turbine.month = 12

    turbine.run()

    if (Verbose == True):
        print '##################### TurbinePrice SE ####################'
        print "Overall rotor cost with 3 advanced blades is ${0:.2f} USD"\
         .format(turbine.rotorCC.cost)
        print "Blade cost is ${0:.2f} USD".format(turbine.rotorCC.bladeCC.cost)
        print "Hub cost is ${0:.2f} USD".format(turbine.rotorCC.hubCC.cost)
        print "Pitch system cost is ${0:.2f} USD".format(
            turbine.rotorCC.pitchSysCC.cost)
        print "Spinner cost is ${0:.2f} USD".format(
            turbine.rotorCC.spinnerCC.cost)
        print
        print "Overall nacelle cost is ${0:.2f} USD".format(
            turbine.nacelleCC.cost)
        print "LSS cost is ${0:.2f} USD".format(turbine.nacelleCC.lssCC.cost)
        print "Main bearings cost is ${0:.2f} USD".format(
            turbine.nacelleCC.bearingsCC.cost)
        print "Gearbox cost is ${0:.2f} USD".format(
            turbine.nacelleCC.gearboxCC.cost)
        print "Hight speed side cost is ${0:.2f} USD".format(
            turbine.nacelleCC.hssCC.cost)
        print "Generator cost is ${0:.2f} USD".format(
            turbine.nacelleCC.generatorCC.cost)
        print "Bedplate cost is ${0:.2f} USD".format(
            turbine.nacelleCC.bedplateCC.cost)
        print "Yaw system cost is ${0:.2f} USD".format(
            turbine.nacelleCC.yawSysCC.cost)
        print
        print "Tower cost is ${0:.2f} USD".format(turbine.towerCC.cost)
        print
        print "The overall turbine cost is ${0:.2f} USD".format(
            turbine.turbine_cost)
        print '#########################################################'

    ############################################################################
    ## 6. Operating Expenses

    # A simple test of nrel_csm_bos model
    bos = bos_csm_assembly()

    # Set input parameters
    bos = bos_csm_assembly()
    bos.machine_rating = hubS.machine_rating / 1000
    bos.rotor_diameter = rotor.diameter
    bos.turbine_cost = turbine.turbine_cost
    bos.hub_height = HubHeight
    bos.turbine_number = 1
    bos.sea_depth = 0
    bos.year = 2009
    bos.month = 12
    bos.multiplier = 1.0
    bos.run()

    om = opex_csm_assembly()

    om.machine_rating = rotor.control.ratedPower / 1000
    # Need to manipulate input or underlying component will not execute
    om.net_aep = AEP * 10e4
    om.sea_depth = 0
    om.year = 2009
    om.month = 12
    om.turbine_number = 100

    om.run()

    if (Verbose == True):
        print '##################### Operating Costs ####################'
        print "BOS cost per turbine: ${0:.2f} USD".format(bos.bos_costs / \
         bos.turbine_number)
        print "Average annual operational expenditures"
        print "OPEX on shore with 100 turbines ${:.2f}: USD".format(\
         om.avg_annual_opex)
        print "Preventative OPEX by turbine: ${:.2f} USD".format(\
         om.opex_breakdown.preventative_opex / om.turbine_number)
        print "Corrective OPEX by turbine: ${:.2f} USD".format(\
         om.opex_breakdown.corrective_opex / om.turbine_number)
        print "Land Lease OPEX by turbine: ${:.2f} USD".format(\
         om.opex_breakdown.lease_opex / om.turbine_number)
        print '#########################################################'

    CapitalCost = turbine.turbine_cost + bos.bos_costs / bos.turbine_number
    OperatingCost = om.opex_breakdown.preventative_opex / om.turbine_number + \
    om.opex_breakdown.lease_opex / om.turbine_number + \
    om.opex_breakdown.corrective_opex / om.turbine_number

    LCOE = ComputeLCOE(AEP, CapitalCost, OperatingCost, DiscountRate, Years)

    print '######################***********************###################'
    print "Levelized Cost of Energy over %d years \
	is $%f/kWH" % (Years, LCOE / 1000)
    print '######################***********************###################'

    return LCOE / 1000
示例#8
0
    def __init__(self, RefBlade):
        super(FloatingTurbine, self).__init__()

        self.add('hub_height', IndepVarComp('hub_height', 0.0), promotes=['*'])

        # TODO:
        #Weibull/Rayleigh CDF

        # Rotor
        self.add('rotor', RotorSE(RefBlade), promotes=['*'])

        # RNA
        self.add('rna', RNA(1), promotes=['downwind'])

        # Tower and substructure
        myfloat = FloatingSE()
        self.add('sm', myfloat, promotes=['*'])

        # Turbine constraints
        self.add('tcons', TurbineConstraints(myfloat.nFullTow), promotes=['*'])

        # Turbine costs
        self.add('tcost', Turbine_CostsSE_2015(), promotes=['*'])

        # Balance of station
        self.add('wobos', WindOBOS(), promotes=['*'])

        # LCOE Calculation
        self.add('lcoe', PlantFinance(), promotes=['*'])

        # Define all input variables from all models
        self.add('offshore',
                 IndepVarComp('offshore', True, pass_by_obj=True),
                 promotes=['*'])
        self.add('crane',
                 IndepVarComp('crane', False, pass_by_obj=True),
                 promotes=['*'])

        # Turbine Costs
        # REMOVE ONCE DRIVESE AND GENERATORSE ARE CONNECTED
        self.add('bearing_number',
                 IndepVarComp('bearing_number', 0, pass_by_obj=True),
                 promotes=['*'])
        self.add('bedplate_mass',
                 IndepVarComp('bedplate_mass', 0.0),
                 promotes=['*'])
        self.add('crane_cost', IndepVarComp('crane_cost', 0.0), promotes=['*'])
        self.add('gearbox_mass',
                 IndepVarComp('gearbox_mass', 0.0),
                 promotes=['*'])
        self.add('generator_mass',
                 IndepVarComp('generator_mass', 0.0),
                 promotes=['*'])
        self.add('hss_mass', IndepVarComp('hss_mass', 0.0), promotes=['*'])
        self.add('hvac_mass', IndepVarComp('hvac_mass', 0.0), promotes=['*'])
        self.add('lss_mass', IndepVarComp('lss_mass', 0.0), promotes=['*'])
        self.add('main_bearing_mass',
                 IndepVarComp('main_bearing_mass', 0.0),
                 promotes=['*'])
        self.add('cover_mass', IndepVarComp('cover_mass', 0.0), promotes=['*'])
        self.add('platforms_mass',
                 IndepVarComp('platforms_mass', 0.0),
                 promotes=['*'])
        self.add('pitch_system_mass',
                 IndepVarComp('pitch_system_mass', 0.0),
                 promotes=['*'])
        self.add('spinner_mass',
                 IndepVarComp('spinner_mass', 0.0),
                 promotes=['*'])
        self.add('transformer_mass',
                 IndepVarComp('transformer_mass', 0.0),
                 promotes=['*'])
        self.add('vs_electronics_mass',
                 IndepVarComp('vs_electronics_mass', 0.0),
                 promotes=['*'])
        self.add('yaw_mass', IndepVarComp('yaw_mass', 0.0), promotes=['*'])

        # Tower
        #self.add('stress_standard_value',          IndepVarComp('stress_standard_value', 0.0), promotes=['*'])
        #self.add('fatigue_parameters',             IndepVarComp('fatigue_parameters', np.zeros(nDEL)), promotes=['*'])
        #self.add('fatigue_z',                      IndepVarComp('fatigue_z', np.zeros(nDEL)), promotes=['*'])
        #self.add('frame3dd_matrix_method',         IndepVarComp('frame3dd_matrix_method', 0, pass_by_obj=True), promotes=['*'])
        #self.add('compute_stiffnes',               IndepVarComp('compute_stiffnes', False, pass_by_obj=True), promotes=['*'])
        self.add('project_lifetime',
                 IndepVarComp('project_lifetime', 0.0),
                 promotes=['*'])
        #self.add('lumped_mass_matrix',             IndepVarComp('lumped_mass_matrix', 0, pass_by_obj=True), promotes=['*'])
        #self.add('slope_SN',                       IndepVarComp('slope_SN', 0, pass_by_obj=True), promotes=['*'])
        #self.add('number_of_modes',                IndepVarComp('number_of_modes', 0, pass_by_obj=True), promotes=['*'])
        #self.add('compute_shear',                  IndepVarComp('compute_shear', True, pass_by_obj=True), promotes=['*'])
        #self.add('shift_value',                    IndepVarComp('shift_value', 0.0), promotes=['*'])
        #self.add('frame3dd_convergence_tolerance', IndepVarComp('frame3dd_convergence_tolerance', 1e-9), promotes=['*'])

        # TODO: Multiple load cases
        # Environment
        self.add('air_density',
                 IndepVarComp('air_density', 0.0),
                 promotes=['*'])
        self.add('air_viscosity',
                 IndepVarComp('air_viscosity', 0.0),
                 promotes=['*'])
        self.add('wind_reference_speed',
                 IndepVarComp('wind_reference_speed', 0.0),
                 promotes=['*'])
        self.add('wind_reference_height',
                 IndepVarComp('wind_reference_height', 0.0),
                 promotes=['*'])
        self.add('shearExp', IndepVarComp('shearExp', 0.0), promotes=['*'])
        self.add('wind_bottom_height',
                 IndepVarComp('wind_bottom_height', 0.0),
                 promotes=['*'])
        self.add('wind_beta', IndepVarComp('wind_beta', 0.0), promotes=['*'])
        self.add('cd_usr', IndepVarComp('cd_usr', np.inf), promotes=['*'])

        # Environment
        self.add('water_depth',
                 IndepVarComp('water_depth', 0.0),
                 promotes=['*'])
        self.add('water_density',
                 IndepVarComp('water_density', 0.0),
                 promotes=['*'])
        self.add('water_viscosity',
                 IndepVarComp('water_viscosity', 0.0),
                 promotes=['*'])
        self.add('wave_height',
                 IndepVarComp('wave_height', 0.0),
                 promotes=['*'])
        self.add('wave_period',
                 IndepVarComp('wave_period', 0.0),
                 promotes=['*'])
        self.add('mean_current_speed',
                 IndepVarComp('mean_current_speed', 0.0),
                 promotes=['*'])
        #self.add('wave_beta',                  IndepVarComp('wave_beta', 0.0), promotes=['*'])
        #self.add('wave_velocity_z0',           IndepVarComp('wave_velocity_z0', 0.0), promotes=['*'])
        #self.add('wave_acceleration_z0',       IndepVarComp('wave_acceleration_z0', 0.0), promotes=['*'])

        # Design standards
        self.add('gamma_freq', IndepVarComp('gamma_freq', 0.0), promotes=['*'])
        self.add('gamma_f', IndepVarComp('gamma_f', 0.0), promotes=['*'])
        self.add('gamma_m', IndepVarComp('gamma_m', 0.0), promotes=['*'])
        self.add('gamma_b', IndepVarComp('gamma_b', 0.0), promotes=['*'])
        self.add('gamma_fatigue',
                 IndepVarComp('gamma_fatigue', 0.0),
                 promotes=['*'])
        self.add('gamma_n', IndepVarComp('gamma_n', 0.0), promotes=['*'])

        # RNA
        self.add('dummy_mass', IndepVarComp('dummy_mass', 0.0), promotes=['*'])
        self.add('hub_mass', IndepVarComp('hub_mass', 0.0), promotes=['*'])
        self.add('nac_mass', IndepVarComp('nac_mass', 0.0), promotes=['*'])
        self.add('hub_cm',
                 IndepVarComp('hub_cm', np.zeros((3, ))),
                 promotes=['*'])
        self.add('nac_cm',
                 IndepVarComp('nac_cm', np.zeros((3, ))),
                 promotes=['*'])
        self.add('hub_I', IndepVarComp('hub_I', np.zeros(6)), promotes=['*'])
        self.add('nac_I', IndepVarComp('nac_I', np.zeros(6)), promotes=['*'])
        self.add('rna_weightM',
                 IndepVarComp('rna_weightM', True, pass_by_obj=True),
                 promotes=['*'])

        # Column
        self.add('morison_mass_coefficient',
                 IndepVarComp('morison_mass_coefficient', 0.0),
                 promotes=['*'])
        self.add('material_density',
                 IndepVarComp('material_density', 0.0),
                 promotes=['*'])
        self.add('E', IndepVarComp('E', 0.0), promotes=['*'])
        self.add('nu', IndepVarComp('nu', 0.0), promotes=['*'])
        self.add('yield_stress',
                 IndepVarComp('yield_stress', 0.0),
                 promotes=['*'])

        # Pontoons
        self.add('G', IndepVarComp('G', 0.0), promotes=['*'])

        # LCOE
        self.add('number_of_turbines',
                 IndepVarComp('number_of_turbines', 0, pass_by_obj=True),
                 promotes=['*'])
        self.add('annual_opex',
                 IndepVarComp('annual_opex', 0.0),
                 promotes=['*'])  # TODO: Replace with output connection
        self.add('fixed_charge_rate',
                 IndepVarComp('fixed_charge_rate', 0.0),
                 promotes=['*'])
        self.add('discount_rate',
                 IndepVarComp('discount_rate', 0.0),
                 promotes=['*'])

        # Connect all input variables from all models
        self.connect('water_depth', ['waterD', 'sea_depth'])
        self.connect('hub_height', 'hubH')
        self.connect('tower_outer_diameter', 'towerD', src_indices=[0])

        self.connect('wind_beta', 'beta')
        self.connect('mean_current_speed', 'Uc')

        self.connect('project_lifetime', ['struc.lifetime', 'projLife'])
        #self.connect('slope_SN', 'm_SN')
        #self.connect('compute_shear', 'shear')
        #self.connect('compute_stiffnes', 'geom')
        #self.connect('frame3dd_matrix_method', 'Mmethod')
        #self.connect('shift_value', 'shift')
        # TODO:
        #self.connect('number_of_modes', ['nM', 'nF'])
        #self.connect('frame3dd_convergence_tolerance', 'tol')
        #self.connect('lumped_mass_matrix', 'lump')
        #self.connect('stress_standard_value', 'DC')

        self.connect('rna.loads.top_F', 'rna_force')
        self.connect('rna.loads.top_M', 'rna_moment')
        self.connect('rna.rna_I_TT', 'rna_I')
        self.connect('rna.rna_mass', ['rnaM', 'rna_mass'])
        self.connect('rna.rna_cm', 'rna_cg')
        self.connect('mass_all_blades', 'rna.blades_mass')
        self.connect('I_all_blades', 'rna.blades_I')
        self.connect('hub_mass', 'rna.hub_mass')
        self.connect('nac_mass', 'rna.nac_mass')
        self.connect('hub_cm', 'rna.hub_cm')
        self.connect('nac_cm', 'rna.nac_cm')
        self.connect('hub_I', 'rna.hub_I')
        self.connect('nac_I', 'rna.nac_I')
        self.connect('tilt', 'rna.tilt')
        self.connect('Fxyz_total', 'rna.loads.F')
        self.connect('Mxyz_total', 'rna.loads.M')
        self.connect('rna_weightM', 'rna.rna_weightM')

        self.connect('air_density', ['main.windLoads.rho', 'analysis.rho'])
        self.connect('air_viscosity', ['main.windLoads.mu', 'analysis.mu'])
        self.connect('water_density', 'water_density')
        self.connect('water_viscosity', 'main.waveLoads.mu')
        self.connect('wave_height', 'Hs')
        self.connect('wave_period', 'T')
        self.connect('wind_reference_speed', 'Uref')
        self.connect('wind_reference_height', ['zref', 'wind.zref'])
        self.connect('wind_bottom_height', ['z0', 'wind.z0'])
        self.connect('shearExp', 'wind.shearExp')
        self.connect('morison_mass_coefficient', 'cm')

        self.connect('ballast_cost_rate', 'ballCR')
        self.connect('mooring_cost_rate', 'moorCR')
        self.connect('mooring_cost', 'moorCost')
        self.connect('mooring_diameter', 'moorDia')
        self.connect('number_of_mooring_lines', 'moorLines')
        self.connect('material_cost_rate', 'sSteelCR')
        self.connect('main.tapered_column_cost_rate',
                     ['spStifColCR', 'spTapColCR', 'ssStifColCR'])
        self.connect('pontoon_cost_rate', 'ssTrussCR')

        self.connect('nBlades', 'blade_number')
        self.connect('mass_one_blade', 'blade_mass')
        self.connect('control_maxOmega', 'rotor_omega')
        self.connect('structural_frequencies', 'tower_freq')

        self.connect('turbine_cost_kW', 'turbCapEx')
        self.connect('machine_rating', 'turbR')
        self.connect('diameter', 'rotorD')
        self.connect('bladeLength', 'bladeL')
        self.connect('hub_diameter', 'hubD')

        # Link outputs from one model to inputs to another
        self.connect('tower_mass', 'towerM')
        self.connect('dummy_mass', 'off.stack_mass_in')

        self.connect('total_cost', 'subTotCost')
        self.connect('total_mass', 'subTotM')
        self.connect('total_bos_cost', 'bos_costs')

        self.connect('number_of_turbines', ['nTurb', 'turbine_number'])
        self.connect('annual_opex', 'avg_annual_opex')
        self.connect('AEP', 'net_aep')
        self.connect('totInstTime', 'construction_time')

        # Use complex number finite differences
        typeStr = 'fd'
        formStr = 'central'
        stepVal = 1e-5
        stepStr = 'relative'

        self.deriv_options['type'] = typeStr
        self.deriv_options['form'] = formStr
        self.deriv_options['step_size'] = stepVal
        self.deriv_options['step_calc'] = stepStr
    def __init__(self, RefBlade):
        super(MonopileTurbine, self).__init__()
        nFull   = 5*(NSECTION) + 1

        self.add('hub_height', IndepVarComp('hub_height', 0.0), promotes=['*'])
        self.add('foundation_height', IndepVarComp('foundation_height', 0.0), promotes=['*'])

        
        # Rotor
        self.add('rotor', RotorSE(RefBlade, regulation_reg_II5=False, regulation_reg_III=True, Analysis_Level=-1), promotes=['*'])

        # RNA
        self.add('drive', Drive4pt('CARB', 'SRB', 'B', 'eep', 'normal', 'geared', True, 0, True, 3),
                 promotes=['bedplate_mass','gearbox_mass','generator_mass','hss_mass','hvac_mass','lss_mass','cover_mass',
                           'pitch_system_mass','platforms_mass','spinner_mass','transformer_mass','vs_electronics_mass','yaw_mass'])
        self.add('rna', RNA(nLC), promotes=['*'])
        
        # Tower and substructure
        self.add('tow',TowerSE(nLC, NSECTION+1, nFull, nDEL, wind='PowerWind'), promotes=['material_density','E','G','tower_section_height',
                                                                                          'tower_outer_diameter','tower_wall_thickness',
                                                                                          'tower_outfitting_factor','tower_buckling_length','downwind',
                                                                                          'max_taper','min_d_to_t','rna_mass','rna_cg','rna_I','hub_cm',
                                                                                          'tower_mass','tower_I_base','hub_height','tip_position',
                                                                                          'foundation_height','monopile','soil_G','soil_nu',
                                                                                          'suctionpile_depth','tip_deflection_margin',
                                                                                          'gamma_f','gamma_m','gamma_b','gamma_n','gamma_fatigue',
                                                                                          'labor_cost_rate','material_cost_rate','painting_cost_rate'])
                 
        # Turbine constraints
        self.add('tcons', TurbineConstraints(nFull), promotes=['*'])
        
        # Turbine costs
        self.add('tcost', Turbine_CostsSE_2015(), promotes=['*'])
        
        # Balance of station
        self.add('wobos', WindOBOS(), promotes=['*'])#tax_rate'])

        # LCOE Calculation
        self.add('lcoe', PlantFinance(), promotes=['*'])

        # Define all input variables from all models
        self.add('offshore',             IndepVarComp('offshore', True, pass_by_obj=True), promotes=['*'])
        self.add('crane',                IndepVarComp('crane', False, pass_by_obj=True), promotes=['*'])

        # Turbine Costs
        # REMOVE ONCE DRIVESE AND GENERATORSE ARE CONNECTED
        self.add('bearing_number',           IndepVarComp('bearing_number', 0, pass_by_obj=True), promotes=['*'])
        #self.add('hub_mass',            IndepVarComp('hub_mass', 0.0), promotes=['*'])
        #self.add('bedplate_mass',            IndepVarComp('bedplate_mass', 0.0), promotes=['*'])
        self.add('crane_cost',               IndepVarComp('crane_cost', 0.0), promotes=['*'])
        #self.add('gearbox_mass',             IndepVarComp('gearbox_mass', 0.0), promotes=['*'])
        #self.add('generator_mass',           IndepVarComp('generator_mass', 0.0), promotes=['*'])
        #self.add('hss_mass',     IndepVarComp('hss_mass', 0.0), promotes=['*'])
        #self.add('hvac_mass',   IndepVarComp('hvac_mass', 0.0), promotes=['*'])
        #self.add('lss_mass',     IndepVarComp('lss_mass', 0.0), promotes=['*'])
        #self.add('main_bearing_mass',        IndepVarComp('main_bearing_mass', 0.0), promotes=['*'])
        #self.add('cover_mass',       IndepVarComp('cover_mass', 0.0), promotes=['*'])
        #self.add('platforms_mass',   IndepVarComp('platforms_mass', 0.0), promotes=['*'])
        #self.add('pitch_system_mass',        IndepVarComp('pitch_system_mass', 0.0), promotes=['*'])
        #self.add('spinner_mass',             IndepVarComp('spinner_mass', 0.0), promotes=['*'])
        #self.add('transformer_mass',         IndepVarComp('transformer_mass', 0.0), promotes=['*'])
        #self.add('vs_electronics_mass', IndepVarComp('vs_electronics_mass', 0.0), promotes=['*'])
        #self.add('yaw_mass',          IndepVarComp('yaw_mass', 0.0), promotes=['*'])
        
        # Tower and Frame3DD options
        self.add('stress_standard_value',          IndepVarComp('stress_standard_value', 0.0), promotes=['*'])
        self.add('frame3dd_matrix_method',         IndepVarComp('frame3dd_matrix_method', 0, pass_by_obj=True), promotes=['*'])
        self.add('compute_stiffness',              IndepVarComp('compute_stiffness', False, pass_by_obj=True), promotes=['*'])
        self.add('project_lifetime',               IndepVarComp('project_lifetime', 0.0), promotes=['*'])
        self.add('lumped_mass_matrix',             IndepVarComp('lumped_mass_matrix', 0, pass_by_obj=True), promotes=['*'])
        self.add('slope_SN',                       IndepVarComp('slope_SN', 0, pass_by_obj=True), promotes=['*'])
        self.add('number_of_modes',                IndepVarComp('number_of_modes', NFREQ, pass_by_obj=True), promotes=['*'])
        self.add('compute_shear',                  IndepVarComp('compute_shear', True, pass_by_obj=True), promotes=['*'])
        self.add('shift_value',                    IndepVarComp('shift_value', 0.0), promotes=['*'])
        self.add('frame3dd_convergence_tolerance', IndepVarComp('frame3dd_convergence_tolerance', 1e-7), promotes=['*'])
        self.add('max_taper_ratio',                IndepVarComp('max_taper_ratio', 0.0), promotes=['*'])
        self.add('min_diameter_thickness_ratio',   IndepVarComp('min_diameter_thickness_ratio', 0.0), promotes=['*'])
        
        # Environment
        #self.add('air_density',                IndepVarComp('air_density', 0.0), promotes=['*'])
        #self.add('air_viscosity',              IndepVarComp('air_viscosity', 0.0), promotes=['*'])
        self.add('wind_reference_speed',       IndepVarComp('wind_reference_speed', 0.0), promotes=['*'])
        self.add('wind_reference_height',      IndepVarComp('wind_reference_height', 0.0), promotes=['*'])
        self.add('shearExp',                   IndepVarComp('shearExp', 0.0), promotes=['*'])
        self.add('wind_bottom_height',         IndepVarComp('wind_bottom_height', 0.0), promotes=['*'])
        self.add('wind_beta',                  IndepVarComp('wind_beta', 0.0), promotes=['*'])
        self.add('cd_usr',                     IndepVarComp('cd_usr', np.inf), promotes=['*'])

        # Environment
        self.add('water_depth',                IndepVarComp('water_depth', 0.0), promotes=['*'])
        self.add('water_density',              IndepVarComp('water_density', 0.0), promotes=['*'])
        self.add('water_viscosity',            IndepVarComp('water_viscosity', 0.0), promotes=['*'])
        self.add('wave_height',                IndepVarComp('wave_height', 0.0), promotes=['*'])
        self.add('wave_period',                IndepVarComp('wave_period', 0.0), promotes=['*'])
        self.add('mean_current_speed',         IndepVarComp('mean_current_speed', 0.0), promotes=['*'])
        self.add('wave_beta',                  IndepVarComp('wave_beta', 0.0), promotes=['*'])
        
        # Design standards
        self.add('gamma_freq',      IndepVarComp('gamma_freq', 0.0), promotes=['*'])
        self.add('gamma_f',         IndepVarComp('gamma_f', 0.0), promotes=['*'])
        self.add('gamma_m',         IndepVarComp('gamma_m', 0.0), promotes=['*'])
        self.add('gamma_b',         IndepVarComp('gamma_b', 0.0), promotes=['*'])
        self.add('gamma_fatigue',   IndepVarComp('gamma_fatigue', 0.0), promotes=['*'])
        self.add('gamma_n',         IndepVarComp('gamma_n', 0.0), promotes=['*'])

        # RNA
        #self.add('nac_mass',                   IndepVarComp('nac_mass', 0.0), promotes=['*'])
        #self.add('hub_cm',                     IndepVarComp('hub_cm', np.zeros((3,))), promotes=['*'])
        #self.add('nac_cm',                     IndepVarComp('nac_cm', np.zeros((3,))), promotes=['*'])
        #self.add('hub_I',                      IndepVarComp('hub_I', np.zeros(6)), promotes=['*'])
        #self.add('nac_I',                      IndepVarComp('nac_I', np.zeros(6)), promotes=['*'])
        self.add('rna_weightM',                IndepVarComp('rna_weightM', True, pass_by_obj=True), promotes=['*'])
        
        # Column
        self.add('morison_mass_coefficient',   IndepVarComp('morison_mass_coefficient', 0.0), promotes=['*'])
        self.add('material_density',           IndepVarComp('material_density', 0.0), promotes=['*'])
        self.add('E',                          IndepVarComp('E', 0.0), promotes=['*'])
        self.add('yield_stress',               IndepVarComp('yield_stress', 0.0), promotes=['*'])

        # Pontoons
        self.add('G',                          IndepVarComp('G', 0.0), promotes=['*'])
        
        # LCOE
        self.add('labor_cost_rate',      IndepVarComp('labor_cost_rate', 0.0), promotes=['*'])
        self.add('material_cost_rate',      IndepVarComp('material_cost_rate', 0.0), promotes=['*'])
        self.add('painting_cost_rate',      IndepVarComp('painting_cost_rate', 0.0), promotes=['*'])
        self.add('number_of_turbines', IndepVarComp('number_of_turbines', 0, pass_by_obj=True), promotes=['*'])
        self.add('annual_opex',        IndepVarComp('annual_opex', 0.0), promotes=['*']) # TODO: Replace with output connection
        self.add('fixed_charge_rate',  IndepVarComp('fixed_charge_rate', 0.0), promotes=['*'])
        self.add('discount_rate',      IndepVarComp('discount_rate', 0.0), promotes=['*'])

        
        # Connect all input variables from all models
        self.connect('water_depth', ['tow.z_floor','waterD', 'sea_depth','mpileL'])
        self.connect('hub_height', ['hub_height', 'hubH'])
        self.connect('tower_outer_diameter', 'towerD', src_indices=[NSECTION])
        self.connect('tower_outer_diameter', 'mpileD', src_indices=[0])
        self.connect('suctionpile_depth', 'mpEmbedL')
        
        self.connect('wind_beta', 'tow.windLoads.beta')
        self.connect('wave_beta', 'tow.waveLoads.beta')
        self.connect('cd_usr', 'tow.cd_usr')
        self.connect('yaw', 'tow.distLoads.yaw')
        self.connect('mean_current_speed', 'tow.wave.Uc')
        
        self.connect('project_lifetime', ['struc.lifetime','tow.life', 'projLife'])
        self.connect('number_of_modes', 'tow.nM')
        self.connect('frame3dd_convergence_tolerance', 'tow.tol')
        self.connect('lumped_mass_matrix', 'tow.lump')
        self.connect('stress_standard_value', 'tow.DC')
        self.connect('shift_value', 'tow.shift')
        self.connect('compute_shear', 'tow.shear')
        self.connect('slope_SN', 'tow.m_SN')
        self.connect('compute_stiffness', 'tow.geom')
        self.connect('frame3dd_matrix_method', 'tow.Mmethod')

        self.connect('diameter','drive.rotor_diameter')
        self.connect('rated_Q','drive.rotor_torque')
        self.connect('rated_Omega','drive.rotor_rpm')
        self.connect('Mxyz_total','drive.rotor_bending_moment_x', src_indices=[0])
        self.connect('Mxyz_total','drive.rotor_bending_moment_y', src_indices=[1])
        self.connect('Mxyz_total','drive.rotor_bending_moment_z', src_indices=[2])
        self.connect('Fxyz_total','drive.rotor_thrust', src_indices=[0])
        self.connect('Fxyz_total','drive.rotor_force_y', src_indices=[1])
        self.connect('Fxyz_total','drive.rotor_force_z', src_indices=[2])
        self.connect('mass_one_blade','drive.blade_mass')
        self.connect('chord', 'drive.blade_root_diameter', src_indices=[0])
        self.connect('drivetrainEff', 'drive.drivetrain_efficiency', src_indices=[0])

        self.connect('mass_all_blades', 'blades_mass')
        self.connect('drive.hub_system_mass', 'hub_mass')
        self.connect('drive.nacelle_mass', 'nac_mass')
        self.connect('I_all_blades', 'blades_I')
        self.connect('drive.hub_system_I', 'hub_I')
        self.connect('drive.nacelle_I', 'nac_I')
        self.connect('drive.hub_system_cm', 'hub_cm')
        self.connect('drive.nacelle_cm', 'nac_cm')
        self.connect('drive.mb1_mass', 'main_bearing_mass')

        #self.connect('drive.hub_system_cm', 'hub_tt')
        self.connect('Fxyz_total','loads.F')
        self.connect('Mxyz_total','loads.M')
        
        self.connect('loads.top_F', 'tow.pre.rna_F')
        self.connect('loads.top_M', 'tow.pre.rna_M')
        self.connect('rna_I_TT', 'rna_I')
        self.connect('rna_mass', 'rnaM')
        self.connect('rna_cm', 'rna_cg')
        
        self.connect('rho', 'tow.windLoads.rho') #,'powercurve.rho'])
        self.connect('mu', 'tow.windLoads.mu')#,'powercurve.mu'])
        self.connect('water_density',['tow.wave.rho','tow.waveLoads.rho'])
        self.connect('water_viscosity', 'tow.waveLoads.mu')
        self.connect('wave_height', 'tow.wave.hmax')
        self.connect('wave_period', 'tow.wave.T')
        self.connect('wind_reference_speed', 'tow.wind.Uref')
        self.connect('wind_reference_height', ['tow.wind.zref','wind.zref'])
        self.connect('wind_bottom_height', ['tow.z0','wind.z0'])
        self.connect('shearExp', ['tow.wind.shearExp', 'wind.shearExp'])
        self.connect('morison_mass_coefficient', 'tow.cm')

        self.connect('yield_stress', 'tow.sigma_y')
        self.connect('max_taper_ratio', 'max_taper')
        self.connect('min_diameter_thickness_ratio', 'min_d_to_t')

        self.connect('nBlades','blade_number')
        self.connect('mass_one_blade', 'blade_mass')
        self.connect('control_maxOmega', 'rotor_omega')
        self.connect('tow.post.structural_frequencies', 'tower_freq')
        #self.connect('tow.z_full', 'tower_z')
        #self.connect('tow.d_full', 'tower_d')
        
        self.connect('turbine_cost_kW', 'turbCapEx')
        self.connect('machine_rating', ['turbR','drive.machine_rating'])
        self.connect('diameter', 'rotorD')
        self.connect('bladeLength', 'bladeL')
        self.connect('hub_diameter', 'hubD')
        
        # Link outputs from one model to inputs to another
        self.connect('tower_mass', 'towerM')

        self.connect('material_cost_rate', 'sSteelCR')
        self.connect('tower_cost', 'subTotCost')
        self.connect('tower_mass', 'subTotM')
        self.connect('total_bos_cost', 'bos_costs')

        self.connect('number_of_turbines', ['nTurb', 'turbine_number'])
        self.connect('annual_opex', 'avg_annual_opex')
        self.connect('AEP', 'net_aep')
        self.connect('totInstTime', 'construction_time')

        # TODO Compare Rotor hub_diameter to Drive hub_diameter
        # TODO: Match Rotor Drivetrain Type to DriveSE Drivetrain options
        # TODO: Match Rotor CSMDrivetrain and efficiency to DriveSE
        
         # Use complex number finite differences
        self.deriv_options['type'] = 'fd'
        self.deriv_options['form'] = 'central'
        self.deriv_options['step_size'] = 1e-5
        self.deriv_options['step_calc'] = 'relative'
示例#10
0
def configure_turbine(assembly,
                      with_new_nacelle=True,
                      flexible_blade=False,
                      with_3pt_drive=False):
    """a stand-alone configure method to allow for flatter assemblies

    Parameters
    ----------
    assembly : Assembly
        an openmdao assembly to be configured
    with_new_nacelle : bool
        False uses the default implementation, True uses an experimental implementation designed
        to smooth out discontinities making in amenable for gradient-based optimization
    flexible_blade : bool
        if True, internally solves the coupled aero/structural deflection using fixed point iteration.
        Note that the coupling is currently only in the flapwise deflection, and is primarily
        only important for highly flexible blades.  If False, the aero loads are passed
        to the structure but there is no further iteration.
    """

    # --- general turbine configuration inputs---
    assembly.add(
        'rho',
        Float(1.225,
              iotype='in',
              units='kg/m**3',
              desc='density of air',
              deriv_ignore=True))
    assembly.add(
        'mu',
        Float(1.81206e-5,
              iotype='in',
              units='kg/m/s',
              desc='dynamic viscosity of air',
              deriv_ignore=True))
    assembly.add(
        'shear_exponent',
        Float(0.2, iotype='in', desc='shear exponent', deriv_ignore=True))
    assembly.add('hub_height',
                 Float(90.0, iotype='in', units='m', desc='hub height'))
    assembly.add(
        'turbine_class',
        Enum('I', ('I', 'II', 'III', 'IV'),
             iotype='in',
             desc='IEC turbine class'))
    assembly.add(
        'turbulence_class',
        Enum('B', ('A', 'B', 'C'),
             iotype='in',
             desc='IEC turbulence class class'))
    assembly.add(
        'g',
        Float(9.81,
              iotype='in',
              units='m/s**2',
              desc='acceleration of gravity',
              deriv_ignore=True))
    assembly.add(
        'cdf_reference_height_wind_speed',
        Float(
            90.0,
            iotype='in',
            desc=
            'reference hub height for IEC wind speed (used in CDF calculation)'
        ))
    assembly.add('downwind',
                 Bool(False, iotype='in', desc='flag if rotor is downwind'))
    assembly.add(
        'tower_d',
        Array([0.0], iotype='in', units='m', desc='diameters along tower'))
    assembly.add('generator_speed',
                 Float(iotype='in', units='rpm', desc='generator speed'))
    assembly.add(
        'machine_rating',
        Float(5000.0, units='kW', iotype='in', desc='machine rated power'))
    assembly.add(
        'rna_weightM',
        Bool(True,
             iotype='in',
             desc='flag to consider or not the RNA weight effect on Moment'))

    assembly.add('rotor', RotorSE())
    if with_new_nacelle:
        assembly.add('hub', HubSE())
        assembly.add('hubSystem', Hub_System_Adder_drive())
        assembly.add('moments', blade_moment_transform())
        assembly.add('forces', blade_force_transform())
        if with_3pt_drive:
            assembly.add('nacelle', Drive3pt())
        else:
            assembly.add('nacelle', Drive4pt())
    else:
        assembly.add('nacelle', DriveWPACT())
        assembly.add('hub', HubWPACT())
    assembly.add('rna', RNAMass())
    assembly.add('rotorloads1', RotorLoads())
    assembly.add('rotorloads2', RotorLoads())
    assembly.add('tower', TowerSE())
    assembly.add('maxdeflection', MaxTipDeflection())

    if flexible_blade:
        assembly.add('fpi', FixedPointIterator())

        assembly.fpi.workflow.add(['rotor'])
        assembly.fpi.add_parameter('rotor.delta_precurve_sub',
                                   low=-1.e99,
                                   high=1.e99)
        assembly.fpi.add_parameter('rotor.delta_bladeLength',
                                   low=-1.e99,
                                   high=1.e99)
        assembly.fpi.add_constraint(
            'rotor.delta_precurve_sub = rotor.delta_precurve_sub_out')
        assembly.fpi.add_constraint(
            'rotor.delta_bladeLength = rotor.delta_bladeLength_out')
        assembly.fpi.max_iteration = 20
        assembly.fpi.tolerance = 1e-8

        assembly.driver.workflow.add(['fpi'])

    else:
        assembly.driver.workflow.add(['rotor'])

    assembly.driver.workflow.add([
        'hub', 'nacelle', 'tower', 'maxdeflection', 'rna', 'rotorloads1',
        'rotorloads2'
    ])

    if with_new_nacelle:
        assembly.driver.workflow.add(['hubSystem', 'moments', 'forces'])

    # TODO: rotor drivetrain design should be connected to nacelle drivetrain design

    # connections to rotor
    assembly.connect('machine_rating', 'rotor.control.ratedPower')
    assembly.connect('rho', 'rotor.rho')
    assembly.connect('mu', 'rotor.mu')
    assembly.connect('shear_exponent', 'rotor.shearExp')
    assembly.connect('hub_height', 'rotor.hubHt')
    assembly.connect('turbine_class', 'rotor.turbine_class')
    assembly.connect('turbulence_class', 'rotor.turbulence_class')
    assembly.connect('g', 'rotor.g')
    assembly.connect('cdf_reference_height_wind_speed',
                     'rotor.cdf_reference_height_wind_speed')

    # connections to hub and hub system
    assembly.connect('rotor.mass_one_blade', 'hub.blade_mass')
    assembly.connect('rotor.root_bending_moment', 'hub.rotor_bending_moment')
    assembly.connect('rotor.diameter', ['hub.rotor_diameter'])
    assembly.connect('rotor.hub_diameter', 'hub.blade_root_diameter')
    assembly.connect('rotor.nBlades', 'hub.blade_number')
    if with_new_nacelle:
        assembly.connect('machine_rating', 'hub.machine_rating')
        assembly.connect('rotor.diameter', ['hubSystem.rotor_diameter'])
        assembly.connect('nacelle.MB1_location',
                         'hubSystem.MB1_location')  # TODO: bearing locations
        assembly.connect('nacelle.L_rb', 'hubSystem.L_rb')
        assembly.connect('rotor.tilt', 'hubSystem.shaft_angle')
        assembly.connect('hub.hub_diameter', 'hubSystem.hub_diameter')
        assembly.connect('hub.hub_thickness', 'hubSystem.hub_thickness')
        assembly.connect('hub.hub_mass', 'hubSystem.hub_mass')
        assembly.connect('hub.spinner_mass', 'hubSystem.spinner_mass')
        assembly.connect('hub.pitch_system_mass',
                         'hubSystem.pitch_system_mass')

    # connections to nacelle #TODO: fatigue option variables
    assembly.connect('rotor.diameter', 'nacelle.rotor_diameter')
    assembly.connect('1.5 * rotor.ratedConditions.Q', 'nacelle.rotor_torque')
    assembly.connect('rotor.ratedConditions.T', 'nacelle.rotor_thrust')
    assembly.connect('rotor.ratedConditions.Omega', 'nacelle.rotor_speed')
    assembly.connect('machine_rating', 'nacelle.machine_rating')
    assembly.connect('rotor.root_bending_moment',
                     'nacelle.rotor_bending_moment')
    assembly.connect('generator_speed/rotor.ratedConditions.Omega',
                     'nacelle.gear_ratio')
    assembly.connect(
        'tower_d[-1]',
        'nacelle.tower_top_diameter')  # OpenMDAO circular dependency issue
    assembly.connect(
        'rotor.mass_all_blades + hub.hub_system_mass',
        'nacelle.rotor_mass')  # assuming not already in rotor force / moments
    # variable connections for new nacelle
    if with_new_nacelle:
        assembly.connect('rotor.nBlades', 'nacelle.blade_number')
        assembly.connect('rotor.tilt', 'nacelle.shaft_angle')
        assembly.connect('333.3 * machine_rating / 1000.0',
                         'nacelle.shrink_disc_mass')
        assembly.connect('rotor.hub_diameter', 'nacelle.blade_root_diameter')

        #moments
        # assembly.connect('rotor.Q_extreme','nacelle.rotor_bending_moment_x')
        assembly.connect('rotor.Mxyz_0', 'moments.b1')
        assembly.connect('rotor.Mxyz_120', 'moments.b2')
        assembly.connect('rotor.Mxyz_240', 'moments.b3')
        assembly.connect('rotor.Pitch', 'moments.pitch_angle')
        assembly.connect('rotor.TotalCone', 'moments.cone_angle')
        assembly.connect('moments.Mx', 'nacelle.rotor_bending_moment_x'
                         )  #accounted for in ratedConditions.Q
        assembly.connect('moments.My', 'nacelle.rotor_bending_moment_y')
        assembly.connect('moments.Mz', 'nacelle.rotor_bending_moment_z')

        #forces
        # assembly.connect('rotor.T_extreme','nacelle.rotor_force_x')
        assembly.connect('rotor.Fxyz_0', 'forces.b1')
        assembly.connect('rotor.Fxyz_120', 'forces.b2')
        assembly.connect('rotor.Fxyz_240', 'forces.b3')
        assembly.connect('rotor.Pitch', 'forces.pitch_angle')
        assembly.connect('rotor.TotalCone', 'forces.cone_angle')
        assembly.connect('forces.Fx', 'nacelle.rotor_force_x')
        assembly.connect('forces.Fy', 'nacelle.rotor_force_y')
        assembly.connect('forces.Fz', 'nacelle.rotor_force_z')
    '''if  with_new_nacelle:
        assembly.connect('rotor.g', 'nacelle.g') # Only drive smooth taking g from rotor; TODO: update when drive_smooth is updated'''

    # connections to rna
    assembly.connect('rotor.mass_all_blades', 'rna.blades_mass')
    assembly.connect('rotor.I_all_blades', 'rna.blades_I')
    if with_new_nacelle:
        assembly.connect('hubSystem.hub_system_mass', 'rna.hub_mass')
        assembly.connect('hubSystem.hub_system_cm', 'rna.hub_cm')
        assembly.connect('hubSystem.hub_system_I', 'rna.hub_I')
    else:
        assembly.connect('hub.hub_system_mass', 'rna.hub_mass')
        assembly.connect('hub.hub_system_cm', 'rna.hub_cm')
        assembly.connect('hub.hub_system_I', 'rna.hub_I')
    assembly.connect('nacelle.nacelle_mass', 'rna.nac_mass')
    assembly.connect('nacelle.nacelle_cm', 'rna.nac_cm')
    assembly.connect('nacelle.nacelle_I', 'rna.nac_I')

    # connections to rotorloads1
    assembly.connect('downwind', 'rotorloads1.downwind')
    assembly.connect('rna_weightM', 'rotorloads1.rna_weightM')
    assembly.connect('1.8 * rotor.ratedConditions.T', 'rotorloads1.F[0]')
    assembly.connect('rotor.ratedConditions.Q', 'rotorloads1.M[0]')
    if with_new_nacelle:
        assembly.connect('hubSystem.hub_system_cm', 'rotorloads1.r_hub')
    else:
        assembly.connect('hub.hub_system_cm', 'rotorloads1.r_hub')
    assembly.connect('rna.rna_cm', 'rotorloads1.rna_cm')
    assembly.connect('rotor.tilt', 'rotorloads1.tilt')
    assembly.connect('g', 'rotorloads1.g')
    assembly.connect('rna.rna_mass', 'rotorloads1.m_RNA')

    # connections to rotorloads2
    assembly.connect('downwind', 'rotorloads2.downwind')
    assembly.connect('rna_weightM', 'rotorloads2.rna_weightM')
    assembly.connect('rotor.T_extreme', 'rotorloads2.F[0]')
    assembly.connect('rotor.Q_extreme', 'rotorloads2.M[0]')
    if with_new_nacelle:
        assembly.connect('hubSystem.hub_system_cm', 'rotorloads2.r_hub')
    else:
        assembly.connect('hub.hub_system_cm', 'rotorloads2.r_hub')
    assembly.connect('rna.rna_cm', 'rotorloads2.rna_cm')
    assembly.connect('rotor.tilt', 'rotorloads2.tilt')
    assembly.connect('g', 'rotorloads2.g')
    assembly.connect('rna.rna_mass', 'rotorloads2.m_RNA')

    # connections to tower
    assembly.connect('rho', 'tower.wind_rho')
    assembly.connect('mu', 'tower.wind_mu')
    assembly.connect('g', 'tower.g')
    assembly.connect('hub_height', 'tower.wind_zref')
    assembly.connect('tower_d', 'tower.d_param')
    assembly.connect('rotor.ratedConditions.V', 'tower.wind_Uref1')
    assembly.connect('rotor.V_extreme', 'tower.wind_Uref2')
    assembly.connect('rotor.yaw', 'tower.yaw')
    assembly.connect('hub_height - nacelle.nacelle_cm[2]',
                     'tower.z_param[-1]')  #TODO: hub height should be derived
    assembly.connect('rna.rna_mass', 'tower.m[0]')
    assembly.connect('rna.rna_cm[0]', 'tower.mrhox[0]')
    assembly.connect('rna.rna_cm[1]', 'tower.mrhoy[0]')
    assembly.connect('rna.rna_cm[2]', 'tower.mrhoz[0]')
    assembly.connect('rna.rna_I_TT[0]', 'tower.mIxx[0]')
    assembly.connect('rna.rna_I_TT[1]', 'tower.mIyy[0]')
    assembly.connect('rna.rna_I_TT[2]', 'tower.mIzz[0]')
    assembly.connect('rna.rna_I_TT[3]', 'tower.mIxy[0]')
    assembly.connect('rna.rna_I_TT[4]', 'tower.mIxz[0]')
    assembly.connect('rna.rna_I_TT[5]', 'tower.mIyz[0]')
    assembly.connect('rotorloads1.top_F[0]', 'tower.Fx1[0]')
    assembly.connect('rotorloads1.top_F[1]', 'tower.Fy1[0]')
    assembly.connect('rotorloads1.top_F[2]', 'tower.Fz1[0]')
    assembly.connect('rotorloads1.top_M[0]', 'tower.Mxx1[0]')
    assembly.connect('rotorloads1.top_M[1]', 'tower.Myy1[0]')
    assembly.connect('rotorloads1.top_M[2]', 'tower.Mzz1[0]')
    assembly.connect('rotorloads2.top_F[0]', 'tower.Fx2[0]')
    assembly.connect('rotorloads2.top_F[1]', 'tower.Fy2[0]')
    assembly.connect('rotorloads2.top_F[2]', 'tower.Fz2[0]')
    assembly.connect('rotorloads2.top_M[0]', 'tower.Mxx2[0]')
    assembly.connect('rotorloads2.top_M[1]', 'tower.Myy2[0]')
    assembly.connect('rotorloads2.top_M[2]', 'tower.Mzz2[0]')

    # connections to maxdeflection
    assembly.connect('rotor.Rtip', 'maxdeflection.Rtip')
    assembly.connect('rotor.precurveTip', 'maxdeflection.precurveTip')
    assembly.connect('rotor.presweepTip', 'maxdeflection.presweepTip')
    assembly.connect('rotor.precone', 'maxdeflection.precone')
    assembly.connect('rotor.tilt', 'maxdeflection.tilt')
    if with_new_nacelle:
        assembly.connect('hubSystem.hub_system_cm', 'maxdeflection.hub_tt')
    else:
        assembly.connect('hub.hub_system_cm', 'maxdeflection.hub_tt')
    assembly.connect('tower.z_param', 'maxdeflection.tower_z')
    assembly.connect('tower.d_param', 'maxdeflection.tower_d')
    assembly.connect('hub_height - nacelle.nacelle_cm[2]',
                     'maxdeflection.towerHt')