コード例 #1
0
ファイル: test_DriveSE.py プロジェクト: crobinsonut/DriveSE
class Test_HubSE(unittest.TestCase):

    def setUp(self):

        self.hub = HubSE()

        self.hub = HubSE()
    
        self.hub.rotor_diameter = 126.0 # m
        self.hub.blade_number  = 3
        self.hub.blade_root_diameter   = 3.542
        self.hub.machine_rating = 5000.0
        self.hub.blade_mass = 17740.0 # kg
    
        AirDensity= 1.225 # kg/(m^3)
        Solidity  = 0.0517
        RatedWindSpeed = 11.05 # m/s
        self.hub.rotor_bending_moment = (3.06 * pi / 8) * AirDensity * (RatedWindSpeed ** 2) * (Solidity * (self.hub.rotor_diameter ** 3)) / self.hub.blade_number
    
        self.hub.gamma = 5.0
        self.hub.MB1_location = np.array([-3.2, 0.0, 1.0])

    def test_functionality(self):
        
        self.hub.run()
        
        self.assertEqual(round(self.hub.hub_system_mass,1), 45025.7)
コード例 #2
0
ファイル: test_DriveSE.py プロジェクト: crobinsonut/DriveSE
    def setUp(self):

        self.hub = HubSE()

        self.hub = HubSE()
    
        self.hub.rotor_diameter = 126.0 # m
        self.hub.blade_number  = 3
        self.hub.blade_root_diameter   = 3.542
        self.hub.machine_rating = 5000.0
        self.hub.blade_mass = 17740.0 # kg
    
        AirDensity= 1.225 # kg/(m^3)
        Solidity  = 0.0517
        RatedWindSpeed = 11.05 # m/s
        self.hub.rotor_bending_moment = (3.06 * pi / 8) * AirDensity * (RatedWindSpeed ** 2) * (Solidity * (self.hub.rotor_diameter ** 3)) / self.hub.blade_number
    
        self.hub.gamma = 5.0
        self.hub.MB1_location = np.array([-3.2, 0.0, 1.0])
コード例 #3
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
コード例 #4
0
ファイル: Benchmark2.py プロジェクト: orhuna/wind-turbine-mdo
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()
print "Estimate of Hub Component Sizes for the Baseline 5 MW Reference Turbine"
print "Hub Components"
print '  Hub: {0:8.1f} kg'.format(hubS.hub.mass)  # 31644.47
print '  Pitch system: {0:8.1f} kg'.format(hubS.pitchSystem.mass) # 17003.98
print '  Nose cone: {0:8.1f} kg'.format(hubS.spinner.mass) # 1810.50
コード例 #5
0
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()
print "Estimate of Hub Component Sizes for the Baseline 5 MW Reference Turbine"
print "Hub Components"
print '  Hub: {0:8.1f} kg'.format(hubS.hub.mass)  # 31644.47
print '  Pitch system: {0:8.1f} kg'.format(hubS.pitchSystem.mass)  # 17003.98
print '  Nose cone: {0:8.1f} kg'.format(hubS.spinner.mass)  # 1810.50
コード例 #6
0
print 'ratedConditions.T =', rotor.ratedConditions.T
print 'ratedConditions.Q =', rotor.ratedConditions.Q
print 'Rated Power =', rotor.control.ratedPower/1000
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

################################################################################
### 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.B 
hubS.blade_root_diameter = 3.542
hubS.blade_root_diameter = 2.5

hubS.L_rb = rotor.Rhub
hubS.MB1_location = np.array([-0.5, 0.0, 0.0])
hubS.machine_rating = rotor.control.ratedPower/1000

hubS.run()

print "Estimate of Hub Component Sizes for the Baseline 5 MW Reference Turbine"
print "Hub Components"
print '  Hub: {0:8.1f} kg'.format(hubS.hub.mass)  # 31644.47
print '  Pitch system: {0:8.1f} kg'.format(hubS.pitchSystem.mass) # 17003.98
コード例 #7
0
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
ファイル: turbine_se_seam.py プロジェクト: satwik-hub/WISDEM
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.
    """

    #SEAM variables ----------------------------------
    #d2e = Float(0.73, iotype='in', desc='Dollars to Euro ratio'
    assembly.add(
        'rated_power',
        Float(3000.,
              iotype='in',
              units='kW',
              desc='Turbine rated power',
              group='Global'))
    assembly.add(
        'hub_height',
        Float(100., iotype='in', units='m', desc='Hub height', group='Global'))
    assembly.add(
        'rotor_diameter',
        Float(110.,
              iotype='in',
              units='m',
              desc='Rotor diameter',
              group='Global'))
    # assembly.add('site_type',Enum('onshore', values=('onshore', 'offshore'), iotype='in', desc='Site type', group='Global'))
    assembly.add(
        'tower_bottom_diameter',
        Float(4., iotype='in', desc='Tower bottom diameter', group='Global'))
    assembly.add(
        'tower_top_diameter',
        Float(2., iotype='in', desc='Tower top diameter', group='Global'))
    assembly.add('project_lifetime',
                 Float(iotype='in', desc='Operating years', group='Global'))

    assembly.add(
        'rho_steel',
        Float(7.8e3, iotype='in', desc='density of steel', group='Tower'))

    assembly.add(
        'lifetime_cycles',
        Float(1.e7,
              iotype='in',
              desc='Equivalent lifetime cycles',
              group='Rotor'))
    assembly.add(
        'stress_limit_extreme_tower',
        Float(iotype='in',
              units='MPa',
              desc='Tower ultimate strength',
              group='Tower'))
    assembly.add(
        'stress_limit_fatigue_tower',
        Float(iotype='in',
              units='MPa',
              desc='Tower fatigue strength',
              group='Tower'))
    assembly.add(
        'safety_factor_tower',
        Float(iotype='in', desc='Tower loads safety factor', group='Tower'))
    assembly.add('PMtarget_tower',
                 Float(1., iotype='in', desc='', group='Tower'))
    assembly.add(
        'wohler_exponent_tower',
        Float(4.,
              iotype='in',
              desc='Tower fatigue Wohler exponent',
              group='Tower'))

    assembly.add('tower_z', Array(iotype='out', desc='Tower discretization'))
    assembly.add('tower_wall_thickness',
                 Array(iotype='out', units='m', desc='Tower wall thickness'))
    assembly.add('tower_mass',
                 Float(iotype='out', units='kg', desc='Tower mass'))

    assembly.add(
        'tsr',
        Float(iotype='in',
              units='m',
              desc='Design tip speed ratio',
              group='Aero'))
    assembly.add(
        'F', Float(iotype='in', desc='Rotor power loss factor', group='Aero'))

    assembly.add(
        'wohler_exponent_blade_flap',
        Float(iotype='in', desc='Wohler Exponent blade flap', group='Rotor'))
    assembly.add('nSigma4fatFlap', Float(iotype='in', desc='', group='Loads'))
    assembly.add('nSigma4fatTower', Float(iotype='in', desc='', group='Loads'))
    assembly.add('dLoad_dU_factor_flap',
                 Float(iotype='in', desc='', group='Loads'))
    assembly.add('dLoad_dU_factor_tower',
                 Float(iotype='in', desc='', group='Loads'))
    assembly.add(
        'blade_edge_dynload_factor_ext',
        Float(iotype='in',
              desc='Extreme dynamic edgewise loads factor',
              group='Loads'))
    assembly.add(
        'blade_edge_dynload_factor_fat',
        Float(iotype='in',
              desc='Fatigue dynamic edgewise loads factor',
              group='Loads'))
    assembly.add('PMtarget_blades',
                 Float(1., iotype='in', desc='', group='Rotor'))

    assembly.add('max_tipspeed',
                 Float(iotype='in', desc='Maximum tip speed', group='Aero'))
    assembly.add(
        'n_wsp',
        Int(iotype='in', desc='Number of wind speed bins', group='Aero'))
    assembly.add(
        'min_wsp',
        Float(0.0,
              iotype='in',
              units='m/s',
              desc='min wind speed',
              group='Aero'))
    assembly.add(
        'max_wsp',
        Float(iotype='in', units='m/s', desc='max wind speed', group='Aero'))

    assembly.add(
        'turbulence_int',
        Float(iotype='in',
              desc='Reference turbulence intensity',
              group='Plant_AEP'))
    # assembly.add('WeibullInput', Bool(True, iotype='in', desc='Flag for Weibull input', group='AEP'))
    assembly.add(
        'weibull_C',
        Float(iotype='in',
              units='m/s',
              desc='Weibull scale factor',
              group='AEP'))
    assembly.add(
        'weibull_k',
        Float(iotype='in', desc='Weibull shape or form factor', group='AEP'))

    assembly.add(
        'blade_sections',
        Int(iotype='in', desc='number of sections along blade', group='Rotor'))
    assembly.add(
        'wohler_exponent_blade_flap',
        Float(iotype='in',
              desc='Blade flap fatigue Wohler exponent',
              group='Rotor'))
    assembly.add(
        'MaxChordrR',
        Float(iotype='in',
              units='m',
              desc='Spanwise position of maximum chord',
              group='Rotor'))
    assembly.add(
        'tif_blade_root_flap_ext',
        Float(1.,
              iotype='in',
              desc='Technology improvement factor flap extreme',
              group='Rotor'))
    assembly.add(
        'tif_blade_root_edge_ext',
        Float(1.,
              iotype='in',
              desc='Technology improvement factor edge extreme',
              group='Rotor'))
    assembly.add(
        'tif_blade_root_flap_fat',
        Float(1.,
              iotype='in',
              desc='Technology improvement factor flap LEQ',
              group='Rotor'))
    assembly.add(
        'sc_frac_flap',
        Float(iotype='in', desc='spar cap fraction of chord', group='Rotor'))
    assembly.add(
        'sc_frac_edge',
        Float(iotype='in',
              desc='spar cap fraction of thickness',
              group='Rotor'))
    assembly.add(
        'safety_factor_blade',
        Float(iotype='in', desc='Blade loads safety factor', group='Rotor'))
    assembly.add(
        'stress_limit_extreme_blade',
        Float(iotype='in',
              units='MPa',
              desc='Blade ultimate strength',
              group='Rotor'))
    assembly.add(
        'stress_limit_fatigue_blade',
        Float(iotype='in',
              units='MPa',
              desc='Blade fatigue strength',
              group='Rotor'))
    assembly.add(
        'AddWeightFactorBlade',
        Float(iotype='in',
              desc='Additional weight factor for blade shell',
              group='Rotor'))
    assembly.add(
        'blade_material_density',
        Float(iotype='in',
              units='kg/m**3',
              desc='Average density of blade materials',
              group='Rotor'))

    assembly.add('blade_mass',
                 Float(iotype='out', units='kg', desc='Blade mass'))

    # assembly.add('mean_wsp', Float(iotype = 'in', units = 'm/s', desc = 'mean wind speed', group='Aero'))  # [m/s]
    assembly.add('air_density',
                 Float(iotype='in',
                       units='kg/m**3',
                       desc='density of air',
                       group='Plant_AEP'))  # [kg / m^3]
    assembly.add('max_Cp', Float(iotype='in', desc='max CP', group='Aero'))
    assembly.add(
        'gearloss_const',
        Float(iotype='in', desc='Gear loss constant', group='Drivetrain'))
    assembly.add(
        'gearloss_var',
        Float(iotype='in', desc='Gear loss variable', group='Drivetrain'))
    assembly.add('genloss',
                 Float(iotype='in', desc='Generator loss', group='Drivetrain'))
    assembly.add('convloss',
                 Float(iotype='in', desc='Converter loss', group='Drivetrain'))

    # Outputs
    assembly.add(
        'rated_wind_speed',
        Float(units='m / s', iotype='out', desc='wind speed for rated power'))
    assembly.add(
        'ideal_power_curve',
        Array(iotype='out',
              units='kW',
              desc='total power before losses and turbulence'))
    assembly.add(
        'power_curve',
        Array(iotype='out',
              units='kW',
              desc='total power including losses and turbulence'))
    assembly.add(
        'wind_curve',
        Array(iotype='out',
              units='m/s',
              desc='wind curve associated with power curve'))

    assembly.add(
        'aep',
        Float(iotype='out',
              units='mW*h',
              desc='Annual energy production in mWh'))
    assembly.add(
        'total_aep',
        Float(iotype='out',
              units='mW*h',
              desc='AEP for total years of production'))

    # END SEAM Variables ----------------------

    # Add SEAM components and connections
    assembly.add('loads', SEAMLoads())
    assembly.add('tower_design', SEAMTower(21))
    assembly.add('blade_design', SEAMBladeStructure())
    assembly.add('aep_calc', SEAM_PowerCurve())
    assembly.driver.workflow.add(
        ['loads', 'tower_design', 'blade_design', 'aep_calc'])

    assembly.connect('loads.tower_bottom_moment_max',
                     'tower_design.tower_bottom_moment_max')
    assembly.connect('loads.tower_bottom_moment_leq',
                     'tower_design.tower_bottom_moment_leq')

    assembly.connect('loads.blade_root_flap_max',
                     'blade_design.blade_root_flap_max')
    assembly.connect('loads.blade_root_edge_max',
                     'blade_design.blade_root_edge_max')
    assembly.connect('loads.blade_root_flap_leq',
                     'blade_design.blade_root_flap_leq')
    assembly.connect('loads.blade_root_edge_leq',
                     'blade_design.blade_root_edge_leq')

    connect_io(assembly, assembly.aep_calc)
    connect_io(assembly, assembly.loads)
    connect_io(assembly, assembly.tower_design)
    connect_io(assembly, assembly.blade_design)

    # End SEAM add components and connections -------------

    if with_new_nacelle:
        assembly.add('hub', HubSE())
        assembly.add('hubSystem', Hub_System_Adder_drive())
        if with_3pt_drive:
            assembly.add('nacelle', Drive3pt())
        else:
            assembly.add('nacelle', Drive4pt())
    else:
        assembly.add('nacelle', DriveWPACT())
        assembly.add('hub', HubWPACT())

    assembly.driver.workflow.add(['hub', 'nacelle'])
    if with_new_nacelle:
        assembly.driver.workflow.add(['hubSystem'])

    # connections to hub and hub system
    assembly.connect('blade_design.blade_mass', 'hub.blade_mass')
    assembly.connect('loads.blade_root_flap_max', 'hub.rotor_bending_moment')
    assembly.connect('rotor_diameter', ['hub.rotor_diameter'])
    assembly.connect('blade_design.blade_root_diameter',
                     'hub.blade_root_diameter')
    assembly.add('blade_number',
                 Int(3, iotype='in', desc='number of blades', group='Aero'))
    assembly.connect('blade_number', 'hub.blade_number')
    if with_new_nacelle:
        assembly.connect('rated_power', '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.add('rotor_tilt',
                     Float(5.0, iotype='in', desc='rotor tilt', group='Rotor'))
        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 * aep_calc.rated_torque', 'nacelle.rotor_torque')
    assembly.connect('loads.max_thrust', 'nacelle.rotor_thrust')
    assembly.connect('aep_calc.rated_speed', 'nacelle.rotor_speed')
    assembly.connect('rated_power', 'nacelle.machine_rating')
    assembly.add('generator_speed',
                 Float(1173.7,
                       iotype='in',
                       units='rpm',
                       desc='speed of generator',
                       group='Drivetrain'))  #  - should be in nacelle
    assembly.connect('generator_speed/aep_calc.rated_speed',
                     'nacelle.gear_ratio')
    assembly.connect('tower_top_diameter', 'nacelle.tower_top_diameter')
    assembly.connect(
        'blade_number * blade_design.blade_mass + 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('blade_number', 'nacelle.blade_number')
        assembly.connect('rotor_tilt', 'nacelle.shaft_angle')
        assembly.connect('333.3 * rated_power / 1000.0',
                         'nacelle.shrink_disc_mass')
        assembly.connect('blade_design.blade_root_diameter',
                         'nacelle.blade_root_diameter')

        #moments - ignoring for now (nacelle will use internal defaults)
        #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('1.5 * aep_calc.rated_torque',
                         '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 - ignoring for now (nacelle will use internal defaults)
        #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('loads.max_thrust', 'nacelle.rotor_force_x')
コード例 #9
0
# 1 ---------

from math import pi
import numpy as np
from drivese.hub import HubSE
from drivese.drive import Drive4pt

# 1 ---------
# 2 ---------

# simple test of hub model

# NREL 5 MW turbine

hubS = HubSE()
hubS.rotor_diameter = 126.0  # m
hubS.blade_number = 3
hubS.blade_root_diameter = 3.542

hubS.L_rb = 0.5
hubS.gamma = 5.0
hubS.MB1_location = np.array([-0.5, 0.0, 0.0])
hubS.machine_rating = 5000.0

# 2 ----------
# 3 ----------

hubS.run()

# 3 ----------
# 4 ----------
コード例 #10
0
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
コード例 #11
0
ファイル: example.py プロジェクト: WISDEM/DriveSE
# 1 ---------

from math import pi
import numpy as np
from drivese.hub import HubSE
from drivese.drive import Drive4pt

# 1 ---------
# 2 ---------

# simple test of hub model

# NREL 5 MW turbine

hubS = HubSE()
hubS.rotor_diameter = 126.0 # m
hubS.blade_number  = 3
hubS.blade_root_diameter   = 3.542

hubS.L_rb = 0.5
hubS.gamma = 5.0
hubS.MB1_location = np.array([-0.5, 0.0, 0.0])
hubS.machine_rating = 5000.0

# 2 ----------
# 3 ----------

hubS.run()

# 3 ----------
# 4 ----------
コード例 #12
0
ファイル: turbine.py プロジェクト: satwik-hub/WISDEM
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')