def test3(self):

        pw = PowerWind()
        pw.Uref = 10.0
        pw.zref = 100.0
        pw.z0 = 0.0
        pw.z = np.linspace(-10.0, 90.0, 20)
        pw.shearExp = 0.2
        pw.betaWind = 5.0


        names, errors = check_gradient(pw)

        tol = 1e-6
        for name, err in zip(names, errors):

            try:
                self.assertLessEqual(err, tol)
            except AssertionError, e:
                print '*** error in:', name
                raise e
示例#2
0
    def setUp(self):

        z = np.linspace(0.0, 100.0, 20)
        nPoints = len(z)
        Uref = 10.0
        zref = 100.0
        z0 = 0.001  #Fails when z0 = 0, What to do here?
        shearExp = 0.2
        betaWind = 0.0

        prob = Problem()
        root = prob.root = Group()
        root.add('p1', IndepVarComp('z', z))
        root.add('p2', IndepVarComp('zref', zref))
        root.add('p3', IndepVarComp('Uref', Uref))
        root.add('p', PowerWind(nPoints))

        root.connect('p1.z', 'p.z')
        root.connect('p2.zref', 'p.zref')
        root.connect('p3.Uref', 'p.Uref')

        prob.driver.add_objective('p.U', scaler=1E-6)

        prob.driver.add_desvar('p1.z',
                               lower=np.ones(nPoints),
                               upper=np.ones(nPoints) * 1000,
                               scaler=1E-6)
        prob.driver.add_desvar('p2.zref', lower=0, upper=1000, scaler=1E-6)
        prob.driver.add_desvar('p3.Uref', lower=0, upper=1000, scaler=1E-6)

        prob.setup()

        prob['p.z0'] = z0
        prob['p.shearExp'] = shearExp
        prob['p.betaWind'] = betaWind

        prob.run()

        print prob['p.U']

        self.J = prob.check_total_derivatives(out_stream=None)
    def test1(self):

        pw = PowerWind()
        pw.Uref = 10.0
        pw.zref = 100.0
        pw.z0 = 0.0
        pw.z = np.linspace(0.0, 100.0, 20)
        pw.shearExp = 0.2
        pw.betaWind = 0.0

        names, errors = check_gradient(pw)

        tol = 1e-6
        for name, err in zip(names, errors):

            if name == 'd_U[0] / d_z[0]':
                continue  # the derivative at z==0 is a discontinuity.  this node must not move in the optimization

            try:
                self.assertLessEqual(err, tol)
            except AssertionError, e:
                print '*** error in:', name
                raise e
    def test3(self):

        pw = PowerWind()
        pw.Uref = 10.0
        pw.zref = 100.0
        pw.z0 = 0.0
        pw.z = np.linspace(-10.0, 90.0, 20)
        pw.shearExp = 0.2
        pw.betaWind = 5.0

        names, errors = check_gradient(pw)

        tol = 1e-6
        for name, err in zip(names, errors):

            try:
                self.assertLessEqual(err, tol)
            except AssertionError, e:
                print "*** error in:", name
                raise e
    def test1(self):

        pw = PowerWind()
        pw.Uref = 10.0
        pw.zref = 100.0
        pw.z0 = 0.0
        pw.z = np.linspace(0.0, 100.0, 20)
        pw.shearExp = 0.2
        pw.betaWind = 0.0

        names, errors = check_gradient(pw)

        tol = 1e-6
        for name, err in zip(names, errors):

            if name == "d_U[0] / d_z[0]":
                continue  # the derivative at z==0 is a discontinuity.  this node must not move in the optimization

            try:
                self.assertLessEqual(err, tol)
            except AssertionError, e:
                print "*** error in:", name
                raise e
示例#6
0
文件: tower.py 项目: pjstanle/TowerSE
        self.connect('gc.manufacturability', 'manufacturability')


if __name__ == '__main__':


    optimize = False

    # --- 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, 43.8, 87.6]
    tower.d_param = [6.0, 4.935, 3.87]
    tower.t_param = [0.027*1.3, 0.023*1.3, 0.019*1.3]
    n = 15
    tower.z_full = np.linspace(0.0, 87.6, n)
    tower.L_reinforced = 30.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)
示例#7
0
def configure_nrel5mw_turbine(turbine, wind_class='I', sea_depth=0.0):
    """
    Inputs:
        rotor = RotorSE()
        nacelle = DriveSE()
        tower = TowerSE()
        wind_class : str ('I', 'III', 'Offshore' - selected wind class for project)
        sea_depth : float (sea depth if an offshore wind plant)
    """

    # === Turbine ===
    turbine.rho = 1.225  # (Float, kg/m**3): density of air
    turbine.mu = 1.81206e-5  # (Float, kg/m/s): dynamic viscosity of air
    turbine.shear_exponent = 0.2  # (Float): shear exponent
    turbine.hub_height = 90.0  # (Float, m): hub height
    turbine.turbine_class = 'I'  # (Enum): IEC turbine class
    turbine.turbulence_class = 'B'  # (Enum): IEC turbulence class class
    turbine.cdf_reference_height_wind_speed = 90.0  # (Float): reference hub height for IEC wind speed (used in CDF calculation)
    turbine.g = 9.81  # (Float, m/s**2): acceleration of gravity
    # ======================

    # === rotor ===
    # --- blade grid ---
    turbine.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 aerodynamic grid on unit radius
    turbine.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
    ])  # (Array): initial structural grid on unit radius
    turbine.rotor.idx_cylinder_aero = 3  # (Int): first idx in r_aero_unit of non-cylindrical section, constant twist inboard of here
    turbine.rotor.idx_cylinder_str = 14  # (Int): first idx in r_str_unit of non-cylindrical section
    turbine.rotor.hubFraction = 0.025  # (Float): hub location as fraction of radius
    # ------------------

    # --- blade geometry ---
    turbine.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
    ])  # (Array): new aerodynamic grid on unit radius
    turbine.rotor.r_max_chord = 0.23577  # (Float): location of max chord on unit radius
    turbine.rotor.chord_sub = [
        3.2612, 4.5709, 3.3178, 1.4621
    ]  # (Array, m): chord at control points. defined at hub, then at linearly spaced locations from r_max_chord to tip
    turbine.rotor.theta_sub = [
        13.2783, 7.46036, 2.89317, -0.0878099
    ]  # (Array, deg): twist at control points.  defined at linearly spaced locations from r[idx_cylinder] to tip
    turbine.rotor.precurve_sub = [
        0.0, 0.0, 0.0
    ]  # (Array, m): precurve at control points.  defined at same locations at chord, starting at 2nd control point (root must be zero precurve)
    turbine.rotor.delta_precurve_sub = [
        0.0, 0.0, 0.0
    ]  # (Array, m): adjustment to precurve to account for curvature from loading
    turbine.rotor.sparT = [0.05, 0.047754, 0.045376, 0.031085, 0.0061398
                           ]  # (Array, m): spar cap thickness parameters
    turbine.rotor.teT = [0.1, 0.09569, 0.06569, 0.02569, 0.00569
                         ]  # (Array, m): trailing-edge thickness parameters
    turbine.rotor.bladeLength = 61.5  # (Float, m): blade length (if not precurved or swept) otherwise length of blade before curvature
    turbine.rotor.delta_bladeLength = 0.0  # (Float, m): adjustment to blade length to account for curvature from loading
    turbine.rotor.precone = 2.5  # (Float, deg): precone angle
    turbine.rotor.tilt = 5.0  # (Float, deg): shaft tilt
    turbine.rotor.yaw = 0.0  # (Float, deg): yaw error
    turbine.rotor.nBlades = 3  # (Int): number of blades
    # ------------------

    # --- airfoil files ---
    import rotorse
    #basepath = os.path.join('5MW_files', '5MW_AFFiles')
    basepath = os.path.join('..', 'reference_turbines', 'nrel5mw', 'airfoils')

    # 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]]
    turbine.rotor.airfoil_files = af  # (List): names of airfoil file
    # ----------------------

    # --- control ---
    turbine.rotor.control.Vin = 3.0  # (Float, m/s): cut-in wind speed
    turbine.rotor.control.Vout = 25.0  # (Float, m/s): cut-out wind speed
    turbine.rotor.control.ratedPower = 5e6  # (Float, W): rated power
    turbine.rotor.control.minOmega = 0.0  # (Float, rpm): minimum allowed rotor rotation speed
    turbine.rotor.control.maxOmega = 12.0  # (Float, rpm): maximum allowed rotor rotation speed
    turbine.rotor.control.tsr = 7.55  # (Float): tip-speed ratio in Region 2 (should be optimized externally)
    turbine.rotor.control.pitch = 0.0  # (Float, deg): pitch angle in region 2 (and region 3 for fixed pitch machines)
    turbine.rotor.pitch_extreme = 0.0  # (Float, deg): worst-case pitch at survival wind condition
    turbine.rotor.azimuth_extreme = 0.0  # (Float, deg): worst-case azimuth at survival wind condition
    turbine.rotor.VfactorPC = 0.7  # (Float): fraction of rated speed at which the deflection is assumed to representative throughout the power curve calculation
    # ----------------------

    # --- aero and structural analysis options ---
    turbine.rotor.nSector = 4  # (Int): number of sectors to divide rotor face into in computing thrust and power
    turbine.rotor.npts_coarse_power_curve = 20  # (Int): number of points to evaluate aero analysis at
    turbine.rotor.npts_spline_power_curve = 200  # (Int): number of points to use in fitting spline to power curve
    turbine.rotor.AEP_loss_factor = 1.0  # (Float): availability and other losses (soiling, array, etc.)
    turbine.rotor.drivetrainType = 'geared'  # (Enum)
    turbine.rotor.nF = 5  # (Int): number of natural frequencies to compute
    turbine.rotor.dynamic_amplication_tip_deflection = 1.35  # (Float): a dynamic amplification factor to adjust the static deflection calculation
    # ----------------------

    # --- materials and composite layup  ---
    #basepath = os.path.join('5MW_files', '5MW_PrecompFiles')
    basepath = os.path.join('..', 'reference_turbines', 'nrel5mw', 'blade')

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

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

    turbine.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): 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
    turbine.rotor.sector_idx_strain_spar = [
        2
    ] * ncomp  # (Array): index of sector for spar (PreComp definition of sector)
    turbine.rotor.sector_idx_strain_te = [
        3
    ] * ncomp  # (Array): index of sector for trailing-edge (PreComp definition of sector)
    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
    ])
    turbine.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
        ]
    )  # (Array, m): chord distribution for reference section, thickness of structural layup scaled with reference thickness (fixed t/c for this case)

    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'))

    turbine.rotor.materials = materials  # (List): list of all Orthotropic2DMaterial objects used in defining the geometry
    turbine.rotor.upperCS = upper  # (List): list of CompositeSection objections defining the properties for upper surface
    turbine.rotor.lowerCS = lower  # (List): list of CompositeSection objections defining the properties for lower surface
    turbine.rotor.websCS = webs  # (List): list of CompositeSection objections defining the properties for shear webs
    turbine.rotor.profile = profile  # (List): airfoil shape at each radial position
    # --------------------------------------

    strain_ult_spar = 1.0e-2
    strain_ult_te = 2500 * 1e-6

    # --- fatigue ---
    turbine.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): nondimensional radial locations of damage equivalent moments
    turbine.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. x-direction
    turbine.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
    ])  # (Array, N*m): damage equivalent moments about blade c.s. y-direction
    turbine.rotor.strain_ult_spar = 1.0e-2  # (Float): ultimate strain in spar cap
    turbine.rotor.strain_ult_te = 2500 * 1e-6 * 2  # (Float): uptimate strain in trailing-edge panels, note that I am putting a factor of two for the damage part only.
    turbine.rotor.eta_damage = 1.35 * 1.3 * 1.0  # (Float): safety factor for fatigue
    turbine.rotor.m_damage = 10.0  # (Float): slope of S-N curve for fatigue analysis
    turbine.rotor.N_damage = 365 * 24 * 3600 * 20.0  # (Float): number of cycles used in fatigue analysis  TODO: make function of rotation speed
    # ----------------
    # =================

    # === nacelle ======
    turbine.nacelle.L_ms = 1.0  # (Float, m): main shaft length downwind of main bearing in low-speed shaft
    turbine.nacelle.L_mb = 2.5  # (Float, m): main shaft length in low-speed shaft

    turbine.nacelle.h0_front = 1.7  # (Float, m): height of Ibeam in bedplate front
    turbine.nacelle.h0_rear = 1.35  # (Float, m): height of Ibeam in bedplate rear

    turbine.nacelle.drivetrain_design = 'geared'
    turbine.nacelle.crane = True  # (Bool): flag for presence of crane
    turbine.nacelle.bevel = 0  # (Int): Flag for the presence of a bevel stage - 1 if present, 0 if not
    turbine.nacelle.gear_configuration = 'eep'  # (Str): tring that represents the configuration of the gearbox (stage number and types)

    turbine.nacelle.Np = [3, 3, 1]  # (Array): number of planets in each stage
    turbine.nacelle.ratio_type = 'optimal'  # (Str): optimal or empirical stage ratios
    turbine.nacelle.shaft_type = 'normal'  # (Str): normal or short shaft length
    #turbine.nacelle.shaft_angle = 5.0  # (Float, deg): Angle of the LSS inclindation with respect to the horizontal
    turbine.nacelle.shaft_ratio = 0.10  # (Float): Ratio of inner diameter to outer diameter.  Leave zero for solid LSS
    turbine.nacelle.carrier_mass = 8000.0  # estimated for 5 MW
    turbine.nacelle.mb1Type = 'CARB'  # (Str): Main bearing type: CARB, TRB or SRB
    turbine.nacelle.mb2Type = 'SRB'  # (Str): Second bearing type: CARB, TRB or SRB
    turbine.nacelle.yaw_motors_number = 8.0  # (Float): number of yaw motors
    turbine.nacelle.uptower_transformer = True
    turbine.nacelle.flange_length = 0.5  #m
    turbine.nacelle.gearbox_cm = 0.1
    turbine.nacelle.hss_length = 1.5
    turbine.nacelle.overhang = 5.0  #TODO - should come from turbine configuration level

    turbine.nacelle.check_fatigue = 0  #0 if no fatigue check, 1 if parameterized fatigue check, 2 if known loads inputs

    # TODO: should come from rotor (these are FAST outputs)
    turbine.nacelle.DrivetrainEfficiency = 0.95
    #turbine.nacelle.rotor_bending_moment_x = 330770.0# Nm
    #turbine.nacelle.rotor_bending_moment_y = -16665000.0 # Nm
    #turbine.nacelle.rotor_bending_moment_z = 2896300.0 # Nm
    #turbine.nacelle.rotor_force_x = 599610.0 # N
    #turbine.nacelle.rotor_force_y = 186780.0 # N
    #turbine.nacelle.rotor_force_z = -842710.0 # N'''

    #turbine.nacelle.h0_rear = 1.35 # only used in drive smooth
    #turbine.nacelle.h0_front = 1.7

    # =================

    # === tower ===

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

    if turbine.sea_depth <> 0.0:
        turbine.tower.replace('wave1', LinearWaves())
        turbine.tower.replace('wave2', LinearWaves())

        turbine.tower.wave1.Uc = 0.0
        turbine.tower.wave1.hs = 8.0 * 1.86
        turbine.tower.wave1.T = 10.0
        turbine.tower.wave1.z_surface = 0.0
        turbine.tower.wave1.z_floor = -sea_depth
        turbine.tower.wave1.g = 9.81
        turbine.tower.wave1.betaWave = 0.0

        turbine.tower.wave2.Uc = 0.0
        turbine.tower.wave2.hs = 8.0 * 1.86
        turbine.tower.wave2.T = 10.0
        turbine.tower.wave2.z_surface = 0.0
        turbine.tower.wave2.z_floor = -sea_depth
        turbine.tower.wave2.g = 9.81
        turbine.tower.wave2.betaWave = 0.0

    if turbine.sea_depth == 0.0:
        # --- geometry ----
        #np.insert(turbine.tower.z_param,0,87.9)
        #np.insert(turbine.tower.z_param,0,43.8)
        #np.insert(turbine.tower.z_param,0,0.0)
        turbine.tower.z_param = [0.0, 43.8, 87.9]
        turbine.tower_d = [6.0, 4.935, 3.87]
        turbine.tower.t_param = [0.027 * 1.3, 0.023 * 1.3, 0.019 * 1.3]
        n = 15
        turbine.tower.z_full = np.linspace(0.0, 87.6, n)
        turbine.tower.L_reinforced = 30.0 * np.ones(n)  # [m] buckling length
        turbine.tower.theta_stress = 0.0 * np.ones(n)
        turbine.tower.yaw = 0.0

        # --- material props ---
        turbine.tower.E = 210e9 * np.ones(n)
        turbine.tower.G = 80.8e9 * np.ones(n)
        turbine.tower.rho = 8500.0 * np.ones(n)
        turbine.tower.sigma_y = 450.0e6 * np.ones(n)
    else:
        # --- geometry ----
        #np.insert(turbine.tower.z_param,0,87.9)
        #np.insert(turbine.tower.z_param,0,43.8)
        #np.insert(turbine.tower.z_param,0,0.0)
        #np.insert(turbine.tower.z_param,0,-20.0)
        turbine.tower.z_param = [-20.0, 0.0, 43.8, 87.9]
        turbine.tower_d = [6.0, 6.0, 4.935, 3.87]
        turbine.tower.t_param = [0.06, 0.027 * 1.3, 0.023 * 1.3, 0.019 * 1.3]
        n = 20
        turbine.tower.z_full = np.linspace(-20, 87.6, n)
        turbine.tower.L_reinforced = 30.0 * np.ones(n)  # [m] buckling length
        turbine.tower.theta_stress = 0.0 * np.ones(n)
        turbine.tower.yaw = 0.0

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

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

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

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

    # if addGravityLoadForExtraMass=True be sure not to double count by adding those force here also
    # # --- loading case 1: max Thrust ---
    #turbine.tower.wind_Uref1 = 11.73732
    turbine.tower.plidx1 = [n - 1]  # at tower top
    turbine.tower.Fx1 = [1284744.19620519]
    turbine.tower.Fy1 = [0.]
    turbine.tower.Fz1 = [-2914124.84400512]
    turbine.tower.Mxx1 = [3963732.76208099]
    turbine.tower.Myy1 = [-2275104.79420872]
    turbine.tower.Mzz1 = [-346781.68192839]
    # # ---------------

    # # --- loading case 2: max wind speed ---
    #turbine.tower.wind_Uref2 = 70.0
    turbine.tower.plidx2 = [n - 1]  # at tower top
    turbine.tower.Fx2 = [930198.60063279]
    turbine.tower.Fy2 = [0.]
    turbine.tower.Fz2 = [-2883106.12368949]
    turbine.tower.Mxx2 = [-1683669.22411597]
    turbine.tower.Myy2 = [-2522475.34625363]
    turbine.tower.Mzz2 = [147301.97023764]
    # # ---------------

    # --- safety factors ---
    turbine.tower.gamma_f = 1.35
    turbine.tower.gamma_m = 1.3
    turbine.tower.gamma_n = 1.0
    turbine.tower.gamma_b = 1.1
    # ---------------

    # --- fatigue ---
    turbine.tower.z_DEL = np.array([
        0.000, 1.327, 3.982, 6.636, 9.291, 11.945, 14.600, 17.255, 19.909,
        22.564, 25.218, 27.873, 30.527, 33.182, 35.836, 38.491, 41.145, 43.800,
        46.455, 49.109, 51.764, 54.418, 57.073, 59.727, 62.382, 65.036, 67.691,
        70.345, 73.000, 75.655, 78.309, 80.964, 83.618, 86.273, 87.600
    ])
    turbine.tower.M_DEL = 1e3 * np.array([
        8.2940E+003, 8.1518E+003, 7.8831E+003, 7.6099E+003, 7.3359E+003,
        7.0577E+003, 6.7821E+003, 6.5119E+003, 6.2391E+003, 5.9707E+003,
        5.7070E+003, 5.4500E+003, 5.2015E+003, 4.9588E+003, 4.7202E+003,
        4.4884E+003, 4.2577E+003, 4.0246E+003, 3.7942E+003, 3.5664E+003,
        3.3406E+003, 3.1184E+003, 2.8977E+003, 2.6811E+003, 2.4719E+003,
        2.2663E+003, 2.0673E+003, 1.8769E+003, 1.7017E+003, 1.5479E+003,
        1.4207E+003, 1.3304E+003, 1.2780E+003, 1.2673E+003, 1.2761E+003
    ])
    turbine.tower.gamma_fatigue = 1.35 * 1.3 * 1.0
    turbine.tower.life = 20.0
    turbine.tower.m_SN = 4
    # ---------------

    # --- constraints ---
    turbine.tower.min_d_to_t = 120.0
    turbine.tower.min_taper = 0.4
    # ---------------

    # ==== Other options

    if wind_class == 'I':
        turbine.rotor.turbine_class = 'I'

    elif wind_class == 'III':
        turbine.rotor.turbine_class = 'III'

        # for fatigue based analysis of class III wind turbine
        turbine.tower.M_DEL = 1.028713178 * 1e3 * np.array([
            7.8792E+003, 7.7507E+003, 7.4918E+003, 7.2389E+003, 6.9815E+003,
            6.7262E+003, 6.4730E+003, 6.2174E+003, 5.9615E+003, 5.7073E+003,
            5.4591E+003, 5.2141E+003, 4.9741E+003, 4.7399E+003, 4.5117E+003,
            4.2840E+003, 4.0606E+003, 3.8360E+003, 3.6118E+003, 3.3911E+003,
            3.1723E+003, 2.9568E+003, 2.7391E+003, 2.5294E+003, 2.3229E+003,
            2.1246E+003, 1.9321E+003, 1.7475E+003, 1.5790E+003, 1.4286E+003,
            1.3101E+003, 1.2257E+003, 1.1787E+003, 1.1727E+003, 1.1821E+003
        ])

        turbine.rotor.Mxb_damage = 1e3 * np.array([
            2.3617E+003, 2.0751E+003, 1.8051E+003, 1.5631E+003, 1.2994E+003,
            1.0388E+003, 8.1384E+002, 6.2492E+002, 4.6916E+002, 3.4078E+002,
            2.3916E+002, 1.5916E+002, 9.9752E+001, 5.6139E+001, 2.6492E+001,
            1.0886E+001, 3.7210E+000, 4.3206E-001
        ])
        turbine.rotor.Myb_damage = 1e3 * np.array([
            2.5492E+003, 2.6261E+003, 2.4265E+003, 2.2308E+003, 1.9882E+003,
            1.7184E+003, 1.4438E+003, 1.1925E+003, 9.6251E+002, 7.5564E+002,
            5.7332E+002, 4.1435E+002, 2.8036E+002, 1.7106E+002, 8.7732E+001,
            3.8678E+001, 1.3942E+001, 1.6600E+000
        ])

    elif wind_class == 'Offshore':
        turbine.rotor.turbine_class = 'I'

    # TODO: these should be specified at the turbine level and connected to other system inputs
    if turbine.sea_depth == 0.0:
        turbine.tower_d = [6.0, 4.935,
                           3.87]  # (Array, m): diameters along tower
    else:
        turbine.tower_d = [6.0, 6.0, 4.935, 3.87]
    turbine.generator_speed = 1173.7  # (Float, rpm)  # generator speed
示例#8
0
    def __init__(self, nSection, nFull):
        super(Column, self).__init__()

        nRefine = (nFull - 1) / nSection

        self.add('cyl_geom',
                 CylinderDiscretization(nSection + 1, nRefine),
                 promotes=[
                     'section_height', 'diameter', 'wall_thickness', 'd_full',
                     't_full'
                 ])

        self.add('cyl_mass',
                 CylinderMass(nFull),
                 promotes=['d_full', 't_full', 'material_density'])

        self.add('col_geom',
                 ColumnGeometry(nSection, nFull),
                 promotes=[
                     'water_depth', 'freeboard', 'fairlead', 'z_full',
                     'z_param', 'z_section', 'draft', 'draft_depth_ratio',
                     'fairlead_draft_ratio'
                 ])

        self.add('gc',
                 GeometricConstraints(nSection + 1, diamFlag=True),
                 promotes=[
                     'min_taper', 'min_d_to_t', 'manufacturability',
                     'weldability'
                 ])

        self.add('bulk',
                 BulkheadMass(nSection, nFull),
                 promotes=[
                     'z_full', 'z_param', 'd_full', 't_full', 'rho',
                     'bulkhead_mass_factor', 'bulkhead_thickness',
                     'bulkhead_mass', 'bulkhead_I_keel'
                 ])

        self.add('stiff',
                 StiffenerMass(nSection, nFull),
                 promotes=[
                     'd_full', 't_full', 'z_full', 'z_param', 'rho',
                     'ring_mass_factor', 'stiffener_mass', 'stiffener_I_keel',
                     'stiffener_web_height', 'stiffener_web_thickness',
                     'stiffener_flange_width', 'stiffener_flange_thickness',
                     'stiffener_spacing', 'flange_spacing_ratio',
                     'stiffener_radius_ratio'
                 ])

        self.add(
            'col',
            ColumnProperties(nFull),
            promotes=[
                'water_density', 'd_full', 't_full', 'z_full', 'z_section',
                'permanent_ballast_density', 'permanent_ballast_height',
                'bulkhead_mass', 'stiffener_mass', 'column_mass_factor',
                'outfitting_mass_fraction', 'bulkhead_I_keel',
                'stiffener_I_keel', 'ballast_cost_rate',
                'tapered_col_cost_rate', 'outfitting_cost_rate',
                'variable_ballast_interp_mass', 'variable_ballast_interp_zpts',
                'z_center_of_mass', 'z_center_of_buoyancy', 'Awater', 'Iwater',
                'I_column', 'displaced_volume', 'added_mass', 'total_mass',
                'total_cost', 'ballast_mass', 'ballast_I_keel', 'ballast_z_cg'
            ])

        self.add('wind',
                 PowerWind(nFull),
                 promotes=['Uref', 'zref', 'shearExp', 'z0'])
        self.add('wave', LinearWaves(nFull), promotes=['Uc', 'hmax', 'T'])
        self.add('windLoads',
                 CylinderWindDrag(nFull),
                 promotes=['cd_usr', 'beta'])
        self.add('waveLoads',
                 CylinderWaveDrag(nFull),
                 promotes=['cm', 'cd_usr'])
        self.add('distLoads',
                 AeroHydroLoads(nFull),
                 promotes=['Px', 'Py', 'Pz', 'qdyn', 'yaw'])

        self.add('buck',
                 ColumnBuckling(nSection, nFull),
                 promotes=[
                     'd_full', 't_full', 'z_full', 'z_section', 'z_param', 'E',
                     'nu', 'yield_stress', 'loading', 'stack_mass_in',
                     'stiffener_web_height', 'stiffener_web_thickness',
                     'stiffener_flange_width', 'stiffener_flange_thickness',
                     'stiffener_spacing', 'flange_compactness',
                     'web_compactness', 'axial_local_unity',
                     'axial_general_unity', 'external_local_unity',
                     'external_general_unity'
                 ])

        self.connect('diameter', 'gc.d')
        self.connect('wall_thickness', 'gc.t')
        self.connect('cyl_geom.z_param', 'col_geom.z_param_in')
        self.connect('cyl_geom.z_full',
                     ['cyl_mass.z_full', 'col_geom.z_full_in'])

        self.connect('cyl_mass.section_center_of_mass',
                     'col_geom.section_center_of_mass')

        self.connect('cyl_mass.mass', 'col.shell_mass')
        self.connect('cyl_mass.I_base', 'col.shell_I_keel')
        self.connect('material_density', 'rho')

        self.connect('total_mass', 'buck.section_mass')

        self.connect('water_depth', 'wave.z_floor')
        self.connect(
            'z_full',
            ['wind.z', 'wave.z', 'windLoads.z', 'waveLoads.z', 'distLoads.z'])
        self.connect('d_full', ['windLoads.d', 'waveLoads.d'])
        self.connect('beta', 'waveLoads.beta')
        self.connect('z0', 'wave.z_surface')

        self.connect('wind.U', 'windLoads.U')

        self.connect('water_density', ['wave.rho', 'waveLoads.rho'])
        self.connect('wave.U', 'waveLoads.U')
        self.connect('wave.A', 'waveLoads.A')
        self.connect('wave.p', 'waveLoads.p')

        # connections to distLoads1
        self.connect('windLoads.windLoads:Px', 'distLoads.windLoads:Px')
        self.connect('windLoads.windLoads:Py', 'distLoads.windLoads:Py')
        self.connect('windLoads.windLoads:Pz', 'distLoads.windLoads:Pz')
        self.connect('windLoads.windLoads:qdyn', 'distLoads.windLoads:qdyn')
        self.connect('windLoads.windLoads:beta', 'distLoads.windLoads:beta')
        self.connect('windLoads.windLoads:z', 'distLoads.windLoads:z')
        self.connect('windLoads.windLoads:d', 'distLoads.windLoads:d')

        self.connect('waveLoads.waveLoads:Px', 'distLoads.waveLoads:Px')
        self.connect('waveLoads.waveLoads:Py', 'distLoads.waveLoads:Py')
        self.connect('waveLoads.waveLoads:Pz', 'distLoads.waveLoads:Pz')
        self.connect('waveLoads.waveLoads:pt', 'distLoads.waveLoads:qdyn')
        self.connect('waveLoads.waveLoads:beta', 'distLoads.waveLoads:beta')
        self.connect('waveLoads.waveLoads:z', 'distLoads.waveLoads:z')
        self.connect('waveLoads.waveLoads:d', 'distLoads.waveLoads:d')

        self.connect('qdyn', 'buck.pressure')
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
示例#10
0
    def configure(self):

        self.add('pre', JcktLoadPre())
        self.add('windj', PowerWind())
        self.add('windt', PowerWind())
        self.add('wavej', LinearWaves())
        self.add('wavet', LinearWaves())
        self.add('windLoadsj', TowerWindDrag())
        self.add('windLoadst', TowerWindDrag())
        self.add('waveLoadsj', TowerWaveDrag())
        self.add('waveLoadst', TowerWaveDrag())
        self.add('post', JcktLoadPost())

        self.driver.workflow.add([
            'pre', 'windj', 'windt', 'wavej', 'wavet', 'windLoadsj',
            'windLoadst', 'waveLoadsj', 'waveLoadst', 'post'
        ])

        # connections to pre
        self.connect('nlegs', 'pre.nlegs')
        self.connect('nodes', 'pre.nodes')
        self.connect('pillegDs', 'pre.pillegDs')
        self.connect('twrDs', 'pre.twrDs')
        #self.connect('twrTs', 'pre.twrTs')
        self.connect('Twrmems', 'pre.Twrmems')
        self.connect('Legmems', 'pre.Legmems')
        self.connect('Pilemems', 'pre.Pilemems')

        # connections to windj/t
        self.connect('windIns.U50HH', ['windj.Uref', 'windt.Uref'])
        self.connect('windIns.HH + waterIns.wdepth + waterIns.z_floor',
                     ['windj.zref', 'windt.zref'])
        self.connect('pre.pillegZs_out', 'windj.z')
        self.connect('pre.twrZs_out', 'windt.z')
        self.connect('waterIns.wdepth + waterIns.z_floor',
                     ['windj.z0', 'windt.z0'])
        self.connect('windIns.psi', ['windj.betaWind', 'windt.betaWind'])
        self.connect('windIns.al_shear', ['windj.shearExp', 'windt.shearExp'])

        # connections to wavej/t
        self.connect('waterIns.Uc', ['wavej.Uc', 'wavet.Uc'])
        self.connect('waterIns.wdepth + waterIns.z_floor',
                     ['wavej.z_surface', 'wavet.z_surface'])
        self.connect('waterIns.HW', ['wavej.hmax', 'wavet.hmax'])
        self.connect('waterIns.wdepth',
                     ['wavej.wdepth', 'wavet.wdepth'])  #CJB+
        # self.connect('waterIns.T', ['wavej.T', 'wavet.T'])
        self.connect('waterIns.T', 'wavej.T')
        self.connect('waterIns.T', 'wavet.T')
        self.connect('waterIns.z_floor', ['wavej.z_floor', 'wavet.z_floor'])
        self.connect('gravity', ['wavej.g', 'wavet.g'])
        self.connect('waterIns.psi', ['wavej.betaWave', 'wavet.betaWave'])
        self.connect('pre.pillegZs_out', 'wavej.z')
        self.connect('pre.twrZs_out', 'wavet.z')

        # connections to windLoadsj
        self.connect('windj.U', 'windLoadsj.U')
        self.connect('windj.beta', 'windLoadsj.beta')
        self.connect('windIns.rho', 'windLoadsj.rho')
        self.connect('windIns.mu', 'windLoadsj.mu')
        self.connect('windIns.Cdj', 'windLoadsj.cd_usr')
        self.connect('pre.pillegZs_out', 'windLoadsj.z')
        self.connect('pre.pillegDs_out', 'windLoadsj.d')

        # connections to windLoadst
        self.connect('windt.U', 'windLoadst.U')
        self.connect('windt.beta', 'windLoadst.beta')
        self.connect('windIns.rho', 'windLoadst.rho')
        self.connect('windIns.mu', 'windLoadst.mu')
        self.connect('windIns.Cdt', 'windLoadst.cd_usr')
        self.connect('pre.twrZs_out', 'windLoadst.z')
        self.connect('pre.twrDs_out', 'windLoadst.d')

        # connections to waveLoadsj
        self.connect('wavej.U', 'waveLoadsj.U')
        self.connect('wavej.A', 'waveLoadsj.A')
        self.connect('wavej.beta', 'waveLoadsj.beta')
        self.connect('wavej.U0', 'waveLoadsj.U0')
        self.connect('wavej.A0', 'waveLoadsj.A0')
        self.connect('wavej.beta0', 'waveLoadsj.beta0')

        self.connect('waterIns.rho', 'waveLoadsj.rho')
        self.connect('waterIns.mu', 'waveLoadsj.mu')
        self.connect('waterIns.Cm', 'waveLoadsj.cm')
        self.connect('waterIns.Cd', 'waveLoadsj.cd_usr')
        self.connect('waterIns.wlevel', 'waveLoadsj.wlevel')
        self.connect('pre.pillegZs_out', 'waveLoadsj.z')
        self.connect('pre.pillegDs_out', 'waveLoadsj.d')

        # connections to waveLoadst
        self.connect('wavet.U', 'waveLoadst.U')
        self.connect('wavet.A', 'waveLoadst.A')
        self.connect('wavet.beta', 'waveLoadst.beta')
        self.connect('wavet.U0', 'waveLoadst.U0')
        self.connect('wavet.A0', 'waveLoadst.A0')
        self.connect('wavet.beta0', 'waveLoadst.beta0')
        self.connect('waterIns.rho', 'waveLoadst.rho')
        self.connect('waterIns.mu', 'waveLoadst.mu')
        self.connect('waterIns.Cm', 'waveLoadst.cm')
        self.connect('waterIns.Cd', 'waveLoadst.cd_usr')
        self.connect('waterIns.wlevel', 'waveLoadst.wlevel')
        self.connect('pre.twrZs_out', 'waveLoadst.z')
        self.connect('pre.twrDs_out', 'waveLoadst.d')

        # connections to post
        self.connect('windLoadst.windLoads', 'post.towerWindLoads')
        self.connect('waveLoadst.waveLoads', 'post.towerWaveLoads')
        self.connect('windLoadsj.windLoads', 'post.pileLegWindLoads')
        self.connect('waveLoadsj.waveLoads', 'post.pileLegWaveLoads')
        self.connect('pre.pilendIDs', 'post.pilendIDs')
        self.connect('pre.legndIDs', 'post.legndIDs')
        self.connect('pre.twrndIDs', 'post.twrndIDs')
        self.connect('nlegs', 'post.nlegs')
        self.connect('TwrRigidTop', 'post.TwrRigidTop')
        self.connect('RNAinputs', 'post.RNAinputs')
        self.connect('RNA_F', 'post.RNA_F')
        self.connect('al_bat3D', 'post.al_bat3D')
        self.connect('VPFlag', 'post.VPFlag')
        self.connect('waterIns.wdepth', 'post.wdepth')

        # connections to outputs
        self.connect('post.Loadouts', 'Loadouts')
        #self.connect('windLoadst.windLoads','twrWindLoads')
        #self.connect('waveLoadst.waveLoads','twrWaveLoads')
        self.create_passthrough('windLoadst.windLoads')
        self.create_passthrough('waveLoadst.waveLoads')
示例#11
0
    def __init__(self, RefBlade, npts_coarse_power_curve=20, npts_spline_power_curve=200, regulation_reg_II5 = True, regulation_reg_III=True):
        super(RotorAeroPower, self).__init__()

        self.add('rho', IndepVarComp('rho', val=1.225), promotes=['*'])
        self.add('mu', IndepVarComp('mu', val=1.81e-5), promotes=['*'])
        self.add('shearExp', IndepVarComp('shearExp', val=0.2), promotes=['*'])

        self.add('cdf_reference_height_wind_speed', IndepVarComp('cdf_reference_height_wind_speed', val=0.0, units='m', desc='reference hub height for IEC wind speed (used in CDF calculation)'), promotes=['*'])

        self.add('tiploss', IndepVarComp('tiploss', True, pass_by_obj=True), promotes=['*'])
        self.add('hubloss', IndepVarComp('hubloss', True, pass_by_obj=True), promotes=['*'])
        self.add('wakerotation', IndepVarComp('wakerotation', True, pass_by_obj=True), promotes=['*'])
        self.add('usecd', IndepVarComp('usecd', True, pass_by_obj=True), promotes=['*'])
        #self.add('airfoil_files', IndepVarComp('airfoil_files', AirfoilProperties.airfoil_files, pass_by_obj=True), promotes=['*'])
        
        # --- control ---
        self.add('c_Vin', IndepVarComp('control_Vin', val=0.0, units='m/s', desc='cut-in wind speed'), promotes=['*'])
        self.add('c_Vout', IndepVarComp('control_Vout', val=0.0, units='m/s', desc='cut-out wind speed'), promotes=['*'])
        self.add('c_ratedPower', IndepVarComp('control_ratedPower', val=0.0,  units='W', desc='rated power'), promotes=['*'])
        self.add('c_minOmega', IndepVarComp('control_minOmega', val=0.0, units='rpm', desc='minimum allowed rotor rotation speed'), promotes=['*'])
        self.add('c_maxOmega', IndepVarComp('control_maxOmega', val=0.0, units='rpm', desc='maximum allowed rotor rotation speed'), promotes=['*'])
        self.add('c_maxTS', IndepVarComp('control_maxTS', val=0.0, units='m/s', desc='maximum allowed blade tip speed'), promotes=['*'])
        self.add('c_tsr', IndepVarComp('control_tsr', val=0.0, desc='tip-speed ratio in Region 2 (should be optimized externally)'), promotes=['*'])
        self.add('c_pitch', IndepVarComp('control_pitch', val=0.0, units='deg', desc='pitch angle in region 2 (and region 3 for fixed pitch machines)'), promotes=['*'])

        # --- drivetrain efficiency ---
        self.add('drivetrainType', IndepVarComp('drivetrainType', val=DRIVETRAIN_TYPE['GEARED'], pass_by_obj=True), promotes=['*'])


        # --- options ---
        self.add('nSector', IndepVarComp('nSector', val=4, iotype='in', desc='number of sectors to divide rotor face into in computing thrust and power', pass_by_obj=True), promotes=['*'])
        self.add('AEP_loss_factor', IndepVarComp('AEP_loss_factor', val=1.0, desc='availability and other losses (soiling, array, etc.)'), promotes=['*'])

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

        
        # --- Rotor Aero & Power ---
        self.add('rotorGeom', RotorGeometry(RefBlade), promotes=['*'])

        # self.add('tipspeed', MaxTipSpeed())
        self.add('powercurve', RegulatedPowerCurve(RefBlade.npts, npts_coarse_power_curve, npts_spline_power_curve, regulation_reg_II5, regulation_reg_III))
        self.add('wind', PowerWind(1))
        # self.add('cdf', WeibullWithMeanCDF(npts_coarse_power_curve))
        self.add('cdf', RayleighCDF(npts_spline_power_curve))
        self.add('aep', AEP(npts_spline_power_curve))

        self.add('outputs_aero', OutputsAero(npts_coarse_power_curve), promotes=['*'])


        # connections to analysis
        self.connect('r_pts', 'powercurve.r')
        self.connect('chord', 'powercurve.chord')
        self.connect('theta', 'powercurve.theta')
        self.connect('precurve', 'powercurve.precurve')
        self.connect('precurve_tip', 'powercurve.precurveTip')
        self.connect('Rhub', 'powercurve.Rhub')
        self.connect('Rtip', 'powercurve.Rtip')
        self.connect('hub_height', 'powercurve.hubHt')
        self.connect('precone', 'powercurve.precone')
        self.connect('tilt', 'powercurve.tilt')
        self.connect('yaw', 'powercurve.yaw')
        self.connect('airfoils', 'powercurve.airfoils')
        self.connect('nBlades', 'powercurve.B')
        self.connect('rho', 'powercurve.rho')
        self.connect('mu', 'powercurve.mu')
        self.connect('shearExp', 'powercurve.shearExp')
        self.connect('nSector', 'powercurve.nSector')
        self.connect('tiploss', 'powercurve.tiploss')
        self.connect('hubloss', 'powercurve.hubloss')
        self.connect('wakerotation', 'powercurve.wakerotation')
        self.connect('usecd', 'powercurve.usecd')

        # connections to powercurve
        self.connect('drivetrainType', 'powercurve.drivetrainType')
        self.connect('control_Vin', 'powercurve.control_Vin')
        self.connect('control_Vout', 'powercurve.control_Vout')
        self.connect('control_maxTS', 'powercurve.control_maxTS')
        self.connect('control_maxOmega', 'powercurve.control_maxOmega')
        self.connect('control_minOmega', 'powercurve.control_minOmega')
        self.connect('control_pitch', 'powercurve.control_pitch')
        self.connect('control_ratedPower', 'powercurve.control_ratedPower')
        self.connect('control_tsr', 'powercurve.control_tsr')

        # connections to wind
        # self.connect('cdf_reference_mean_wind_speed', 'wind.Uref')
        self.connect('turbineclass.V_mean', 'wind.Uref')
        self.connect('cdf_reference_height_wind_speed', 'wind.zref')
        self.connect('wind_zvec', 'wind.z')
        self.connect('shearExp', 'wind.shearExp')

        # connections to cdf
        self.connect('powercurve.V_spline', 'cdf.x')
        self.connect('wind.U', 'cdf.xbar', src_indices=[0])
        self.connect('shape_parameter', 'cdf.k')

        # connections to aep
        self.connect('cdf.F', 'aep.CDF_V')
        self.connect('powercurve.P_spline', 'aep.P')
        self.connect('AEP_loss_factor', 'aep.lossFactor')

        # connect to outputs
        self.connect('geom.diameter', 'diameter_in')
        self.connect('turbineclass.V_extreme50', 'V_extreme_in')
        self.connect('precurve_tip', 'precurveTip_in')
        self.connect('presweep_tip', 'presweepTip_in')

        self.connect('powercurve.V', 'V_in')
        self.connect('powercurve.P', 'P_in')
        self.connect('aep.AEP', 'AEP_in')
        self.connect('powercurve.rated_V', 'rated_V_in')
        self.connect('powercurve.rated_Omega', 'rated_Omega_in')
        self.connect('powercurve.rated_pitch', 'rated_pitch_in')
        self.connect('powercurve.rated_T', 'rated_T_in')
        self.connect('powercurve.rated_Q', 'rated_Q_in')

        self.deriv_options['type'] = 'fd'
        self.deriv_options['form']      = 'central'
        self.deriv_options['step_calc'] = 'relative'
示例#12
0
def main():  #\
    """Function to Instantiate a TowerSE Assembly: \n
       INPUTS \n
             All hardwired, so edit the quantities below all the way to the line "#________________ DO NOT MODIFY THE FOLLOWING ________________#" \n
             -See TowerSEOpt_Py&MDAOopt.py for more information. \n
       OUTPUTS \n
             mytwr -tower assembly instance \n\n

             Optimization parameters:    \n\n

             f0          -float, target frequency [Hz]
             f0epsilon   -float,  f0*(1+f0epsilon) will not be exceeded \n
             guesses     -Float(n), guesses for all design variables check out DesVar class. \n
             bounds      -Float(n,2), bounds for all design variables check out DesVar class. \n\n
             SAMPLE CALLS: \n
             1.OPTIMIZATION: python towerOpt_ExtCobyla.py C:\RRD\PYTHON\WISDEM\towerSE\src\towerse\MyTowerInputs.py \n
             2.OPTIMIZATION: python TowerSEOpt_Py&MDAOopt.py C:\RRD\PYTHON\WISDEM\towerSE\src\towerse\MytowerInputs.py True \n
             3.BUILD Tower: python >>> mytwr=C:\RRD\PYTHON\WISDEM\TowerSE\src\towerse\MyTowerInputs.py \n
        """

    # I need to put this at the top as it is not set up nicely as jacket: do not modify next line and go to inputs below
    mytwr = set_as_top(TowerMonopileSE())

    # __________Frame3DD or PBeam___________#
    mytwr.replace('tower1', TowerWithpBEAM())
    mytwr.replace('tower2', TowerWithpBEAM())
    #mytwr.replace('tower1', TowerWithFrame3DD())
    #mytwr.replace('tower2', TowerWithFrame3DD())

    # __________Material___________#
    mytwr.material = Material(matname='heavysteel',
                              E=2.1e11,
                              G=8.08e10,
                              rho=8500.)

    # __________Geometry/Positioning___________#
    mytwr.sea_depth = 20.0
    mytwr.tower_length = 87.60
    mytwr.tower_to_shaft = 2.0
    mytwr.deck_height = 15.0
    mytwr.monopile_extension = 5.0
    mytwr.d_monopile = 6.0  # positioning for several variables now depends on monopile diameter
    mytwr.t_monopile = 0.06
    mytwr.t_jacket = 0.05
    mytwr.d_tower_base = 6.0
    mytwr.d_tower_top = 3.87
    mytwr.t_tower_base = 1.3 * 0.027
    mytwr.t_tower_top = 1.3 * 0.019

    mytwr.yaw = 0.0
    mytwr.tilt = 5.0

    # full geometry now specified by positioning component for monopile application

    # __________Environment___________#

    mytwr.replace('wind1', PowerWind())
    mytwr.replace('wind2', PowerWind())

    # wind
    mytwr.wind1.shearExp = 0.2
    mytwr.wind2.shearExp = 0.2

    # waves
    mytwr.replace('wave1', LinearWaves())
    mytwr.replace('wave2', LinearWaves())

    mytwr.wave1.Uc = 0.0
    mytwr.wave1.hs = 8.0 * 1.86
    mytwr.wave1.T = 10.0
    mytwr.wave1.g = 9.81
    mytwr.wave1.betaWave = 0.0

    mytwr.wave2.Uc = 0.0
    mytwr.wave2.hs = 8.0 * 1.86
    mytwr.wave2.T = 10.0
    mytwr.wave2.g = 9.81
    mytwr.wave2.betaWave = 0.0

    # __________Soil___________#
    mytwr.replace('soil', TowerSoil())

    mytwr.soil.rigid = 6 * [True]

    #________RNA mass Properties_________#
    mytwr.top_m = 350000.  #Float(iotype='in', units='m', desc='RNA (tower top) mass')
    mytwr.top_I = np.array(
        [114930678.00, 22035403.00, 18759742.50, 0.00, 503710.47, 0.00]
    )  #Array(iotype='in', units='kg*m**2', desc='mass moments of inertia. order: (xx, yy, zz, xy, xz, yz)')
    mytwr.top_cm = np.array(
        [-1.13, 0.00,
         0.51])  #Array(iotype='in', units='m', desc='RNA center of mass')

    #_______________Loads________________#

    # max Thrust case
    mytwr.wind_Uref1 = 11.73732
    mytwr.top1_F = np.array([
        1284744.196, 0.0, -112400.5527
    ])  #Array(iotype='in', units='N', desc='Aerodynamic forces')
    mytwr.top1_M = np.array([
        3963732.762, 896380.8464, -346781.6819
    ])  #Array(iotype='in', units='N*m', desc='Aerodynamic moments')

    # max wind speed case
    mytwr.wind_Uref2 = 70.0
    mytwr.top2_F = np.array(
        [188038.8045, 0, -16451.2637]
    )  #Array(iotype='in', units='N', desc='Aerodynamic forces') # with all blades feathered
    mytwr.top2_M = np.array(
        [0.0, 131196.8431,
         0.0])  #Array(iotype='in', units='N*m', desc='Aerodynamic moments')

    # fatigue
    mytwr.z_DEL = np.array(
        [0.000]
    )  #, 1.327, 3.982, 6.636, 9.291, 11.945, 14.600, 17.255, 19.909, 22.564, 25.218, 27.873, 30.527, 33.182, 35.836, 38.491, 41.145, 43.800, 46.455, 49.109, 51.764, 54.418, 57.073, 59.727, 62.382, 65.036, 67.691, 70.345, 73.000, 75.655, 78.309, 80.964, 83.618, 86.273, 87.600])
    mytwr.M_DEL = 1e3 * np.array(
        [1.0]
    )  #8.2940E+003, 8.1518E+003, 7.8831E+003, 7.6099E+003, 7.3359E+003, 7.0577E+003, 6.7821E+003, 6.5119E+003, 6.2391E+003, 5.9707E+003, 5.7070E+003, 5.4500E+003, 5.2015E+003, 4.9588E+003, 4.7202E+003, 4.4884E+003, 4.2577E+003, 4.0246E+003, 3.7942E+003, 3.5664E+003, 3.3406E+003, 3.1184E+003, 2.8977E+003, 2.6811E+003, 2.4719E+003, 2.2663E+003, 2.0673E+003, 1.8769E+003, 1.7017E+003, 1.5479E+003, 1.4207E+003, 1.3304E+003, 1.2780E+003, 1.2673E+003, 1.2761E+003])
    mytwr.gamma_fatigue = 1.35 * 1.3 * 1.0
    mytwr.life = 20.0
    mytwr.m_SN = 4

    # Frame3DD parameters
    FrameAuxIns = Frame3DDaux()
    FrameAuxIns.sh_fg = 1  #shear flag-->Timoshenko
    FrameAuxIns.deltaz = 5.
    FrameAuxIns.geo_fg = 0
    FrameAuxIns.nModes = 6  # number of desired dynamic modes of vibration
    FrameAuxIns.Mmethod = 1  # 1: subspace Jacobi     2: Stodola
    FrameAuxIns.lump = 0  # 0: consistent mass ... 1: lumped mass matrix
    FrameAuxIns.tol = 1e-9  # mode shape tolerance
    FrameAuxIns.shift = 0.0  # shift value ... for unrestrained structures
    FrameAuxIns.gvector = np.array([0., 0., -9.8065])  #GRAVITY

    #_____ Safety Factors______#
    mytwr.gamma_f = 1.35
    mytwr.gamma_m = 1.3
    mytwr.gamma_n = 1.0
    mytwr.gamma_b = 1.1

    #______________________________________________#
    #______________________________________________#

    # OTHER AUXILIARY CONSTRAINTS AND TARGETS FOR OPTIMIZATION # !!! NOT USED IN THIS FILE!
    #______________________________________________#
    #______________________________________________#

    # _______Geometric constraints__________#

    mytwr.min_taper = 0.4

    DTRsdiff = True  #Set whether or not DTRt=DTRb

    #______Set target frequency [Hz] and f0epsilon, i.e. fmax=(1+f0eps)*f0_________#
    f0 = 0.28
    f0epsilon = 0.1

    #________Set Optimization Bounds and guesses for the various variables_________#
    #          x=  [      Db,   DTRb   Dt,   DTRt   Htwr2fac  ]
    MnCnst = np.array([5., 120., 3., 120., 0.05])
    MxCnst = np.array([7., 200., 4., 200., 0.25])
    guesses = np.array([6., 140., 3.5, 150., 0.2])

    #_____________________________________________________________#
    #________________ DO NOT MODIFY THE FOLLOWING ________________#
    #_____________________________________________________________#

    mytwr.min_d_to_t = np.min(MnCnst[[1, 3]])
    bounds = np.vstack((MnCnst, MxCnst))
    desvarmeans = np.mean(bounds, 1)

    mytwr.FrameAuxIns = FrameAuxIns

    return mytwr, f0, f0epsilon, DTRsdiff, guesses, bounds.T
示例#13
0
    def __init__(self, nPoints, nFull, nK, nMass, nPL, nDEL, wind=''):

        super(TowerSE, self).__init__()

        self.fd_options['force_fd'] = True

        self.add('geometry',
                 TowerDiscretization(nPoints, nFull),
                 promotes=['*'])
        # two load cases.  TODO: use a case iterator
        if wind == 'PowerWind':
            self.add('wind1', PowerWind(nFull), promotes=['zref', 'z0'])
            self.add('wind2', PowerWind(nFull), promotes=['zref', 'z0'])
        elif wind == 'LogWind':
            self.add('wind1', LogWind(nFull), promotes=['zref', 'z0'])
            self.add('wind2', LogWind(nFull), promotes=['zref', 'z0'])
        self.add('wave1', WaveBase(nFull))
        self.add('wave2', WaveBase(nFull))
        self.add('windLoads1', TowerWindDrag(nFull))
        self.add('windLoads2', TowerWindDrag(nFull))
        self.add('waveLoads1', TowerWaveDrag(nFull))
        self.add('waveLoads2', TowerWaveDrag(nFull))
        self.add('distLoads1', AeroHydroLoads(nFull), promotes=['yaw'])
        self.add('distLoads2', AeroHydroLoads(nFull), promotes=['yaw'])
        self.add('props',
                 CylindricalShellProperties(nFull),
                 promotes=['Az', 'Asx', 'Asy', 'Jz', 'Ixx', 'Iyy'])
        self.add('tower1',
                 TowerFrame3DD(nFull, nK, nMass, nPL, nDEL),
                 promotes=[
                     'E', 'G', 'sigma_y', 'L_reinforced', 'kidx', 'kx', 'ky',
                     'kz', 'ktx', 'kty', 'ktz', 'midx', 'm', 'mIxx', 'mIyy',
                     'mIzz', 'mIxy', 'mIxz', 'mIyz', 'mrhox', 'mrhoy', 'mrhoz',
                     'addGravityLoadForExtraMass', 'g', 'gamma_f', 'gamma_m',
                     'gamma_n', 'gamma_b', 'life', 'm_SN', 'DC', 'z_DEL',
                     'M_DEL', 'gamma_fatigue', 'shear', 'geom', 'dx', 'nM',
                     'Mmethod', 'lump', 'tol', 'shift', 'Az', 'Asx', 'Asy',
                     'Jz', 'Ixx', 'Iyy'
                 ])
        self.add('tower2',
                 TowerFrame3DD(nFull, nK, nMass, nPL, nDEL),
                 promotes=[
                     'E', 'G', 'sigma_y', 'L_reinforced', 'kidx', 'kx', 'ky',
                     'kz', 'ktx', 'kty', 'ktz', 'midx', 'm', 'mIxx', 'mIyy',
                     'mIzz', 'mIxy', 'mIxz', 'mIyz', 'mrhox', 'mrhoy', 'mrhoz',
                     'addGravityLoadForExtraMass', 'g', 'gamma_f', 'gamma_m',
                     'gamma_n', 'gamma_b', 'life', 'm_SN', 'DC', 'z_DEL',
                     'M_DEL', 'gamma_fatigue', 'shear', 'geom', 'dx', 'nM',
                     'Mmethod', 'lump', 'tol', 'shift', 'Az', 'Asx', 'Asy',
                     'Jz', 'Ixx', 'Iyy'
                 ])
        self.add('gc', GeometricConstraints(nPoints))

        self.connect('distLoads2.Px', 'tower2.Px')
        self.connect('distLoads2.Py', 'tower2.Py')
        self.connect('distLoads2.Pz', 'tower2.Pz')
        self.connect('distLoads2.qdyn', 'tower2.qdyn')
        #self.connect('distLoads2.outloads', 'tower2.WWloads')

        # connect tower1 and tower2
        self.connect('tower1.rho', 'tower2.rho')

        # connections to gc
        self.connect('d_param', 'gc.d')
        self.connect('t_param', 'gc.t')

        # connections to wind1
        self.connect('z_full', 'wind1.z')

        # connections to wind2
        self.connect('z_full', 'wind2.z')

        # connections to wave1 and wave2
        self.connect('z_full', 'wave1.z')
        self.connect('z_full', 'wave2.z')

        # connections to windLoads1
        self.connect('wind1.U', 'windLoads1.U')
        self.connect('z_full', 'windLoads1.z')
        self.connect('d_full', 'windLoads1.d')
        self.connect('wind1.beta', 'windLoads1.beta')

        # connections to windLoads2
        self.connect('wind2.U', 'windLoads2.U')
        self.connect('z_full', 'windLoads2.z')
        self.connect('d_full', 'windLoads2.d')
        self.connect('wind2.beta', 'windLoads2.beta')

        # connect windLoads
        self.connect('windLoads1.rho', 'windLoads2.rho')
        self.connect('windLoads1.mu', 'windLoads2.mu')
        self.connect('windLoads1.cd_usr', 'windLoads2.cd_usr')

        # connections to waveLoads1
        self.connect('wave1.U', 'waveLoads1.U')
        self.connect('wave1.A', 'waveLoads1.A')
        self.connect('z_full', 'waveLoads1.z')
        self.connect('d_full', 'waveLoads1.d')
        self.connect('wave1.beta', 'waveLoads1.beta')

        # connections to waveLoads2
        self.connect('wave2.U', 'waveLoads2.U')
        self.connect('wave2.A', 'waveLoads2.A')
        self.connect('z_full', 'waveLoads2.z')
        self.connect('d_full', 'waveLoads2.d')
        self.connect('wave2.beta', 'waveLoads2.beta')

        # connect waveLoads
        self.connect('waveLoads1.rho', 'waveLoads2.rho')
        self.connect('waveLoads1.mu', 'waveLoads2.mu')
        self.connect('waveLoads1.cm', 'waveLoads2.cm')
        self.connect('waveLoads1.cd_usr', 'waveLoads2.cd_usr')

        # connections to distLoads1
        self.connect('z_full', 'distLoads1.z')

        # connections to distLoads2
        self.connect('z_full', 'distLoads2.z')

        # connections to props
        self.connect('d_full', 'props.d')
        self.connect('t_full', 'props.t')

        # connect to tower1
        self.connect('z_full', 'tower1.z')

        self.connect('d_full', 'tower1.d')
        self.connect('t_full', 'tower1.t')

        self.connect('distLoads1.Px', 'tower1.Px')
        self.connect('distLoads1.Py', 'tower1.Py')
        self.connect('distLoads1.Pz', 'tower1.Pz')
        self.connect('distLoads1.qdyn', 'tower1.qdyn')
        #self.connect('distLoads1.outloads', 'tower1.WWloads')

        # connect to tower2
        self.connect('z_full', 'tower2.z')

        self.connect('d_full', 'tower2.d')
        self.connect('t_full', 'tower2.t')

        self.connect('windLoads1.windLoads:Px', 'distLoads1.windLoads:Px')
        self.connect('windLoads1.windLoads:Py', 'distLoads1.windLoads:Py')
        self.connect('windLoads1.windLoads:Pz', 'distLoads1.windLoads:Pz')
        self.connect('windLoads1.windLoads:qdyn', 'distLoads1.windLoads:qdyn')
        self.connect('windLoads1.windLoads:beta', 'distLoads1.windLoads:beta')
        self.connect('windLoads1.windLoads:Px0', 'distLoads1.windLoads:Px0')
        self.connect('windLoads1.windLoads:Py0', 'distLoads1.windLoads:Py0')
        self.connect('windLoads1.windLoads:Pz0', 'distLoads1.windLoads:Pz0')
        self.connect('windLoads1.windLoads:qdyn0',
                     'distLoads1.windLoads:qdyn0')
        self.connect('windLoads1.windLoads:beta0',
                     'distLoads1.windLoads:beta0')
        self.connect('windLoads1.windLoads:z', 'distLoads1.windLoads:z')
        self.connect('windLoads1.windLoads:d', 'distLoads1.windLoads:d')

        self.connect('windLoads2.windLoads:Px', 'distLoads2.windLoads:Px')
        self.connect('windLoads2.windLoads:Py', 'distLoads2.windLoads:Py')
        self.connect('windLoads2.windLoads:Pz', 'distLoads2.windLoads:Pz')
        self.connect('windLoads2.windLoads:qdyn', 'distLoads2.windLoads:qdyn')
        self.connect('windLoads2.windLoads:beta', 'distLoads2.windLoads:beta')
        self.connect('windLoads2.windLoads:Px0', 'distLoads2.windLoads:Px0')
        self.connect('windLoads2.windLoads:Py0', 'distLoads2.windLoads:Py0')
        self.connect('windLoads2.windLoads:Pz0', 'distLoads2.windLoads:Pz0')
        self.connect('windLoads2.windLoads:qdyn0',
                     'distLoads2.windLoads:qdyn0')
        self.connect('windLoads2.windLoads:beta0',
                     'distLoads2.windLoads:beta0')
        self.connect('windLoads2.windLoads:z', 'distLoads2.windLoads:z')
        self.connect('windLoads2.windLoads:d', 'distLoads2.windLoads:d')

        self.connect('waveLoads1.waveLoads:Px', 'distLoads1.waveLoads:Px')
        self.connect('waveLoads1.waveLoads:Py', 'distLoads1.waveLoads:Py')
        self.connect('waveLoads1.waveLoads:Pz', 'distLoads1.waveLoads:Pz')
        self.connect('waveLoads1.waveLoads:qdyn', 'distLoads1.waveLoads:qdyn')
        self.connect('waveLoads1.waveLoads:beta', 'distLoads1.waveLoads:beta')
        self.connect('waveLoads1.waveLoads:Px0', 'distLoads1.waveLoads:Px0')
        self.connect('waveLoads1.waveLoads:Py0', 'distLoads1.waveLoads:Py0')
        self.connect('waveLoads1.waveLoads:Pz0', 'distLoads1.waveLoads:Pz0')
        self.connect('waveLoads1.waveLoads:qdyn0',
                     'distLoads1.waveLoads:qdyn0')
        self.connect('waveLoads1.waveLoads:beta0',
                     'distLoads1.waveLoads:beta0')
        self.connect('waveLoads1.waveLoads:z', 'distLoads1.waveLoads:z')
        self.connect('waveLoads1.waveLoads:d', 'distLoads1.waveLoads:d')

        self.connect('waveLoads2.waveLoads:Px', 'distLoads2.waveLoads:Px')
        self.connect('waveLoads2.waveLoads:Py', 'distLoads2.waveLoads:Py')
        self.connect('waveLoads2.waveLoads:Pz', 'distLoads2.waveLoads:Pz')
        self.connect('waveLoads2.waveLoads:qdyn', 'distLoads2.waveLoads:qdyn')
        self.connect('waveLoads2.waveLoads:beta', 'distLoads2.waveLoads:beta')
        self.connect('waveLoads2.waveLoads:Px0', 'distLoads2.waveLoads:Px0')
        self.connect('waveLoads2.waveLoads:Py0', 'distLoads2.waveLoads:Py0')
        self.connect('waveLoads2.waveLoads:Pz0', 'distLoads2.waveLoads:Pz0')
        self.connect('waveLoads2.waveLoads:qdyn0',
                     'distLoads2.waveLoads:qdyn0')
        self.connect('waveLoads2.waveLoads:beta0',
                     'distLoads2.waveLoads:beta0')
        self.connect('waveLoads2.waveLoads:z', 'distLoads2.waveLoads:z')
        self.connect('waveLoads2.waveLoads:d', 'distLoads2.waveLoads:d')

        # outputs TODO
        """