示例#1
0
class LoftedBladeSurfaceBase(Component):

    surfout = VarTree(BladeSurfaceVT(), iotype='out')
    surfnorot = VarTree(BladeSurfaceVT(), iotype='out')
class floris_windframe(Component):
    """ Calculates the locations of each turbine in the wind direction reference frame """

    # original variables
    parameters = VarTree(FLORISParameters(), iotype='in')
    verbose = Bool(False,
                   iotype='in',
                   desc='verbosity of FLORIS, False is no output')

    # flow property variables
    wind_speed = Float(iotype='in',
                       units='m/s',
                       desc='free stream wind velocity')
    wind_direction = Float(
        iotype='in',
        units='deg',
        desc='wind direction using direction to, in deg. ccw from east')

    def __init__(self, nTurbines, resolution):

        print 'entering windframe __init__ - analytic'

        super(floris_windframe, self).__init__()

        # Explicitly size input arrays
        self.add('turbineX', Array(np.zeros(nTurbines), iotype='in', \
                                   desc='x positions of turbines in original ref. frame'))
        self.add('turbineY', Array(np.zeros(nTurbines), iotype='in', \
                                   desc='y positions of turbines in original ref. frame'))

        # variables for verbosity
        self.add('Ct', Array(np.zeros(nTurbines), iotype='in'))
        self.add('Cp', Array(np.zeros(nTurbines), iotype='in', \
                             desc='power coefficient for all turbines'))
        self.add('axialInduction', Array(np.zeros(nTurbines), iotype='in', dtype='float', \
                                         desc='axial induction of all turbines'))
        self.add('yaw', Array(np.zeros(nTurbines), iotype='in', \
                              desc='yaw of each turbine'))

        # variables for testing wind speed at various locations
        self.add('ws_position', Array(np.zeros(resolution*resolution), iotype='in', units='m', \
                                      desc='position of desired measurements in original ref. frame'))

        # Explicitly size output arrays
        self.add('wsw_position', Array(np.zeros(resolution*resolution), iotype='out', units='m', \
                                       desc='position of desired measurements in wind ref. frame'))

        # for testing purposes only
        self.add('turbineXw', Array(np.zeros(nTurbines), iotype='out', units='m', \
                                    desc='x coordinates of turbines in wind dir. ref. frame'))
        self.add('turbineYw', Array(np.zeros(nTurbines), iotype='out', units='m', \
                                    desc='y coordinates of turbines in wind dir. ref. frame'))

    def execute(self):

        print 'entering windframe - analytic'

        if self.parameters.FLORISoriginal:

            ke = 0.065
            keCorrCT = 0.0
            # ignore these for now
            # keCorrTI = 0.0
            # keCorrHR = 0.0
            # keCorrHRTI = 0.0
            keCorrArray = 0.0

            kd = 0.15
            # kdCorrYawDirection = 0.0  # ignored for now

            me = np.array([-0.5, 0.22, 1.0])
            MU = np.array([0.5, 1.0, 5.5])
            pP = 1.88
            useWakeAngle = False
            initialWakeDisplacement = 4.5
            bd = -0.01
            useaUbU = True
            aU = 5.0
            bU = 1.66
            adjustInitialWakeDiamToYaw = False

        else:
            # rename inputs and outputs
            ke = self.parameters.ke

            keCorrCT = self.parameters.keCorrCT
            keCorrTI = self.parameters.keCorrTI
            keCorrHR = self.parameters.keCorrHR
            keCorrHRTI = self.parameters.keCorrHRTI
            keCorrArray = self.parameters.keCorrArray

            kd = self.parameters.kd
            kdCorrYawDirection = self.parameters.kdCorrYawDirection

            me = self.parameters.me
            MU = self.parameters.MU

            initialWakeDisplacement = self.parameters.initialWakeDisplacement
            useWakeAngle = self.parameters.useWakeAngle
            initialWakeAngle = self.parameters.initialWakeAngle

            bd = self.parameters.bd

            useaUbU = self.parameters.useaUbU
            aU = self.parameters.aU
            bU = self.parameters.bU

            adjustInitialWakeDiamToYaw = self.parameters.adjustInitialWakeDiamToYaw

            pP = self.parameters.pP

        baselineCT = self.parameters.baselineCT
        baselineTI = self.parameters.baselineTI
        keSaturation = self.parameters.keSaturation

        CTcorrected = self.parameters.CTcorrected
        CPcorrected = self.parameters.CPcorrected
        axialIndProvided = self.parameters.axialIndProvided

        Vinf = self.wind_speed
        windDirection = self.wind_direction * np.pi / 180.0

        #variables to satisfy verbosity
        axialInd = self.axialInduction
        Cp = self.Cp
        Ct = self.Ct
        yaw = self.yaw * np.pi / 180

        if self.verbose:
            np.set_printoptions(formatter={'float': '{: 0.3f}'.format})
            print "wind direction %s deg" % [windDirection * 180.0 / np.pi]
            print "free-stream wind speed %s" % Vinf
            print "axial induction turbines %s" % axialInd
            print "C_P turbines %s" % Cp
            print "C_T turbines %s" % Ct
            print "yaw turbines %s" % yaw

        # get turbine positions and velocity sampling positions
        # position = self.position
        # turbineX = position[:, 0]
        # turbineY = position[:, 1]
        turbineX = self.turbineX
        turbineY = self.turbineY
        # print turbineX, turbineY

        if self.ws_position.any():
            velX = self.ws_position[:, 0]
            velY = self.ws_position[:, 1]
        else:
            velX = np.zeros([0, 0])
            velY = np.zeros([0, 0])

        # convert to downwind-crosswind coordinates
        rotationMatrix = np.array([
            (np.cos(-windDirection), -np.sin(-windDirection)),
            (np.sin(-windDirection), np.cos(-windDirection))
        ])
        # print 'rotation matrix = ', rotationMatrix
        turbineLocations = np.dot(rotationMatrix,
                                  np.array([turbineX, turbineY]))
        # print turbineLocations
        self.turbineXw = np.zeros(turbineX.size)
        self.turbineYw = np.zeros(turbineX.size)
        # print self.turbineXw
        self.turbineXw = turbineLocations[0]
        self.turbineYw = turbineLocations[1]
        #print 'windframe.turbineX = %s' %self.turbineX
        if velX.size > 0:
            locations = np.dot(rotationMatrix, np.array([velX, velY]))
            velX = locations[0]
            velY = locations[1]

        self.wsw_position = np.array([velX, velY])
        #print 'wsw_position in windframe is:', self.wsw_position
        #print 'ws_position in windframe is:', self.ws_position

        # print self.turbineXw

    def list_deriv_vars(self):
        """specifies the inputs and outputs where derivatives are defined"""

        return ('turbineX', 'turbineY'), ('turbineXw', 'turbineYw')

    def provideJ(self):

        #print 'entering windframe - provideJ'

        n = np.size(self.turbineX)

        windDirection = self.wind_direction * np.pi / 180

        dturbineXw_dturbineX = np.zeros([n, n])
        dturbineXw_dturbineY = np.zeros([n, n])
        dturbineYw_dturbineX = np.zeros([n, n])
        dturbineYw_dturbineY = np.zeros([n, n])

        for i in range(0, n):
            dturbineXw_dturbineX[i, i] = np.cos(-windDirection)
            dturbineXw_dturbineY[i, i] = -np.sin(-windDirection)
            dturbineYw_dturbineX[i, i] = np.sin(-windDirection)
            dturbineYw_dturbineY[i, i] = np.cos(-windDirection)

        JturbineXw = np.concatenate(
            (dturbineXw_dturbineX, dturbineXw_dturbineY), 1)
        JturbineYw = np.concatenate(
            (dturbineYw_dturbineX, dturbineYw_dturbineY), 1)
        J = np.concatenate((JturbineXw, JturbineYw), 0)

        return J
示例#3
0
class Strains(Component):
    """
    Computes internal forces and strains
    """

    # inputs
    yN = Array(iotype='in', desc='')
    d = Array(iotype='in', desc='')
    k = Array(iotype='in', desc='Local elastic stiffness matrix')
    F = Array(iotype='in', desc='global force vector')
    q = Array(iotype='in', desc='deformation')

    # outputs
    Finternal = Array(iotype='out', desc='internal forces')
    strain = VarTree(Strain(), iotype='out', desc='strains')

    def execute(self):
        # short alias
        d = self.d

        Ns = len(self.yN) - 1  # number of elements
        dy = np.zeros((Ns, 1))
        for s in range(1, Ns + 1):
            dy[s - 1] = self.yN[s] - self.yN[s - 1]  # length of each element

        Ftemp = np.zeros((12, Ns))
        Finternal = np.zeros((6, Ns + 1))

        strain = Strain()
        strain.top = np.zeros((3, Ns + 1))
        strain.bottom = np.zeros((3, Ns + 1))
        strain.back = np.zeros((3, Ns + 1))
        strain.front = np.zeros((3, Ns + 1))

        strain.bending_x = np.zeros((1, Ns + 1))
        strain.bending_z = np.zeros((1, Ns + 1))
        strain.axial_y = np.zeros((1, Ns + 1))
        strain.torsion_y = np.zeros((1, Ns + 1))

        for s in range(Ns):
            # Determine internal forces acting at the nodes of each element
            Ftemp[:, s] = -(np.dot(self.k[:, :, s], self.q[s * 6:s * 6 + 12]) -
                            self.F[s * 6:s * 6 + 12]).squeeze()
            Finternal[0, s] = Ftemp[0, s]  # x-shear load
            Finternal[1, s] = Ftemp[1, s]  # y-axial load
            Finternal[2, s] = Ftemp[2, s]  # z-shear load
            Finternal[3, s] = Ftemp[3, s]  # x-bending moment
            Finternal[4, s] = Ftemp[4, s]  # y-torsional load
            Finternal[5, s] = Ftemp[5, s]  # z-bending moment

            # Determine strains at each node
            x_hat = d[s] / 2
            z_hat = d[s] / 2
            r_hat = d[s] / 2

            # Break out displacement vector for element
            qq = self.q[s * 6:s * 6 + 12]

            strain.bending_x[0, s] = np.dot(
                -np.array([(-(6 * x_hat) / (dy[s]**2)), ((4 * x_hat) / dy[s]),
                           ((6 * x_hat) / (dy[s]**2)),
                           ((2 * x_hat) / dy[s])]).reshape(1, -1),
                np.array([qq[0], qq[5], qq[6], qq[11]]).reshape(1, -1).T)

            strain.bending_z[0, s] = np.dot(
                -np.array([(-(6 * z_hat) / (dy[s]**2)), ((-4 * z_hat) / dy[s]),
                           ((+6 * z_hat) / (dy[s]**2)),
                           ((-2 * z_hat) / dy[s])]).reshape(1, -1),
                np.array([qq[2], qq[3], qq[8], qq[9]]).reshape(1, -1).T)

            strain.axial_y[0, s] = np.dot(
                np.array([(-1 / dy[s]), (1 / dy[s])]).reshape(1, -1),
                np.array([qq[1], qq[7]]).reshape(1, -1).T)

            strain.torsion_y[0, s] = np.dot(
                r_hat * np.array([(-1 / dy[s]), (1 / dy[s])]).reshape(1, -1),
                np.array([qq[4], qq[10]]).reshape(1, -1).T)

            strain.top[0, s] = strain.bending_z[0, s] + strain.axial_y[0, s]
            strain.top[1, s] = 0
            strain.top[2, s] = strain.torsion_y[0, s]
            strain.bottom[0,
                          s] = -strain.bending_z[0, s] + strain.axial_y[0, s]
            strain.bottom[1, s] = 0
            strain.bottom[2, s] = strain.torsion_y[0, s]
            strain.back[0, s] = strain.bending_x[0, s] + strain.axial_y[0, s]
            strain.back[1, s] = 0
            strain.back[2, s] = strain.torsion_y[0, s]
            strain.front[0, s] = -strain.bending_x[0, s] + strain.axial_y[0, s]
            strain.front[1, s] = 0
            strain.front[2, s] = strain.torsion_y[0, s]

        # Loads at the tip are zero
        Finternal[0, Ns] = 0  # x-shear load
        Finternal[1, Ns] = 0  # y-axial load
        Finternal[2, Ns] = 0  # z-shear load
        Finternal[3, Ns] = 0  # x-bending moment
        Finternal[4, Ns] = 0  # y-torsional load
        Finternal[5, Ns] = 0  # z-bending moment

        # Strains at tip are zero
        strain.top[0, Ns] = 0
        strain.top[1, Ns] = 0
        strain.top[2, Ns] = 0

        strain.bottom[0, Ns] = 0
        strain.bottom[1, Ns] = 0
        strain.bottom[2, Ns] = 0

        strain.back[0, Ns] = 0
        strain.back[1, Ns] = 0
        strain.back[2, Ns] = 0

        strain.front[0, Ns] = 0
        strain.front[1, Ns] = 0
        strain.front[2, Ns] = 0

        # Strains at tip are zero
        strain.bending_x[0, Ns] = 0
        strain.bending_z[0, Ns] = 0
        strain.axial_y[0, Ns] = 0
        strain.torsion_y[0, Ns] = 0

        # set outputs
        self.Finternal = Finternal
        self.strain = strain
示例#4
0
class Structures(Assembly):
    """
    structural computation, first computes the mass of the helicopter based on
    the structural description of the spars and chord lengths. It then
    computes the deformation of the spars, the strains, and the resulting
    factor of safety for each of the failure modes.
    """

    # flags
    flags = VarTree(Flags(), iotype='in')

    # inputs for spars
    yN = Array(iotype='in',
               desc='node locations for each element along the span')
    d = Array(iotype='in', desc='spar diameter')
    theta = Array(iotype='in', desc='wrap angle')
    nTube = Array(iotype='in', desc='number of tube layers')
    nCap = Array(iotype='in', desc='number of cap strips')
    lBiscuit = Array(iotype='in', desc='unsupported biscuit length')

    # joint properties
    Jprop = VarTree(JointProperties(), iotype='in')

    # inputs for chord
    b = Int(iotype='in', desc='number of blades')
    cE = Array(iotype='in', desc='chord of each element')
    xEA = Array(iotype='in', desc='')
    xtU = Array(iotype='in', desc='')

    # inputs for quad
    dQuad = Float(iotype='in', desc='diameter of quad rotor struts')
    thetaQuad = Float(iotype='in', desc='wrap angle of quad rotor struts')
    nTubeQuad = Int(iotype='in',
                    desc='number of CFRP layers in quad rotor struts')
    lBiscuitQuad = Float(iotype='in', desc='')
    RQuad = Float(
        iotype='in',
        desc='distance from centre of helicopter to centre of quad rotors')
    hQuad = Float(iotype='in', desc='height of quad-rotor truss')

    # inputs for cover
    ycmax = Float(iotype='in', desc='')

    # inputs for wire
    yWire = Array(iotype='in', desc='location of wire attachment along span')
    zWire = Float(iotype='in', desc='depth of wire attachement')
    tWire = Float(iotype='in', desc='thickness of wire')
    TWire = Array(iotype='in', desc='')
    TEtension = Float(iotype='in', desc='')

    # inputs for 'other stuff'
    mElseRotor = Float(iotype='in', desc='')
    mElseCentre = Float(iotype='in', desc='')
    mElseR = Float(iotype='in', desc='')
    R = Float(iotype='in', desc='rotor radius')
    mPilot = Float(iotype='in', desc='mass of pilot')

    # inputs for FEM
    fblade = VarTree(Fblade(), iotype='in')
    presLoad = VarTree(PrescribedLoad(), iotype='in')

    def configure(self):
        self.add('spar', SparProperties())
        self.connect('yN', 'spar.yN')
        self.connect('d', 'spar.d')
        self.connect('theta', 'spar.theta')
        self.connect('nTube', 'spar.nTube')
        self.connect('nCap', 'spar.nCap')
        self.connect('lBiscuit', 'spar.lBiscuit')
        self.connect('flags.CFRPType', 'spar.CFRPType')

        self.add('joint', JointSparProperties())
        self.connect('flags.CFRPType', 'joint.CFRPType')
        self.connect('Jprop', 'joint.Jprop')

        self.add('chord', ChordProperties())
        self.connect('yN', 'chord.yN')
        self.connect('cE', 'chord.c')
        self.connect('d', 'chord.d')
        self.connect('flags.GWing', 'chord.GWing')
        self.connect('xtU', 'chord.xtU')

        self.add('quad', QuadSparProperties())
        self.connect('dQuad', 'quad.dQuad')
        self.connect('thetaQuad', 'quad.thetaQuad')
        self.connect('nTubeQuad', 'quad.nTubeQuad')
        self.connect('lBiscuitQuad', 'quad.lBiscuitQuad')
        self.connect('flags.CFRPType', 'quad.CFRPType')
        self.connect('RQuad', 'quad.RQuad')
        self.connect('hQuad', 'quad.hQuad')

        self.add('mass', MassProperties())
        self.connect('flags', 'mass.flags')
        self.connect('b', 'mass.b')
        self.connect('spar.mSpar', 'mass.mSpar')
        self.connect('chord.mChord', 'mass.mChord')
        self.connect('chord.xCGChord', 'mass.xCGChord')
        self.connect('quad.mQuad', 'mass.mQuad')
        self.connect('xEA', 'mass.xEA')
        self.connect('ycmax', 'mass.ycmax')
        self.connect('zWire', 'mass.zWire')
        self.connect('yWire', 'mass.yWire')
        self.connect('tWire', 'mass.tWire')
        self.connect('mElseRotor', 'mass.mElseRotor')
        self.connect('mElseCentre', 'mass.mElseCentre')
        self.connect('mElseR', 'mass.mElseR')
        self.connect('R', 'mass.R')
        self.connect('mPilot', 'mass.mPilot')

        self.add('fem', FEM())
        self.connect('flags', 'fem.flags')
        self.connect('yN', 'fem.yN')
        self.connect('spar.EIx', 'fem.EIx')
        self.connect('spar.EIz', 'fem.EIz')
        self.connect('spar.EA', 'fem.EA')
        self.connect('spar.GJ', 'fem.GJ')
        self.connect('cE', 'fem.cE')
        self.connect('xEA', 'fem.xEA')
        self.connect('spar.mSpar', 'fem.mSpar')
        self.connect('chord.mChord', 'fem.mChord')
        self.connect('mass.xCG', 'fem.xCG')
        self.connect('zWire', 'fem.zWire')
        self.connect('yWire', 'fem.yWire')
        self.connect('TWire', 'fem.TWire')
        self.connect('fblade', 'fem.fblade')
        self.connect('presLoad', 'fem.presLoad')

        self.add('strains', Strains())
        self.connect('yN', 'strains.yN')
        self.connect('d', 'strains.d')
        self.connect('fem.k', 'strains.k')
        self.connect('fem.F', 'strains.F')
        self.connect('fem.q', 'strains.q')

        self.add('failure', Failures())
        self.connect('flags', 'failure.flags')
        self.connect('yN', 'failure.yN')
        self.connect('strains.Finternal', 'failure.Finternal')
        self.connect('strains.strain', 'failure.strain')
        self.connect('d', 'failure.d')
        self.connect('theta', 'failure.theta')
        self.connect('nTube', 'failure.nTube')
        self.connect('nCap', 'failure.nCap')
        self.connect('yWire', 'failure.yWire')
        self.connect('zWire', 'failure.zWire')
        self.connect('joint.EIx', 'failure.EIxJ')
        self.connect('joint.EIz', 'failure.EIzJ')
        self.connect('lBiscuit', 'failure.lBiscuit')
        self.connect('dQuad', 'failure.dQuad')
        self.connect('thetaQuad', 'failure.thetaQuad')
        self.connect('nTubeQuad', 'failure.nTubeQuad')
        self.connect('lBiscuitQuad', 'failure.lBiscuitQuad')
        self.connect('RQuad', 'failure.RQuad')
        self.connect('hQuad', 'failure.hQuad')
        self.connect('quad.EIx', 'failure.EIQuad')
        self.connect('quad.GJ', 'failure.GJQuad')
        self.connect('tWire', 'failure.tWire')
        self.connect('TWire', 'failure.TWire')
        self.connect('TEtension', 'failure.TEtension')
        self.connect('b', 'failure.b')
        self.connect('fblade', 'failure.fblade')
        self.connect('spar.mSpar', 'failure.mSpar')
        self.connect('chord.mChord', 'failure.mChord')
        self.connect('mElseRotor', 'failure.mElseRotor')

        # link up the outputs
        self.create_passthrough('mass.Mtot')
        self.create_passthrough('fem.q')
        self.create_passthrough('strains.Finternal')
        self.create_passthrough('strains.strain')
        self.create_passthrough('failure.fail')

        self.driver.workflow.add('chord')
        self.driver.workflow.add('fem')
        self.driver.workflow.add('joint')
        self.driver.workflow.add('mass')
        self.driver.workflow.add('quad')
        self.driver.workflow.add('spar')
        self.driver.workflow.add('strains')
        self.driver.workflow.add('failure')
示例#5
0
    def __init__(self, Ns):
        super(LiftDrag, self).__init__()

        # inputs
        self.add('Ns', Int(0, iotype="in", desc="number of Elements"))

        self.add('yN',
                 Array(np.zeros(Ns + 1), iotype="in", desc='node locations'))

        self.add('rho', Float(0., iotype='in', desc='air density'))
        self.add('visc', Float(0., iotype='in', desc='air viscosity'))
        self.add('vw', Float(0., iotype='in', desc='wind'))
        self.add('vc', Float(0., iotype='in', desc='vertical velocity'))
        self.add('Omega', Float(0., iotype='in',
                                desc='Rotor angular velocity'))

        self.add(
            'r',
            Array(np.zeros(Ns),
                  iotype='in',
                  desc='radial location of each element'))
        self.add(
            'vi',
            Array(np.zeros(Ns),
                  iotype='in',
                  desc='induced downwash distribution'))
        self.add('c',
                 Array(np.zeros(Ns), iotype='in', desc='chord distribution'))
        self.add(
            'Cl',
            Array(np.zeros(Ns),
                  iotype='in',
                  desc='lift coefficient distribution'))
        self.add(
            'dr',
            Array(np.zeros(Ns), iotype='in', desc='length of each element'))
        self.add(
            'd',
            Array(np.zeros(Ns), iotype='in',
                  desc='spar diameter distribution'))

        self.add(
            'yWire',
            Array([0],
                  iotype='in',
                  desc='location of wire attachment along span'))
        self.add('zWire',
                 Float(0., iotype='in', desc='depth of wire attachement'))
        self.add('tWire', Float(0., iotype='in', desc='thickness of wire'))

        self.add('chordFrac', Array(np.zeros(Ns), iotype='in', desc=''))

        self.add('Cm', Array(np.zeros(Ns), iotype='in', desc=''))
        self.add(
            'xtU',
            Array(np.zeros(Ns),
                  iotype='in',
                  desc='fraction of laminar flow on the upper surface'))
        self.add(
            'xtL',
            Array(np.zeros(Ns),
                  iotype='in',
                  desc='fraction of laminar flow on the lower surface'))

        # outputs
        self.add('Re', Array(np.zeros(Ns),
                             iotype='out',
                             desc='Reynolds number'))
        self.add('Cd',
                 Array(np.zeros(Ns), iotype='out', desc='drag coefficients'))
        self.add('phi', Array(np.zeros(Ns), iotype='out', desc=''))
        self.add('Fblade', VarTree(Fblade(Ns), iotype='out', desc=''))
 def add_section(self, name):
     self.add(name, VarTree(SectionVT()))
示例#7
0
class openwind_assembly(Assembly): # todo: has to be assembly or manipulation and passthrough of aep in execute doesnt work
    """ Runs OpenWind from OpenMDAO framework """

    # Inputs
    hub_height     = Float(90.0, iotype='in', desc='turbine hub height', unit='m')
    rotor_diameter = Float(126.0, iotype='in', desc='turbine rotor diameter', unit='m')
    power_curve    = Array([], iotype='in', desc='wind turbine power curve')
    rpm            = Array([], iotype='in', desc='wind turbine rpm curve')
    ct             = Array([], iotype='in', desc='wind turbine ct curve')
    machine_rating = Float(6000.0, iotype='in', desc='wind turbine rated power', unit='kW')
    availability   = Float(0.941, iotype='in', desc='wind plant availability')
    wt_layout      = VarTree(GenericWindFarmTurbineLayout(), iotype='in', desc='properties for each wind turbine and layout')    
    other_losses   = Float(0.0, iotype='in', desc='wind plant losses due to blade soiling, etc')
    dummyVbl       = Float(0, iotype='in', desc='unused variable to make it easy to do DOE runs')
    
    # TODO: loss inputs
    # TODO: wake model option selections

    # Outputs
      # inherits output vbls net_aep and gross_aep from GenericAEPModel - NOT when using fusedwind implement_base
      
    gross_aep        = Float(0.0, iotype='out', desc='Gross Output')
    net_aep          = Float(0.0, iotype='out', desc='Net Output')
    #ideal_aep = Float(0.0, iotype='out', desc='Ideal Annual Energy Production before topographic, availability and loss impacts', unit='kWh')
    array_aep       = Float(0.0, iotype='out', desc='Gross Annual Energy Production net of array impacts', unit='kWh')
    array_losses    = Float(0.0, iotype='out', desc='Array Losses')
    capacity_factor = Float(0.0, iotype='out', desc='capacity factor')
    turbine_number = Int(100, iotype='out', desc='plant number of turbines')

    # -------------------
    
    def __init__(self, openwind_executable, workbook_path, 
                 turbine_name=None, script_file=None, machine_rating=None,
                 academic=False, debug=False):
        """ Creates a new LCOE Assembly object """

        foundErrors = False
        if not os.path.isfile(openwind_executable):
            sys.stderr.write('\n*** ERROR: executable {:} not found\n\n'.format(openwind_executable))
            foundErrors = True
        if not os.path.isfile(workbook_path):
            sys.stderr.write('\n*** ERROR: workbook {:} not found\n\n'.format(workbook_path))
            foundErrors = True
        if foundErrors:
            return None
        
        # Set the location where new scripts and turbine files will be written
        
        self.workDir = os.getcwd()
        #self.workDir = os.path.dirname(os.path.realpath(__file__)) # location of this source file
                
        self.openwind_executable = openwind_executable
        self.workbook_path = workbook_path
        self.turbine_name = turbine_name
        self.script_file = script_file
        self.academic = academic
        self.debug = debug
        
        if machine_rating is not None:
            self.machine_rating = machine_rating
            
        super(openwind_assembly, self).__init__()

        # TODO: hack for now assigning turbine
        self.turb = GenericWindTurbinePowerCurveVT()
        self.turb.power_rating = self.machine_rating
        self.turb.hub_height = self.hub_height
        self.turb.power_curve = np.copy(self.power_curve)
        for i in xrange(0,self.turbine_number):
            self.wt_layout.wt_list.append(self.turb)

    # -------------------
    
    def configure(self):
        """ Add Openwind external code component """

        super(openwind_assembly, self).configure()        
        
        '''if self.academic:
            #ow = OWACwrapped(self.openwind_executable, scriptFile=self.script_file, debug=True)
            sys.stderr.write('\nERROR - openwind_assembly.py not currently configured for Academic version\n')
            sys.stderr.write('Use ../Academic/openwindAC_assembly.py instead\n')
            quit()
        else:'''
        ow = OWwrapped(self.openwind_executable, scriptFile=self.script_file, debug=self.debug)
        self.add('ow', ow)
        
        self.driver.workflow.add(['ow'])
        
        # Inputs to OWwrapped
        
        #self.connect('rotor_diameter', 'ow.rotor_diameter') # todo: hack to force external code execution
        self.connect('other_losses', 'ow.other_losses')
        self.connect('availability', 'ow.availability')
        
        self.connect('dummyVbl', 'ow.dummyVbl')
        
        # Outputs from OWwrapped
        
        self.connect('ow.array_losses', 'array_losses')
        self.connect('ow.gross_aep', 'gross_aep')
        self.connect('ow.array_aep', 'array_aep')
        self.connect('ow.net_aep', 'net_aep')
        self.connect('ow.turbine_number', 'turbine_number')
    
    # -------------------
    
    def execute(self):
        """
            Set up XML and run OpenWind
            #This will leave OW running - use the File/Exit button to shut it down until
            #  Nick comes up with a way to stop it from the script.
            # 20140326: OW now has Exit operation in scripter
        """

        if self.debug:
            sys.stderr.write("In {0}.execute()...\n".format(self.__class__))

        report_path = self.workDir + '/' + 'scrtest1.txt'
        workbook_path = self.workbook_path
        turbine_name = self.turbine_name

        # Prepare for next iteration here...
        #   - write new scripts
        #   - write new turbine files
        #   - etc.
        #turbine_path = self.workDir + '/' + 'Turbine_Model.owtg'
        #self.writeNewTurbine('Turbine_Model.owtg')

        # write new script for execution  
    
        # newScriptName = 'OpenWind_Script.xml'
        # self.writeNewScript(newScriptName)
        # self.command[1] = newScriptName
        
        # will actually run the workflow
        super(openwind_assembly, self).execute()

        # calculate capacity factor
        #  - assumes that all turbines have the same power rating
        #    and that self.wt_layout is correct
        
        #self.capacity_factor = ((self.net_aep) / (self.wt_layout.wt_list[0].power_rating * 8760.0 * self.turbine_number))
        # 8766 hrs = 365.25 days to agree with OpenWind
        
        self.capacity_factor = ((self.net_aep) / (self.wt_layout.wt_list[0].power_rating * 8766.0 * self.turbine_number))
        
    # -------------------
    
    def writeNewTurbine(self, turbFileName):
        ''' Set up turbine to write to xml
        '''
        rho = [1.225]
        vels = [float(i) for i in range(26)]
        
        # power table
        
        power = []
        for i in xrange(0,4):
            power.append(0.0)
        counter = 5.0
        for i in xrange(5,26):
            myi = min(range(self.power_curve.shape[1]), key=lambda i: abs(self.power_curve[0][i]-counter))
            power.append(self.power_curve[1][myi])
            counter += 1.0 
        power.append(self.power_curve[1][-1])

        # thrust table
        
        thrust = []
        for i in xrange(0,4):
            thrust.append(1.0)
        counter = 5.0
        for j in xrange(5,26):
            myi = min(range(self.ct.shape[1]), key=lambda i: abs(self.ct[0][i]-counter))
            thrust.append(self.ct[1][myi])
            counter += 1.0
        thrust.append(self.ct[1][0])
        
        # RPM table
        
        rpm = []
        for i in xrange(0,4):
            rpm.append(0.0)
        counter = 5.0
        for j in xrange(5,26):
            myi = min(range(self.rpm.shape[1]), key=lambda i: abs(self.rpm[0][i]-counter))
            rpm.append(self.rpm[1][myi])
            counter += 1.0
        rpm.append(self.rpm[1][-1])

        percosts = []
        cut_in_wind_speed = 4.0
        cut_out_wind_speed = 25.0
        blade_number = 3
        turbine_cost = 2000000
        foundation_cost =  100000
        turbine_name = 'NewTurbine'
        desc = 'New Turbine'
        turbtree = rwTurbXML.getTurbTree(turbine_name, desc, \
                                          vels, power, thrust, rpm, \
                                          self.hub_height, self.rotor_diameter, rho, \
                                          percosts, cut_in_wind_speed, cut_out_wind_speed, \
                                          blade_number, self.machine_rating, turbine_cost, foundation_cost)
        turbXML = etree.tostring(turbtree, 
                                 xml_declaration=True,
                                 doctype='<!DOCTYPE {:}>'.format(turbine_name), 
                                 pretty_print=True)

        ofh = open(self.workDir + '/' + turbFileName, 'w')
        ofh.write(turbXML)
        ofh.close()
        
    # -------------------
    
    def writeNewScript(self, scriptFileName):
        '''
          Write a new XML script to scriptFileName and use that as the active
          script for OpenWind
          Operations are: load workbook, replace turbine, energy capture, exit
        '''
        
        script_tree, operations = rwScriptXML.newScriptTree(self.report_path)    
        # add operations to 'operations' (the 'AllOperations' tree in script_tree)
        
        rwScriptXML.makeChWkbkOp(operations,self.workbook_path)       # change workbook
        rwScriptXML.makeRepTurbOp(operations,turbine_name,turbine_path)  # replace turbine
        rwScriptXML.makeEnCapOp(operations)                # run energy capture
        rwScriptXML.makeExitOp(operations)                 # exit
        
        script_XML = etree.tostring(script_tree, 
                                   xml_declaration=True, 
                                   doctype='<!DOCTYPE OpenWindScript>',
                                   pretty_print=True)
        
        self.ow.script_file = self.workDir + '/' + scriptFileName
        ofh = open(thisdir + '/' + self.ow.script_file, 'w')
        ofh.write(script_XML)
        ofh.close()
    
    # -------------------
    
    def updateRptPath(self, rptPathName, newScriptName):
        '''
        Writes a new script file and sets internal script name
        New script writes to 'rptPathName'
        rptPathName should be a full path name (if possible)
        '''
        
        if not hasattr(self,'ow'):
            sys.stderr.write("{:}: 'ow' not defined yet (missing script file?)\n".format(self.__class__))
            raise RuntimeError("OpenWind wrapped executable not defined")
            return
            
        e = rwScriptXML.parseScript(self.ow.script_file, debug=self.debug)
        rp = e.find("ReportPath")
        if rp is None:
            sys.stderr.write('Can\'t find report path in "{:}"\n'.format(self.ow.script_file))
            return
            
        if self.debug:
            sys.stderr.write('Changing report path from "{:}" to "{:}"\n'.format(rp.get('value'),rptPathName))
        rp.set('value',rptPathName)
        
        rwScriptXML.wrtScript(e, newScriptName)
        self.ow.script_file = self.workDir + '/' + newScriptName
        if self.debug:
            sys.stderr.write('Wrote new script file "{:}"\n'.format(self.ow.script_file))
示例#8
0
class HAWC2VarTrees(VariableTree):

    sim = VarTree(HAWC2Simulation())
    wind = VarTree(HAWC2Wind())
    aero = VarTree(HAWC2Aero())
    aerodrag = VarTree(HAWC2AeroDrag())
    blade_ae = VarTree(HAWC2BladeGeometry())
    blade_structure = List()
    airfoildata = VarTree(HAWC2AirfoilData())

    output = VarTree(HAWC2OutputVT())

    rotor = VarTree(RotorVT())
    nacelle = VarTree(NacelleVT())
    generator = VarTree(GeneratorVT())
    tower = VarTree(TowerVT())
    shaft = VarTree(ShaftVT())
    hub = VarTree(HubVT())

    body_order = List()
    main_bodies = VarTree(HAWC2MainBodyList())
    dlls = VarTree(HAWC2Type2DLLList())

    h2s = VarTree(HAWC2SVar())
示例#9
0
from openmdao.main.api import Component, VariableTree
from openmdao.lib.datatypes.api import Float, VarTree

#Variable Tree definition
class Gas(VariableTree):
	#default to helium
	cost = Float(6.452, desc='Cost in $USD, #/m^3, NASA Praxair Quote', units='USD/m**3')
	rho_stp = Float(0.1664, desc='density at Standard TP 273.15 and 1 atm', units='kg/m**3')
	rho_ntp = Float(0.1786, desc='density at Normal TP 293.15 K and 1 atm', units='kg/m**3')


#Library Values
#http://www.engineeringtoolbox.com/gas-density-d_158.html

#Helium
helium = VarTree(Gas(), iotype='in')
helium.cost = 6.452
helium.rho_ntp = 0.1664
helium.rho_stp = 0.1786
#Hydrogen
hydrogen = VarTree(Gas(), iotype='in')
hydrogen.cost = 1.14
hydrogen.rho_ntp = 0.0899
hydrogen.rho_stp = 0.0899
#Air
air = VarTree(Gas(), iotype='in')
air.cost = 0
air.rho_ntp = 1.205
air.rho_stp = 1.293

示例#10
0
class HAWC2GeometryBuilder(Component):

    bladegeom = VarTree(BladePlanformVT(), iotype='in')
    c12axis_init = Array(iotype='in')
    blade_ae = VarTree(HAWC2BladeGeometry(), iotype='out')
    interp_from_htc = Bool(
        True,
        iotype='in',
        desc=
        'Interpolate blade onto the distribution defined in the htc master file'
    )
    blade_ni_span = Int(30,
                        iotype='in',
                        desc='spanwise distribution of blade planform')

    blade_length = Float(86.366, iotype='in')
    hub_radius = Float(2.8, iotype='in')

    def execute(self):

        c12axis = self.calculate_c12axis()

        if self.interp_from_htc:
            cni = self.c12axis_init.shape[0]
            if self.c12axis_init[-1, 2] > 1.:
                self.c12axis_init /= self.blade_length

            # interpolate blade_ae distribution onto c12 distribution
            self.blade_ae.c12axis = np.zeros((cni, 4))
            for i in range(4):
                tck = pchip(c12axis[:, 2], c12axis[:, i])
                self.blade_ae.c12axis[:, i] = tck(self.c12axis_init[:, 2])
        else:
            ds_root = 1. / self.blade_ni_span
            ds_tip = 1. / self.blade_ni_span / 3.
            dist = np.array([[0., ds_root, 1],
                             [1., ds_tip, self.blade_ni_span]])
            x = distfunc(dist)
            self.blade_ae.c12axis = np.zeros((x.shape[0], 4))
            for i in range(4):
                tck = pchip(c12axis[:, 2], c12axis[:, i])
                self.blade_ae.c12axis[:, i] = tck(x)

        # scale main axis according to radius
        self.blade_ae.c12axis[:, :3] *= self.blade_length

        self.blade_ae.radius = self.blade_length + self.hub_radius
        self.blade_ae.s = self.bladegeom.smax * self.bladegeom.s * self.blade_length
        self.blade_ae.rthick = self.bladegeom.rthick * 100.
        self.blade_ae.chord = self.bladegeom.chord * self.blade_length
        self.blade_ae.aeset = np.ones(len(self.blade_ae.s))

    def calculate_c12axis(self):
        """
        compute the 1/2 chord axis based on the blade axis and chordwise rotation point

        nb: this only works for straight blades!
        """

        # The HAWC2 blade axis is defined using the 1/2 chord points
        b = self.bladegeom
        c12axis = np.zeros((b.x.shape[0], 4))
        for i in range(b.x.shape[0]):
            xc12 = (0.5 - b.p_le[i]) * b.chord[i] * np.cos(
                b.rot_z[i] * np.pi / 180.)
            yc12 = -(0.5 - b.p_le[i]) * b.chord[i] * np.sin(
                b.rot_z[i] * np.pi / 180.)
            c12axis[i, 0] = -(b.x[i] + xc12)
            c12axis[i, 1] = b.y[i] + yc12
            c12axis[i, 2] = b.z[i]
        c12axis[:, 3] = b.rot_z
        return c12axis
示例#11
0
class FullBOSCostAggregator(Component):
    """ Full balance of station cost aggregator for doing some auxiliary cost calculations needed to get a full wind plant balance of station cost estimate as well as a detailed cost breakdown.    """

    # outputs
    bos_breakdown = VarTree(FullBOSVarTree(), iotype='out', desc='BOS cost breakdown')
    bos_costs = Float(iotype='out', desc='Output BOS cost elements')
示例#12
0
class ExtendedBOSCostModel(Assembly):
    """ Extended balance of station cost assembly for coupling models to get a full wind plant balance of station cost estimate as well as a detailed cost breakdown.    """

    # Outputs
    bos_breakdown = VarTree(BOSVarTree(), iotype='out', desc='BOS cost breakdown')
    bos_costs = Float(iotype='out', desc='Overall wind plant balance of station/system costs up to point of comissioning')
示例#13
0
class ExtendedBOSCostAggregator(Component):
    """ Extended balance of station cost aggregator for doing some auxiliary cost calculations needed to get a full wind plant balance of station cost estimate as well as a detailed cost breakdown.    """

    # Outputs
    bos_breakdown = VarTree(BOSVarTree(), iotype='out', desc='BOS cost breakdown')
    bos_costs = Float(iotype='out', desc='Overall wind plant balance of station/system costs up to point of comissioning')
示例#14
0
class FullBOSCostModel(Assembly):
	  
    # outputs
    bos_breakdown = VarTree(FullBOSVarTree(), iotype='out', desc='BOS cost breakdown')
    bos_costs = Float(iotype='out', desc='Output BOS cost elements')	  
示例#15
0
class BladeStructureWriterBase(Component):

    st3d = VarTree(
        BladeStructureVT3D(),
        iotype='in',
        desc='Vartree containing discrete definition of blade structure')
示例#16
0
class HAWC2Type2DLL(VariableTree):

    name = Str(
        desc='Reference name of this DLL (to be used with DLL output commands)'
    )
    filename = Str(
        desc=
        'Filename incl. relative path of the DLL (example ./DLL/control.dll)')
    dll_subroutine_init = Str(
        desc='Name of initialization subroutine in DLL that is addressed'
        '(remember to specify the name in the DLL with small letters!)')
    dll_subroutine_update = Str(
        desc='Name of subroutine in DLL that is addressed at every time step'
        '(remember to specify the name in the DLL with small letters!)')
    arraysizes_init = List(
        desc=
        'size of array with outgoing/ingoing data in the initialization call')
    arraysizes_update = List(
        desc='size of array with outgoing/ingoing data in the update call')
    deltat = Float(desc='Time between dll calls.')
    dll_init = VarTree(HAWC2Type2DLLinit(),
                       desc='Slot for DLL specific variable tree')
    output = VarTree(HAWC2Type2DLLoutput(),
                     desc='Outputs for DLL specific variable tree')
    actions = VarTree(HAWC2Type2DLLoutput(),
                      desc='Actions for DLL specific variable tree')

    def set_init(self, name):
        """
        sets the parameters slot with the VariableTree corresponding to the
        name string defined in the type2_dll interface
        """
        try:
            klass = type2_dll_dict[name]
            self.dll_init = klass()
        except:
            self._logger.warning(
                'No init vartree available for %s, falling back on default HAWC2Type2DLLinit'
                % self.name)
        return self.dll_init

    def set_output(self, name):
        """
        sets the parameters slot with the VariableTree corresponding to the
        name string defined in the type2_dll interface
        """
        try:
            klass = type2_dll_out_dict[name]
            self.output = klass()
        except:
            self._logger.warning(
                'No output vartree available for %s, falling back on default HAWC2Type2DLLoutput'
                % self.name)
        return self.output

    def set_actions(self, name):
        """
        sets the parameters slot with the VariableTree corresponding to the
        name string defined in the type2_dll interface
        """
        try:
            klass = type2_dll_action_dict[name]
            self.actions = klass()
        except:
            self._logger.warning(
                'No actions vartree available for %s, falling back on default HAWC2Type2DLLoutput'
                % self.name)
        return self.actions
示例#17
0
class BladeStructureWriter(Component):
    """
    input file writer of BladeStructureVT3D data
    """

    filebase = Str('blade', iotype='in')
    st3d = VarTree(BladeStructureVT3D(), iotype='in')

    def execute(self):

        try:
            if '-fd' in self.itername or '-fd' in self.parent.itername:
                return
            else:
                self.fbase = self.filebase + '_' + str(self.exec_count)
        except:
            self.fbase = self.filebase
        self.fbase = self.filebase

        self.write_layup_data()
        self.write_materials()

    def write_materials(self):

        fid = open(self.fbase + '.mat', 'w')
        fid.write('# %s\n' % (' '.join(self.st3d.materials.keys())))
        fid.write('# E1 E2 E3 nu12 nu13 nu23 G12 G13 G23 rho\n')
        matdata = []
        for name, mat in self.st3d.materials.iteritems():
            data = np.array([
                mat.E1, mat.E2, mat.E3, mat.nu12, mat.nu13, mat.nu23, mat.G12,
                mat.G13, mat.G23, mat.rho
            ])
            matdata.append(data)

        np.savetxt(fid, np.asarray(matdata))

        failcrit = dict(maximum_strain=1, maximum_stress=2, tsai_wu=3)
        fid = open(self.fbase + '.failmat', 'w')
        fid.write('# %s\n' % (' '.join(self.st3d.materials.keys())))
        fid.write('# failcrit s11_t s22_t s33_t s11_c s22_c s33_c'
                  't12 t13 t23 e11_c e22_c e33_c e11_t e22_t e33_t g12 g13 g23'
                  'gM0 C1a C2a C3a C4a\n')
        matdata = []
        for name, mat in self.st3d.materials.iteritems():
            data = np.array([
                failcrit[mat.failure_criterium], mat.s11_t, mat.s22_t,
                mat.s33_t, mat.s11_c, mat.s22_c, mat.s33_c, mat.t12, mat.t13,
                mat.t23, mat.e11_c, mat.e22_c, mat.e33_c, mat.e11_t, mat.e22_t,
                mat.e33_t, mat.g12, mat.g13, mat.g23, mat.gM0, mat.C1a,
                mat.C2a, mat.C3a, mat.C4a
            ])
            matdata.append(data)
        fmt = '%i ' + ' '.join(23 * ['%.20e'])
        np.savetxt(fid, np.asarray(matdata), fmt=fmt)

    def write_layup_data(self):

        DPs = []

        fid1 = open(self.fbase + '.dp3d', 'w')
        fid1.write('# %s\n' % ('  '.join(self.st3d.webs)))
        for web in self.st3d.iwebs:
            fid1.write('# %i %i\n' % (web[0], web[1]))
        fid1.write('# s %s\n' % ('  '.join(self.st3d.DPs)))
        DPs.append(self.st3d.x)
        for i, rname in enumerate(self.st3d.regions):

            self._logger.info('  writing region: %s' % rname)
            reg = getattr(self.st3d, rname)

            DP = getattr(self.st3d, 'DP%02d' % (i))
            DPs.append(DP)

            fname = '_'.join([self.fbase, rname]) + '.st3d'
            fid = open(fname, 'w')
            lnames = '    '.join(reg.layers)
            fid.write('# %s\n' % rname)
            fid.write('# s    %s\n' % lnames)
            data = []
            data.append(self.st3d.x)
            for lname in reg.layers:
                self._logger.info('    writing layer: %s' % lname)
                layer = getattr(reg, lname)
                data.append(layer.thickness)
            for lname in reg.layers:
                self._logger.info('    writing layer: %s' % lname)
                layer = getattr(reg, lname)
                data.append(layer.angle)
            data = np.asarray(data).T
            np.savetxt(fid, data)
            fid.close()
        DPs.append(getattr(self.st3d, 'DP%02d' % (i + 1)))
        DPs = np.asarray(DPs).T
        np.savetxt(fid1, DPs)
        for i, wname in enumerate(self.st3d.webs):

            self._logger.info('  writing web: %s' % rname)
            reg = getattr(self.st3d, wname)
            fname = '_'.join([self.fbase, wname]) + '.st3d'
            fid = open(fname, 'w')
            lnames = '    '.join(reg.layers)
            fid.write('# %s\n' % wname)
            fid.write('# s    %s\n' % lnames)
            data = []
            data.append(self.st3d.x)
            for lname in reg.layers:
                self._logger.info('    writing layer: %s' % lname)
                layer = getattr(reg, lname)
                data.append(layer.thickness)
            for lname in reg.layers:
                self._logger.info('    writing layer: %s' % lname)
                layer = getattr(reg, lname)
                data.append(layer.angle)
            data = np.asarray(data).T
            np.savetxt(fid, data)
            fid.close()
示例#18
0
class WeibullWindRose(Component):
    """Calculates the frequency_array using a weibull distribution"""
    wind_directions = List(iotype='in',
                           units='deg',
                           desc='Direction sectors angles [n_wd]')
    wind_speeds = List(iotype='in',
                       units='m/s',
                       desc='wind speeds sectors [n_ws]')
    wind_rose_array = Array(
        [],
        iotype='in',
        units='m/s',
        desc='Windrose array [wind_directions, frequency, weibull_A, weibull_k]'
    )
    cut_in = Float(4.0,
                   iotype='in',
                   desc='The cut-in wind speed of the wind turbine')
    cut_out = Float(25.0,
                    iotype='in',
                    desc='The cut-out wind speed of the wind turbine')

    wind_rose = VarTree(GenericWindRoseVT(),
                        iotype='out',
                        desc='A wind rose VT')

    @property
    def n_wd(self):
        """Number of wind direction bins"""
        return len(self.wind_directions)

    @property
    def n_ws(self):
        """Number of wind speed bins"""
        return len(self.wind_speeds)

    def test_consistency_inputs(self):
        """Test the consistency of the inputs. This will be optimized away in production"""
        assert len(self.wind_rose_array) > 0,\
            'wind_rose_array is empty: %r' % self.wind_rose_array
        assert len(self.wind_speeds) > 0,\
            'wind_speeds is empty: %r' % self.wind_speeds
        assert len(self.wind_directions) > 0,\
            'wind_directions is empty: %r' % self.wind_directions
        assert isinstance(self.wind_rose_array, ndarray),\
            'The wind rose array is a ndarray of 4 columns'
        assert self.wind_rose_array.shape[1] == 4,\
            'wind_rose_array = array([wind_directions, frequency, weibull_A, weibull_k])'
        assert mean(self.wind_directions) > 20.0,\
            'Wind direction should be given in degrees'
        assert self.wind_rose_array[:, 0].mean() > 20.0,\
            'The first column of wind_rose should be in degrees'
        assert 1.0 - sum(self.wind_rose_array[:, 1]) < 1.0E-3,\
            'The second column of self.wind_rose_array should sum to 1.0'

    def test_consistency_outputs(self):
        """Test the consistency of the outputs. This will be optimized away in production"""
        assert sum(self.wind_rose.frequency_array.flatten()) <= 1.0 + 1.0E-3, \
            'The frequency array should never reach 1.0, because there are some high wind speeds not considered in the array.'

    def execute(self):
        """Calculate the new wind_rose"""
        if len(self.wind_rose_array) == 0:
            return

        self.test_consistency_inputs()

        self._directions = self.wind_rose_array[:, 0]
        _direction_frequency = self.wind_rose_array[:, 1]
        self._weibull_A = self.wind_rose_array[:, 2]
        self._weibull_k = self.wind_rose_array[:, 3]

        # Creating the interpolation functions
        indis = range(self.wind_rose_array.shape[0])
        indis.extend([0])
        _d_wd = self._directions[1] - self._directions[0]
        diff_dir = _direction_frequency[indis] / _d_wd
        directions = self._directions.tolist() + [360.0]

        def corr_dir(d):
            if d < 0.0:
                return d + 360.0
            if d >= 360.0:
                return d - 360.0
            return d

        pdf_wd = interp1d(directions, diff_dir, kind='linear')
        pdf_wd_ext = lambda d: pdf_wd(corr_dir(d))
        weibull_A = interp1d(directions, self._weibull_A[indis], kind='linear')
        weibull_k = interp1d(directions, self._weibull_k[indis], kind='linear')
        self.wind_rose.wind_directions = self.wind_directions
        self.wind_rose.wind_speeds = self.wind_speeds

        # Statistical functions
        pdf_ws = lambda A, k, u: k / A * \
            (u / A) ** (k - 1.0) * exp(-(u / A) ** k)
        #cdf_ws = lambda A,k,u, bin=1.0: exp(-(max(0.0, u-bin/2.0)/A)**k) - exp(-((u+bin/2.0)/A)**k)
        cdf_ws = lambda A, k, u0, u1: exp(-(u0 / A)**k) - exp(-(u1 / A)**k)
        # TODO: Fine tune this epsrel
        cdf_wd = lambda wd0, wd1: quad(pdf_wd_ext, wd0, wd1, epsrel=0.1)[0]

        # Create the array
        self.wind_rose.frequency_array = zeros([self.n_wd, self.n_ws])

        for iwd, wd in enumerate(self.wind_directions):

            A = weibull_A(wd)
            k = weibull_k(wd)

            # We include all the wind directions between each wind directions
            if iwd == 0:
                wd0 = 0.5 * (self.wind_directions[-1] + wd + 360)
            else:
                wd0 = 0.5 * (self.wind_directions[iwd - 1] + wd)
            if iwd == len(self.wind_directions) - 1:
                wd1 = 0.5 * (self.wind_directions[0] + wd + 360)
            else:
                wd1 = 0.5 * (self.wind_directions[iwd + 1] + wd)

            if wd0 > wd1:  # deal with the 360-0 issue
                P_dir = cdf_wd(wd0, 359.99) + cdf_wd(0.0, wd1)
            else:
                P_dir = cdf_wd(wd0, wd1)
            # print 'between', wd0, wd1, P_dir
            for iws, ws in enumerate(self.wind_speeds):
                if iws == 0:  # We include all the cases from cut_in
                    ws0 = self.cut_in
                else:
                    ws0 = 0.5 * (self.wind_speeds[iws - 1] + ws)
                if iws == len(self.wind_speeds) - 1:
                    ws1 = self.cut_out
                else:
                    ws1 = 0.5 * (self.wind_speeds[iws + 1] + ws)
                ws0 = min(self.cut_out, max(self.cut_in, ws0))
                ws1 = min(self.cut_out, max(self.cut_in, ws1))

                self.wind_rose.frequency_array[iwd, iws] = P_dir * cdf_ws(
                    A, k, ws0, ws1)

        self.test_consistency_outputs()
示例#19
0
class BeamStructureReaderBase(Component):

    beamprops = VarTree(BeamStructureVT(), iotype='out')
 def add_region(self, name):
     self.add(name, VarTree(RegionVT()))
     self.regions.append(name)
示例#21
0
class SplinedBladeStructure(Assembly):
    """
    Class for building a complete spline parameterized
    representation of the blade structure.

    Outputs a BladeStructureVT3D vartree with a discrete
    representation of the structural geometry.

    Interface with a BladeStructureBuilder class for generating code specific
    inputs.
    """

    x = Array(iotype='in', desc='spanwise resolution of blade')
    span_ni = Int(20, iotype='in', desc='Number of discrete points along span')
    nC = Int(8, iotype='in', desc='Number of spline control points along span')
    Cx = Array(iotype='in',
               desc='spanwise distribution of spline control points')
    st3dIn = VarTree(
        BladeStructureVT3D(),
        iotype='in',
        desc='Vartree containing initial discrete definition of blade structure'
    )
    st3dOut = VarTree(
        BladeStructureVT3D(),
        iotype='out',
        desc=
        'Vartree containing re-splined discrete definition of blade structure')

    def __init__(self):
        """
        initialize the blade structure

        parameters
        -----------
        nsec: int
            total number of sections in blade
        """
        super(SplinedBladeStructure, self).__init__()

        self._nsec = 0

        self.add('pf', RedistributedBladePlanform())
        self.driver.workflow.add('pf')
        self.create_passthrough('pf.pfIn')
        self.create_passthrough('pf.pfOut.blade_length')
        self.connect('x', 'pf.x')

    def configure_bladestructure(self):
        """
        method for trawling through the st3dIn vartree
        and initializing all spline curves in the assembly
        """

        if self.x.shape[0] == 0:
            self.x = np.linspace(0, 1, self.span_ni)
        else:
            self.span_ni = self.x.shape[0]
        if self.Cx.shape[0] == 0:
            self.Cx = np.linspace(0, 1, self.nC)
        else:
            self.nC = self.Cx.shape[0]

        self.st3dOut = self.st3dIn.copy()
        self.connect('x', 'st3dOut.x')

        sec = self.st3dIn
        nr = len(sec.regions)
        for ip in range(nr + 1):
            dpname = 'DP%02d' % ip
            # division point spline
            DPc = self.add(dpname, FFDSplineComponentBase(self.nC))
            self.driver.workflow.add(dpname)
            # DPc.log_level = logging.DEBUG
            x = getattr(sec, 'x')
            DP = getattr(sec, dpname)
            self.connect('x', '%s.x' % dpname)
            self.connect('Cx', dpname + '.Cx')
            DPc.xinit = x
            DPc.Pinit = DP
            self.connect(dpname + '.P', '.'.join(['st3dOut', dpname]))
            self.create_passthrough(dpname + '.C', alias=dpname + '_C')
            # regions
            if ip < nr:
                rname = 'region%02d' % ip
                region = getattr(sec, rname)
                for lname in region.layers:
                    layer = getattr(region, lname)
                    lcname = 'r%02d%s' % (ip, lname)
                    # thickness spline
                    lcomp = self.add(lcname + 'T',
                                     FFDSplineComponentBase(self.nC))
                    self.driver.workflow.add(lcname + 'T')
                    # lcomp.log_level = logging.DEBUG
                    self.connect('x', '%s.x' % (lcname + 'T'))
                    lcomp.xinit = sec.x
                    lcomp.Pinit = layer.thickness
                    self.connect('Cx', lcname + 'T' + '.Cx')
                    self.connect(
                        '%sT.P' % lcname,
                        '.'.join(['st3dOut', rname, lname, 'thickness']))
                    # angle spline
                    lcomp = self.add(lcname + 'A',
                                     FFDSplineComponentBase(self.nC))
                    self.driver.workflow.add(lcname + 'A')
                    # lcomp.log_level = logging.DEBUG
                    self.connect('x', '%s.x' % (lcname + 'A'))
                    self.create_passthrough(lcname + 'T' + '.C',
                                            alias=lcname + 'T' + '_C')
                    lcomp.xinit = sec.x
                    lcomp.Pinit = layer.angle
                    self.connect('Cx', lcname + 'A' + '.Cx')
                    self.connect('%sA.P' % lcname,
                                 '.'.join(['st3dOut', rname, lname, 'angle']))
                    self.create_passthrough(lcname + 'A' + '.C',
                                            alias=lcname + 'A' + '_C')
        # shear webs
        for wname in sec.webs:
            web = getattr(sec, wname)
            for lname in web.layers:
                layer = getattr(web, lname)
                lcname = '%s%s' % (wname, lname)
                # thickness spline
                lcomp = self.add(lcname + 'T', FFDSplineComponentBase(self.nC))
                # lcomp.log_level = logging.DEBUG
                self.driver.workflow.add(lcname + 'T')
                self.connect('x', '%s.x' % (lcname + 'T'))
                lcomp.xinit = sec.x
                lcomp.Pinit = layer.thickness
                self.connect('Cx', lcname + 'T' + '.Cx')
                self.connect('%sT.P' % lcname,
                             '.'.join(['st3dOut', wname, lname, 'thickness']))
                self.create_passthrough(lcname + 'T' + '.C',
                                        alias=lcname + 'T' + '_C')
                # angle spline
                lcomp = self.add(lcname + 'A', FFDSplineComponentBase(self.nC))
                # lcomp.log_level = logging.DEBUG
                self.driver.workflow.add(lcname + 'A')
                self.connect('x', '%s.x' % (lcname + 'A'))
                lcomp.xinit = sec.x
                lcomp.Pinit = layer.angle
                self.connect('Cx', lcname + 'A' + '.Cx')
                self.connect('%sA.P' % lcname,
                             '.'.join(['st3dOut', wname, lname, 'angle']))
                self.create_passthrough(lcname + 'A' + '.C',
                                        alias=lcname + 'A' + '_C')

        # copy materials to output VT
        self.st3dOut.materials = self.st3dIn.materials.copy()

    def _post_execute(self):
        """
        update all thicknesses and region widths
        """
        super(SplinedBladeStructure, self)._post_execute()

        for i, rname in enumerate(self.st3dOut.regions):
            region = getattr(self.st3dOut, rname)
            DP0 = getattr(self.st3dOut, 'DP%02d' % i)
            DP1 = getattr(self.st3dOut, 'DP%02d' % (i + 1))
            width = DP1 - DP0
            for ix in range(width.shape[0]):
                if width[ix] < 0.:
                    DPt = DP0[ix]
                    DP0[ix] = DP1[ix]
                    DP1[ix] = DPt
                    width[ix] *= -1.
                    self._logger.warning('switching DPs %i %i for section %i' %
                                         (i, i + 1, ix))
            region.width = width * self.pf.pfOut.chord * self.blade_length
            region.thickness = np.zeros(self.st3dOut.x.shape)
            for layer in region.layers:
                region.thickness += np.maximum(
                    0.,
                    getattr(region, layer).thickness)

        for i, rname in enumerate(self.st3dOut.webs):
            region = getattr(self.st3dOut, rname)
            region.thickness = np.zeros(self.st3dOut.x.shape)
            for layer in region.layers:
                region.thickness += np.maximum(
                    0.,
                    getattr(region, layer).thickness)
示例#22
0
class FEM(Component):
    """
    Computes the deformation of the spar
    """

    # inputs
    flags = VarTree(Flags(), iotype='in')

    yN = Array(iotype='in', desc='')

    EIx = Array(iotype='in', desc='')
    EIz = Array(iotype='in', desc='')
    EA = Array(iotype='in', desc='')
    GJ = Array(iotype='in', desc='')

    cE = Array(iotype='in', desc='chord of each element')
    xEA = Array(iotype='in', desc='')

    fblade = VarTree(Fblade(), iotype='in')

    mSpar = Array(iotype='in', desc='mass of spars')
    mChord = Array(iotype='in', desc='mass of chords')
    xCG = Array(iotype='in', desc='')

    yWire = Array(iotype='in', desc='location of wire attachment along span')
    zWire = Float(iotype='in', desc='depth of wire attachement')
    TWire = Array(iotype='in', desc='')

    presLoad = VarTree(PrescribedLoad(), iotype='in')

    # outputs
    k = Array(iotype='out', desc='local elastic stiffness matrix')
    K = Array(iotype='out', desc='global stiffness matrix')
    F = Array(iotype='out', desc='global force vector')
    q = Array(iotype='out', desc='deformation')

    def execute(self):
        # short aliases
        yN = self.yN
        EIx = self.EIx
        EIz = self.EIz
        EA = self.EA
        GJ = self.GJ
        xEA = self.xEA
        cE = self.cE
        mSpar = self.mSpar
        mChord = self.mChord
        xCG = self.xCG
        yWire = self.yWire
        zWire = self.zWire
        TWire = self.TWire
        fblade = self.fblade
        presLoad = self.presLoad

        Ns = len(yN) - 1  # number of elements
        dy = np.zeros(Ns)
        for s in range(Ns + 1):
            dy[s - 1] = yN[s] - yN[s - 1]  # length of each element

        # FEM computation for structural deformations
        # -------------------------------------------

        # Initialize global stiffness matrix
        K = np.zeros(((Ns + 1) * 6, (Ns + 1) * 6))  # global stiffness
        F = np.zeros(((Ns + 1) * 6, 1))  # global force vector

        # Create global stiffness maxtrix and force vector
        k = np.zeros((12, 12, Ns))

        for s in range(Ns):

            # Local elastic stiffness matrix
            k[0, 0, s] = 12 * EIx[s] / (dy[s] * dy[s] * dy[s])
            k[0, 5, s] = -6 * EIx[s] / (dy[s] * dy[s])
            k[5, 0, s] = k[0, 5, s]
            k[0, 6, s] = -12 * EIx[s] / (dy[s] * dy[s] * dy[s])
            k[6, 0, s] = k[0, 6, s]
            k[0, 11, s] = -6 * EIx[s] / (dy[s] * dy[s])
            k[11, 0, s] = k[0, 11, s]
            k[1, 1, s] = EA[s] / dy[s]
            k[1, 7, s] = -EA[s] / dy[s]
            k[7, 1, s] = k[1, 7, s]
            k[2, 2, s] = 12 * EIz[s] / (dy[s] * dy[s] * dy[s])
            k[2, 3, s] = 6 * EIz[s] / (dy[s] * dy[s])
            k[3, 2, s] = k[2, 3, s]
            k[2, 8, s] = -12 * EIz[s] / (dy[s] * dy[s] * dy[s])
            k[8, 2, s] = k[2, 8, s]
            k[2, 9, s] = 6 * EIz[s] / (dy[s] * dy[s])
            k[9, 2, s] = k[2, 9, s]
            k[3, 3, s] = 4 * EIz[s] / dy[s]
            k[3, 8, s] = -6 * EIz[s] / (dy[s] * dy[s])
            k[8, 3, s] = k[3, 8, s]
            k[3, 9, s] = 2 * EIz[s] / dy[s]
            k[9, 3, s] = k[3, 9, s]
            k[4, 4, s] = GJ[s] / dy[s]
            k[4, 10, s] = -GJ[s] / dy[s]
            k[10, 4, s] = k[4, 10, s]
            k[5, 5, s] = 4 * EIx[s] / dy[s]
            k[5, 6, s] = 6 * EIx[s] / (dy[s] * dy[s])
            k[6, 5, s] = k[5, 6, s]
            k[5, 11, s] = 2 * EIx[s] / dy[s]
            k[11, 5, s] = k[5, 11, s]
            k[6, 6, s] = 12 * EIx[s] / (dy[s] * dy[s] * dy[s])
            k[6, 11, s] = 6 * EIx[s] / (dy[s] * dy[s])
            k[11, 6, s] = k[6, 11, s]
            k[7, 7, s] = EA[s] / dy[s]
            k[8, 8, s] = 12 * EIz[s] / (dy[s] * dy[s] * dy[s])
            k[8, 9, s] = -6 * EIz[s] / (dy[s] * dy[s])
            k[9, 8, s] = k[8, 9, s]
            k[9, 9, s] = 4 * EIz[s] / dy[s]
            k[10, 10, s] = GJ[s] / dy[s]
            k[11, 11, s] = 4 * EIx[s] / dy[s]

            # Perform dihedral and sweep rotations here if needed

            # Assemble global stiffness matrix
            K[(6*s):(6*s + 12), (6*s):(6*s + 12)] = \
                K[(6*s):(6*s + 12), (6*s):(6*s + 12)] + k[:, :, s]

            Faero = np.zeros((6, 1))
            if self.flags.Load == 0:  # include aero forces
                # aerodynamic forces
                xAC = 0.25
                Faero[0] = fblade.Fx[s] / 2
                Faero[1] = 0
                Faero[2] = fblade.Fz[s] / 2
                Faero[3] = fblade.Fz[s] * dy[s] / 12
                Faero[4] = fblade.My[s] / 2 + (xEA[s] -
                                               xAC) * cE[s] * fblade.Fz[s] / 2
                Faero[5] = -fblade.Fx[s] * dy[s] / 12

            Fg = np.zeros((6, 1))
            Fwire = np.zeros((12, 1))

            if (self.flags.Load == 0) or (self.flags.Load == 1):
                # gravitational forces
                g = 9.81
                Fg[0] = 0
                Fg[1] = 0
                Fg[2] = -(mSpar[s] + mChord[s]) * g / 2
                Fg[3] = -(mSpar[s] + mChord[s]) * g * dy[s] / 12
                Fg[4] = (xCG[s] - xEA[s]) * cE[s] * (mSpar[s] +
                                                     mChord[s]) * g / 2
                Fg[5] = 0

                # Wire forces (using consistent force vector)
                for w in range(len(yWire)):
                    if (yWire[w] >= yN[s]) and (yWire[w] < yN[s + 1]):
                        thetaWire = atan2(zWire, yWire[w])
                        a = yWire[w] - yN[s]
                        L = dy[s]
                        FxWire = -cos(thetaWire) * TWire[w]
                        FzWire = -sin(thetaWire) * TWire[w]
                        Fwire[0] = 0
                        Fwire[1] = FxWire * (1 - a / L)
                        Fwire[2] = FzWire * (2 * (a / L)**3 - 3 *
                                             (a / L)**2 + 1)
                        Fwire[3] = FzWire * a * ((a / L)**2 - 2 * (a / L) + 1)
                        Fwire[4] = 0
                        Fwire[5] = 0
                        Fwire[6] = 0
                        Fwire[7] = FxWire * (a / L)
                        Fwire[8] = FzWire * (-2 * (a / L)**3 + 3 * (a / L)**2)
                        Fwire[9] = FzWire * a * ((a / L)**2 - (a / L))
                        Fwire[10] = 0
                        Fwire[11] = 0
                    else:
                        Fwire = np.zeros((12, 1))

            Fpres = np.zeros((12, 1))

            if self.flags.Load == 2:
                # Prescribed point load (using consistent force vector)
                if (presLoad.y >= yN[s]) and (presLoad.y < yN[s + 1]):
                    a = presLoad.y - yN[s]
                    L = dy[s]
                    Fpres[0] = 0
                    Fpres[1] = 0
                    Fpres[2] = presLoad.pointZ * (2 * (a / L)**3 - 3 *
                                                  (a / L)**2 + 1)
                    Fpres[3] = presLoad.pointZ * a * ((a / L)**2 - 2 *
                                                      (a / L) + 1)
                    Fpres[4] = presLoad.pointM * (1 - a / L)
                    Fpres[5] = 0
                    Fpres[6] = 0
                    Fpres[7] = 0
                    Fpres[8] = presLoad.pointZ * (-2 * (a / L)**3 + 3 *
                                                  (a / L)**2)
                    Fpres[9] = presLoad.pointZ * a * ((a / L)**2 - (a / L))
                    Fpres[10] = presLoad.pointM * (a / L)
                    Fpres[11] = 0

                # Prescribed distributed load
                Fpres[0] = Fpres[0] + presLoad.distributedX * dy[s] / 2
                Fpres[1] = Fpres[1] + 0
                Fpres[2] = Fpres[2] + presLoad.distributedZ * dy[s] / 2
                Fpres[
                    3] = Fpres[3] + presLoad.distributedZ * dy[s] * dy[s] / 12
                Fpres[4] = Fpres[4] + presLoad.distributedM * dy[s] / 2
                Fpres[
                    5] = Fpres[5] - presLoad.distributedX * dy[s] * dy[s] / 12
                Fpres[6] = Fpres[6] + presLoad.distributedX * dy[s] / 2
                Fpres[7] = Fpres[7] + 0
                Fpres[8] = Fpres[8] + presLoad.distributedZ * dy[s] / 2
                Fpres[
                    9] = Fpres[9] - presLoad.distributedZ * dy[s] * dy[s] / 12
                Fpres[10] = Fpres[10] + presLoad.distributedM * dy[s] / 2
                Fpres[11] = Fpres[
                    11] + presLoad.distributedX * dy[s] * dy[s] / 12

            # Assemble global force vector
            F[(s * 6 +
               0)] = F[(s * 6 +
                        0)] + Fpres[0] + Fwire[0] + Fg[0] + Faero[0]  # x force
            F[(s * 6 +
               1)] = F[(s * 6 +
                        1)] + Fpres[1] + Fwire[1] + Fg[1] + Faero[1]  # y force
            F[(s * 6 +
               2)] = F[(s * 6 +
                        2)] + Fpres[2] + Fwire[2] + Fg[2] + Faero[2]  # z force
            F[(s * 6 +
               3)] = F[(s * 6 + 3
                        )] + Fpres[3] + Fwire[3] + Fg[3] + Faero[3]  # x moment
            F[(s * 6 +
               4)] = F[(s * 6 + 4
                        )] + Fpres[4] + Fwire[4] + Fg[4] + Faero[4]  # y moment
            F[(s * 6 +
               5)] = F[(s * 6 + 5
                        )] + Fpres[5] + Fwire[5] + Fg[5] + Faero[5]  # z moment
            F[(s * 6 +
               6)] = F[(s * 6 +
                        6)] + Fpres[6] + Fwire[6] + Fg[0] + Faero[0]  # x force
            F[(s * 6 +
               7)] = F[(s * 6 +
                        7)] + Fpres[7] + Fwire[7] + Fg[1] + Faero[1]  # y force
            F[(s * 6 +
               8)] = F[(s * 6 +
                        8)] + Fpres[8] + Fwire[8] + Fg[2] + Faero[2]  # z force
            F[(s * 6 +
               9)] = F[(s * 6 + 9
                        )] + Fpres[9] + Fwire[9] - Fg[3] - Faero[3]  # x moment
            F[(s * 6 +
               10)] = F[(s * 6 + 10)] + Fpres[10] + Fwire[10] + Fg[4] + Faero[
                   4]  # y moment
            F[(s * 6 +
               11)] = F[(s * 6 + 11)] + Fpres[11] + Fwire[11] - Fg[5] - Faero[
                   5]  # z moment

        # Add constraints to all 6 dof at root

        if self.flags.wingWarp > 0:  # Also add wingWarping constraint
            raise Exception(
                'FEM is untested and surely broken for wingWarp > 0')
            ii = np.array([])
            for ss in range((Ns + 1) * 6 - 1):
                if (ss > 5) and (ss != self.flags.wingWarp * 6 + 5):
                    ii = np.array([ii, ss]).reshape(1, -1)
            Fc = F[(ii - 1)]
            Kc = K[(ii - 1), (ii - 1)]
        else:
            Fc = F[6:]
            Kc = K[6:, 6:]

        # Solve constrained system
        qc, _, _, _ = np.linalg.lstsq(Kc, Fc)

        if self.flags.wingWarp > 0:
            self.q[ii, 1] = qc
        else:
            # self.q = np.array([0, 0, 0, 0, 0, 0, qc]).reshape(1, -1)
            self.q = np.append(
                np.array([0, 0, 0, 0, 0, 0]).reshape(-1, 1),
                qc).reshape(-1, 1)

        # output the stiffness and force arrays as well (for use in failure analysis)
        self.k = k
        self.K = K
        self.F = F
示例#23
0
class BladeStructureReader(Component):
    """
    input file reader of BladeStructureVT3D data
    """

    filebase = Str(iotype='in')

    st3d = VarTree(
        BladeStructureVT3D(),
        iotype='out',
        desc='Vartree containing discrete definition of blade structure')

    def execute(self):

        self.read_layups()
        self.read_materials()

    def read_materials(self):

        fid = open(self.filebase + '.mat', 'r')
        materials = fid.readline().split()[1:]
        data = np.loadtxt(fid)
        for i, name in enumerate(materials):
            mat = self.st3d.add_material(name)
            try:
                d = data[i, :]
            except:
                d = data
            mat.E1 = d[0]
            mat.E2 = d[1]
            mat.E3 = d[2]
            mat.nu12 = d[3]
            mat.nu13 = d[4]
            mat.nu23 = d[5]
            mat.G12 = d[6]
            mat.G13 = d[7]
            mat.G23 = d[8]
            mat.rho = d[9]

        failcrit = {1: 'maximum_strain', 2: 'maximum_stress', 3: 'tsai_wu'}
        fid = open(self.filebase + '.failmat', 'r')
        materials = fid.readline().split()[1:]
        data = np.loadtxt(fid)
        for i, name in enumerate(materials):
            mat = self.st3d.add_material(name)
            try:
                d = data[i, :]
            except:
                d = data
            mat.failure_criterium = failcrit[int(d[0])]
            mat.s11_t = d[1]
            mat.s22_t = d[2]
            mat.s33_t = d[3]
            mat.s11_c = d[4]
            mat.s22_c = d[5]
            mat.s33_c = d[6]
            mat.t12 = d[7]
            mat.t13 = d[8]
            mat.t23 = d[9]
            mat.e11_c = d[10]
            mat.e22_c = d[11]
            mat.e33_c = d[12]
            mat.e11_t = d[13]
            mat.e22_t = d[14]
            mat.e33_t = d[15]
            mat.g12 = d[16]
            mat.g13 = d[17]
            mat.g23 = d[18]
            mat.gM0 = d[19]
            mat.C1a = d[20]
            mat.C2a = d[21]
            mat.C3a = d[22]
            mat.C4a = d[23]

    def read_layups(self):
        """
        dp3d data format:

        # web00 web01\n
        <DP index0> <DP index1>\n
        <DP index0> <DP index0>\n
        # s DP00  DP01  DP02  DP03  DP04  DP05\n
        <float> <float> <float> <float> ... <float>\n
        .       .       .       .           .\n
        .       .       .       .           .\n
        .       .       .       .           .\n

        st3d data format:\n

        # region00\n
        # s    triax    uniax    core    uniax01    triax01    core01\n
        <float> <float> <float> <float> <float> <float> <float>\n
        .       .       .       .       .       .       .\n
        .       .       .       .       .       .       .\n
        .       .       .       .       .       .       .\n
        """

        self.dp_files = glob.glob(self.filebase + '*.dp3d')

        self.layup_files = glob.glob(self.filebase + '*.st3d')

        for dpfile in self.dp_files:
            self._logger.info('reading dp_file: %s' % dpfile)
            dpfid = open(dpfile, 'r')

            # read webs
            wnames = dpfid.readline().split()[1:]
            iwebs = []
            for w, wname in enumerate(wnames):
                line = dpfid.readline().split()[1:]
                line = [int(entry) for entry in line]
                iwebs.append(line)
            nwebs = len(iwebs)
            header = dpfid.readline()
            dpdata = np.loadtxt(dpfile)
            nreg = dpdata.shape[1] - 2

            try:
                regions = header.split()[1:]
                assert len(regions) == nreg

            except:
                regions = ['region%02d' % i for i in range(nreg)]

            self.st3d.configure_regions(nreg, names=regions)
            self.st3d.configure_webs(len(wnames), iwebs, names=wnames)
            self.st3d.x = dpdata[:, 0]

            self.st3d.DP00 = dpdata[:, 1]

            for i, rname in enumerate(regions):
                r = getattr(self.st3d, rname)
                self._logger.info('  adding region: %s' % rname)

                dpname = 'DP%02d' % (i + 1)
                setattr(self.st3d, dpname, dpdata[:, i + 2])

                layup_file = '_'.join([self.filebase, rname]) + '.st3d'
                self._logger.info('  reading layup file %s' % layup_file)
                fid = open(layup_file, 'r')
                rrname = fid.readline().split()[1]
                lheader = fid.readline().split()[1:]

                cldata = np.loadtxt(fid)
                layers = lheader[1:]
                nl = len(lheader)

                s = cldata[:, 0]
                r.thickness = np.zeros(self.st3d.x.shape[0])
                for il, lname in enumerate(layers):
                    self._logger.info('    adding layer %s' % lname)
                    l = r.add_layer(lname)
                    l.thickness = cldata[:, il + 1]
                    r.thickness += l.thickness
                    try:
                        l.angle = cldata[:, il + 1 + nl]
                    except:
                        l.angle = np.zeros(s.shape[0])

            for i, rname in enumerate(wnames):
                r = getattr(self.st3d, rname)
                self._logger.info('  adding web: %s' % rname)

                layup_file = '_'.join([self.filebase, rname]) + '.st3d'
                self._logger.info('  reading layup file %s' % layup_file)
                fid = open(layup_file, 'r')
                rrname = fid.readline().split()[1]
                lheader = fid.readline().split()[1:]

                cldata = np.loadtxt(fid)
                layers = lheader[1:]
                nl = len(lheader)

                r.thickness = np.zeros(self.st3d.x.shape[0])
                # assert len(lheader) == cldata.shape[1]

                s = cldata[:, 0]

                for il, lname in enumerate(layers):
                    self._logger.info('    adding layer %s' % lname)
                    l = r.add_layer(lname)
                    l.thickness = cldata[:, il + 1]
                    r.thickness += l.thickness
                    try:
                        l.angle = cldata[:, il + 1 + nl]
                    except:
                        l.angle = np.zeros(s.shape[0])
示例#24
0
class Failures(Component):
    """
    Computes the factor of safety for each of the failure modes of the spar.
    """
    # inputs
    flags = VarTree(Flags(), iotype='in')

    yN = Array(iotype='in', desc='')

    Finternal = Array(iotype='in', desc='')
    strain = VarTree(Strain(), iotype='in')

    d = Array(iotype='in', desc='')
    theta = Array(iotype='in', desc='')
    nTube = Array(iotype='in', desc='')
    nCap = Array(iotype='in', desc='')

    yWire = Array(iotype='in', desc='')
    zWire = Float(iotype='in', desc='')
    EIxJ = Array(iotype='in', desc='')
    EIzJ = Array(iotype='in', desc='')

    lBiscuit = Array(iotype='in', desc='')
    dQuad = Float(iotype='in', desc='')
    thetaQuad = Float(iotype='in', desc='')
    nTubeQuad = Float(iotype='in', desc='')
    lBiscuitQuad = Float(iotype='in', desc='')
    RQuad = Float(iotype='in', desc='')
    hQuad = Float(iotype='in', desc='')
    EIQuad = Array(iotype='in', desc='')
    GJQuad = Array(iotype='in', desc='')
    tWire = Float(iotype='in', desc='')
    TWire = Array(iotype='in', desc='')
    TEtension = Float(iotype='in', desc='')

    # all this to get TQuad... maybe should be split out
    b = Int(iotype='in', desc='number of blades')
    fblade = VarTree(Fblade(), iotype='in')
    mSpar = Array(iotype='in', desc='mass of spars')
    mChord = Array(iotype='in', desc='mass of chords')
    mElseRotor = Float(iotype='in', desc='')

    # outputs
    fail = VarTree(Failure(), iotype='out')

    def execute(self):
        # Compute factor of safety for each failure mode
        # ----------------------------------------------
        # computes material failure, euler buckling failure and torsional
        # buckling failure. All failure modes are computed at the nodes.
        #
        # For material failure it looks at a sample laminate on the top,
        # bottom, back and front of the spar. For each side of the spar
        # it computes the material failure for the cap, the plus angle
        # plys and the minus angle plys. For each ply it computes the
        # fracture of failure in the fibre direction, matrix direction
        # and shear. Thus there are 4x3x3=36 (side x lamina x direction)
        # possible failure modes in the tube.
        # ex. fail.top.cap = 3x(Ns+1) vector
        #     fail.top.plus = 3x(Ns+1) vector
        #     fail.top.minus = 3x(Ns+1) vector
        #
        # Stresses and strain are given as a 3x(Ns+1) vector
        # ex. sigma_11, sigma_22, sigma_12
        # Positive sign denotes tensile stresses, negative denotes compressive

        # factor of safety for each failure mode

        # short aliases
        flags = self.flags
        yN = self.yN
        Finternal = self.Finternal
        strain = self.strain
        d = self.d
        theta = self.theta
        nTube = self.nTube
        nCap = self.nCap
        yWire = self.yWire
        zWire = self.zWire
        EIxJ = self.EIxJ
        EIzJ = self.EIzJ
        lBiscuit = self.lBiscuit
        dQuad = self.dQuad
        thetaQuad = self.thetaQuad
        nTubeQuad = self.nTubeQuad
        lBiscuitQuad = self.lBiscuitQuad
        RQuad = self.RQuad
        hQuad = self.hQuad
        EIQuad = self.EIQuad[0]  # convert single element array to scalar
        GJQuad = self.GJQuad[0]  # convert single element array to scalar
        tWire = self.tWire
        TWire = self.TWire
        TEtension = self.TEtension
        b = self.b
        fblade = self.fblade
        mSpar = self.mSpar
        mChord = self.mChord
        mElseRotor = self.mElseRotor

        TQuad = np.sum(fblade.Fz) * b - (np.sum(mSpar + mChord) * b +
                                         mElseRotor / 4) * 9.81

        Ns = max(yN.shape) - 1  # number of elements

        fail = Failure()

        # Material failure
        fail.top = self.material_failure(Ns, strain.top, theta, nCap, flags)
        fail.bottom = self.material_failure(Ns, strain.bottom, theta, nCap,
                                            flags)
        fail.back = self.material_failure(Ns, strain.back, theta, [], flags)
        fail.front = self.material_failure(Ns, strain.front, theta, [], flags)

        # Euler Buckling failure in main spar from wire force
        k = 0.7  # pinned-pinned = 1, fixed-pinned = 0.7 with correction factor
        #kk = 1.42  # correction factor
        kk = 1  # correction factor was in error, never saw buckling failure
        thetaWire = atan2(zWire, yWire)
        L = yWire  # wire attachment provides pinned end
        F = TWire * cos(thetaWire) + TEtension

        fail.buckling.x = np.zeros(Ns + 1)
        fail.buckling.z = np.zeros(Ns + 1)

        for s in range(Ns):
            if yN[s] <= yWire:
                critical_load_x = pi**2 * EIxJ / (k * L)**2
                critical_load_z = pi**2 * EIzJ / (k * L)**2
                fail.buckling.x[s] = kk * F / critical_load_x
                fail.buckling.z[s] = kk * F / critical_load_z
            else:
                fail.buckling.x[s] = 0
                fail.buckling.z[s] = 0

        # no buckling at tip
        fail.buckling.x[Ns] = 0
        fail.buckling.z[Ns] = 0

        # Torsional Buckling failure
        fail.buckling.torsion = self.torsional_buckling_failure(
            Ns, Finternal, d, theta, nTube, nCap, lBiscuit, flags)

        # Quad Buckling failure
        if EIQuad != 0:
            k = 1
            L = sqrt(RQuad**2 + hQuad**2)
            alpha = atan2(hQuad, RQuad)
            P = TQuad / sin(alpha)
            critical_load = pi**2 * EIQuad / (k * L)**2
            fail.quad_buckling = P / critical_load
        else:
            fail.quad_buckling = 0

        # Quad bending moment failure (does not include torsion since they don't occur at the same time)
        RotorMoment = 1400
        if EIQuad != 0:
            TbottomWire = TQuad / tan(alpha)
            BM = TbottomWire * zWire + RotorMoment
            strainQuad = -np.array([BM * (dQuad / 2) / EIQuad, 0, 0]).reshape(
                1, -1).T  # strain on compression side
            mf = self.material_failure(1, strainQuad, [thetaQuad], [], flags)
            fail.quad_bend = abs(
                mf.plus[0,
                        0])  # use only compressive failure in fibre direction
        else:
            fail.quad_bend = 0

        # Quad torsional material failure
        if GJQuad != 0:
            strainQuad = np.array([0, 0, dQuad / 2 * RotorMoment / GJQuad
                                   ]).reshape(1, -1).T
            mf = self.material_failure(1, strainQuad, [thetaQuad], [], flags)
            fail.quad_torsion = abs(mf.plus[0, 0])
        else:
            fail.quad_torsion = 0

        # Quad torsional buckling failure
        FRotorMoment = np.array([0, 0, 0, 0, RotorMoment]).reshape(1, -1).T
        tbf = self.torsional_buckling_failure(1, FRotorMoment, [dQuad],
                                              [thetaQuad], [nTubeQuad], [0],
                                              [lBiscuitQuad], flags)
        fail.quad_torbuck = tbf[0]

        # Wire tensile failure
        wire_props = wireProperties[flags.WireType]
        fail.wire = np.zeros(len(yWire))
        for i in range(len(yWire)):
            stress_wire = TWire[i] / (pi * (tWire / 2)**2)
            fail.wire[i] = stress_wire / wire_props['ULTIMATE']

        self.fail = fail

    def material_failure(self, Ns, strain, theta, nCap, flags):
        failure = MaterialFailure()
        failure.cap = np.zeros((3, Ns + 1))
        failure.plus = np.zeros((3, Ns + 1))
        failure.minus = np.zeros((3, Ns + 1))

        # Material Properties
        tube_props = prepregProperties[flags.CFRPType]

        # Cap Prepreg Properties (MTM28-M46J 140 37 %RW 12")
        cap_props = prepregProperties[flags.CFRPType]

        # Populate Q matrix for tube
        Q_TUBE = np.zeros((3, 3))
        Q_TUBE[0, 0] = tube_props['E_11']
        Q_TUBE[1, 1] = tube_props['E_22']
        Q_TUBE[0, 1] = tube_props['E_22'] * tube_props['V_12']
        Q_TUBE[1, 0] = Q_TUBE[0, 1]
        Q_TUBE[2, 2] = tube_props['G_12']

        # Populate Q matrix for caps
        Q_CAP = np.zeros((3, 3))
        Q_CAP[0, 0] = cap_props['E_11']
        Q_CAP[1, 1] = cap_props['E_22']
        Q_CAP[0, 1] = cap_props['E_22'] * cap_props['V_12']
        Q_CAP[1, 0] = Q_CAP[0, 1]
        Q_CAP[2, 2] = cap_props['G_12']

        stress = MaterialFailure()
        stress.cap = np.zeros((3, Ns))
        stress.plus = np.zeros((3, Ns))
        stress.minus = np.zeros((3, Ns))

        for s in range(Ns):
            # Compute stresses in structural axes for each lamina angle
            # Q is the matrix of elastic constants in the material axis
            # Q_bar is the matrix of elastic constants in the structural axes for a
            # lamina at a ply angle theta.

            # Failure is computed at each node, but using the ply angle of the
            # element (this shouldn't cause a large discrepency). Failure at tip is
            # zero, since stresses/strains at tip are zero.

            # Transform the elastic constants for the plus angle ply
            x = theta[s]  # Composite angle (in radians)
            T_PLUS = np.array([[cos(x)**2,
                                sin(x)**2, 2 * sin(x) * cos(x)],
                               [sin(x)**2,
                                cos(x)**2, -2 * sin(x) * cos(x)],
                               [
                                   -sin(x) * cos(x),
                                   sin(x) * cos(x), (cos(x)**2) - (sin(x)**2)
                               ]])
            # MATLAB version: Qbar_TUBE_PLUS = (T_PLUS\Q_TUBE)/T_PLUS'
            tmp = np.linalg.solve(T_PLUS, Q_TUBE)
            Qbar_TUBE_PLUS = np.linalg.solve(T_PLUS, tmp.T)

            # Transform the elastic constants for the minus angle ply
            x = -theta[s]  # Composite angle (in radians)
            T_MINUS = np.array([[cos(x)**2,
                                 sin(x)**2, 2 * sin(x) * cos(x)],
                                [sin(x)**2,
                                 cos(x)**2, -2 * sin(x) * cos(x)],
                                [
                                    -sin(x) * cos(x),
                                    sin(x) * cos(x), (cos(x)**2) - (sin(x)**2)
                                ]])
            # MATLAB version: Qbar_TUBE_MINUS = (T_MINUS\Q_TUBE)/T_MINUS'
            tmp = np.linalg.solve(T_MINUS, Q_TUBE)
            Qbar_TUBE_MINUS = np.linalg.solve(T_MINUS, tmp.T)

            # Compute stresses in structural coordinates
            stress.cap[:, s] = np.dot(Q_CAP, strain[:,
                                                    s])  # using Q for the cap
            stress.plus[:, s] = np.dot(
                Qbar_TUBE_PLUS, strain[:,
                                       s])  # using Q_bar for the + angle plys
            stress.minus[:, s] = np.dot(
                Qbar_TUBE_MINUS, strain[:,
                                        s])  # using Q_bar for the - angle plys

            # Transform stresses to material axes for each lamina angle
            stress.plus[:, s] = np.dot(T_PLUS, stress.plus[:, s])
            stress.minus[:, s] = np.dot(T_MINUS, stress.minus[:, s])

            # Determine fraction of failure for each lamina angle

            # ULTIMATE_11_TENS and ULTIMATE_11_COMP are both positive values
            # indicating the maximum tensile and compressive stress before failure.
            # failure.cap[0,s] will be positive for tensile failures and negative for
            # compressive failures.

            # Cap failure
            if len(nCap) == 0 or (nCap == 0).all():
                failure.cap[0, s] = 0
                failure.cap[1, s] = 0
                failure.cap[2, s] = 0
            else:
                if stress.cap[0, s] > 0:  # tensile stress in fibre
                    failure.cap[
                        0,
                        s] = stress.cap[0, s] / cap_props['ULTIMATE_11_TENS']
                else:
                    failure.cap[
                        0,
                        s] = stress.cap[0, s] / cap_props['ULTIMATE_11_COMP']

                if stress.cap[1, s] > 0:  # tensile stress in matrix
                    failure.cap[
                        1,
                        s] = stress.cap[1, s] / cap_props['ULTIMATE_22_TENS']
                else:
                    failure.cap[
                        1,
                        s] = stress.cap[1, s] / cap_props['ULTIMATE_22_COMP']

                failure.cap[2, s] = stress.cap[2, s] / cap_props['ULTIMATE_12']

            # Plus angle ply failure
            if stress.plus[0, s] > 0:  # tensile stress in fibre
                failure.plus[
                    0, s] = stress.plus[0, s] / tube_props['ULTIMATE_11_TENS']
            else:
                failure.plus[
                    0, s] = stress.plus[0, s] / tube_props['ULTIMATE_11_COMP']

            if stress.plus[1, s] > 0:  # tensile stress in matrix
                failure.plus[
                    1, s] = stress.plus[1, s] / tube_props['ULTIMATE_22_TENS']
            else:
                failure.plus[
                    1, s] = stress.plus[1, s] / tube_props['ULTIMATE_22_COMP']

            failure.plus[2, s] = stress.plus[2, s] / tube_props['ULTIMATE_12']

            # Minus angle ply failure
            if stress.minus[0, s] > 0:  # tensile stress in fibre
                failure.minus[
                    0, s] = stress.minus[0, s] / tube_props['ULTIMATE_11_TENS']
            else:
                failure.minus[
                    0, s] = stress.minus[0, s] / tube_props['ULTIMATE_11_COMP']

            if stress.minus[1, s] > 0:  # tensile stress in matrix
                failure.minus[
                    1, s] = stress.minus[1, s] / tube_props['ULTIMATE_22_TENS']
            else:
                failure.minus[
                    1, s] = stress.minus[1, s] / tube_props['ULTIMATE_22_COMP']

            failure.minus[2,
                          s] = stress.minus[2, s] / tube_props['ULTIMATE_12']

        return failure

    def torsional_buckling_failure(self, Ns, Finternal, d, theta, nTube, nCap,
                                   lBiscuit, flags):
        # Material Properties
        tube_props = prepregProperties[flags.CFRPType]
        V_21_TUBE = tube_props['V_12'] * (tube_props['E_22'] /
                                          tube_props['E_11'])

        # Coordinate system: x is axial direction, theta is circumferential direction
        mu_prime_x = tube_props['V_12']
        mu_prime_theta = V_21_TUBE

        Q = np.zeros((3, 3))  # Preallocate Q-matrix

        # Matrix of elastic constants (AER1401, Composite Lamina, slide 8)
        Q[0, 0] = tube_props['E_11'] / (1 - tube_props['V_12'] * V_21_TUBE)
        Q[1, 1] = tube_props['E_22'] / (1 - tube_props['V_12'] * V_21_TUBE)
        Q[0, 1] = tube_props['E_22'] * tube_props['V_12'] / (
            1 - tube_props['V_12'] * V_21_TUBE)
        Q[1, 0] = Q[0, 1]
        Q[2, 2] = tube_props['G_12']

        failure = np.zeros(Ns + 1)

        for s in range(Ns):

            if nCap[s] != 0:
                AF_torsional_buckling = 1.25  # See "Validation - Torsional Buckling.xlsx"
            else:
                AF_torsional_buckling = 1

            # Determine elastic properties of rotated tube laminate
            x = theta[s]  # Composite angle (in radians)

            # Transformation matrix
            T = np.array(
                [[cos(x)**2, sin(x)**2, 2 * sin(x) * cos(x)],
                 [sin(x)**2, cos(x)**2, -2 * sin(x) * cos(x)],
                 [-sin(x) * cos(x),
                  sin(x) * cos(x),
                  cos(x)**2 - sin(x)**2]])

            # Transform the elastic constants using the transformation matrix to obtain the
            # elastic constants at the composite angle.
            # MATLAB version: Qbar = (T\Q)/T'
            tmp = np.linalg.solve(T, Q)
            Qbar = np.linalg.solve(T, tmp.T)

            # Breakout tube elastic constants at the transformed angle
            E_x = Qbar[0, 0]
            E_theta = Qbar[1, 1]

            # Calculate tube geometric properties
            t_tube = nTube[s] * tube_props[
                'T_PLY']  # Shell thickness, CR-912 p.xxxvi
            R = (
                d[s] + t_tube
            ) / 2  # Radius from axis of rotation to centroidal surface of cylinder wall, CR-912 p.xxxiv
            L = lBiscuit[s]  # Unsupported length of cylinder, CR-912 p.xxx

            # Calculate tube elastic properties (CR-912 p.576)
            D_x = E_x * (1. / 12) * (t_tube**3)
            D_theta = E_theta * (1. / 12) * (t_tube**3)
            B_x = E_x * t_tube
            B_theta = E_theta * t_tube

            # Calculate Gamma
            rho = ((D_x * D_theta) / (B_x * B_theta))**(1. / 4)
            Gamma = 3.6125e-07  * ((R / (rho * 1000)) ** 6)  + \
                    -1.9724e-05 * ((R / (rho * 1000)) ** 5)  + \
                     0.0004283  * ((R / (rho * 1000)) ** 4)  + \
                    -0.0048315  * ((R / (rho * 1000)) ** 3)  + \
                     0.031801   * ((R / (rho * 1000)) ** 2)  + \
                    -0.12975    *  (R / (rho * 1000))        + \
                     0.88309

            # Calculate factors required in critical torque equation
            Z = ((B_theta * (1 - mu_prime_x * mu_prime_theta) * (L**4)) /
                 (12 * D_x * (R**2)))**(1. / 2)
            Z_s = ((D_theta / D_x)**(5. / 6)) * ((B_x / B_theta)**(1. / 2)) * Z
            K_s = 0.89 * (Z_s**(3. / 4))
            N_x_theta = (Gamma * K_s * (pi**2) * D_x) / (L**2)

            # Calculate critical torque
            critical_torque = AF_torsional_buckling * N_x_theta * 2 * pi * (R**
                                                                            2)

            failure[s] = abs(Finternal[4, s] / critical_torque)

        failure[Ns] = 0  # no torsion at tip

        return failure
示例#25
0
class BladeStructureCSBuilder(BladeStructureBuilderBase):
    """
    Class that generates a series of 2D cross-sectional property
    vartrees (CrossSectionStructureVT) used by structural codes like BECAS
    """

    blade_length = Float(1., iotype='in')
    surface = VarTree(BladeSurfaceVT(),
                      iotype='in',
                      desc='Stacked blade surface object')
    st3d = VarTree(BladeStructureVT3D(),
                   iotype='in',
                   desc='Blade structure definition')

    cs2d = List(iotype='out',
                desc='List of cross-sectional properties'
                'vartrees')

    def execute(self):
        """
        generate cross sections at every spanwise node of the st3d vartree
        """

        # clear list of outputs!
        self.cs2d = []

        ni = self.st3d.x.shape[0]
        for i in range(ni):
            x = self.st3d.x[i]
            # print 'adding section at r/R = %2.2f' % x
            st2d = CrossSectionStructureVT()
            st2d.s = x * self.blade_length
            st2d.DPs = []
            try:
                airfoil = self.surface.interpolate_profile(
                    x)[:, [0, 1]] * self.blade_length
                st2d.airfoil.initialize(airfoil)
            except:
                pass
            for ir, rname in enumerate(self.st3d.regions):
                reg = getattr(self.st3d, rname)
                if reg.thickness[i] == 0.:
                    print 'zero thickness region!', rname
                    # continue
                DP0 = getattr(self.st3d, 'DP%02d' % ir)
                DP1 = getattr(self.st3d, 'DP%02d' % (ir + 1))
                r = st2d.add_region(rname.upper())
                st2d.DPs.append(DP0[i])
                r.s0 = DP0[i]
                r.s1 = DP1[i]
                for lname in reg.layers:
                    lay = getattr(reg, lname)
                    if lay.thickness[i] > 1.e-5:
                        l = r.add_layer(lname)
                        # try:
                        lnamebase = lname.translate(None, digits)
                        st2d.add_material(lnamebase,
                                          self.get_material(lname).copy())
                        # except:
                        # raise RuntimeError('Material %s not in materials list' % lname)
                        l.materialname = lnamebase
                        l.thickness = max(0., lay.thickness[i])
                        try:
                            l.angle = lay.angle[i]
                        except:
                            l.angle = 0.

            st2d.DPs.append(DP1[i])
            for ir, rname in enumerate(self.st3d.webs):
                reg = getattr(self.st3d, rname)
                if reg.thickness[i] == 0.:
                    continue
                r = st2d.add_web(rname.upper())
                try:
                    DP0 = getattr(self.st3d, 'DP%02d' % self.st3d.iwebs[ir][0])
                except:
                    DP0 = getattr(
                        self.st3d, 'DP%02d' %
                        (len(self.st3d.regions) + self.st3d.iwebs[ir][0] + 1))
                try:
                    DP1 = getattr(self.st3d, 'DP%02d' % self.st3d.iwebs[ir][1])
                except:
                    DP1 = getattr(
                        self.st3d, 'DP%02d' %
                        (len(self.st3d.regions) + self.st3d.iwebs[ir][1] + 1))
                r.s0 = DP0[i]
                r.s1 = DP1[i]
                for lname in reg.layers:
                    lay = getattr(reg, lname)
                    if lay.thickness[i] > 1.e-5:
                        l = r.add_layer(lname)
                        try:
                            lnamebase = lname.translate(None, digits)
                            st2d.add_material(lnamebase,
                                              self.get_material(lname).copy())
                        except:
                            raise RuntimeError(
                                'Material %s not in materials list' % lname)
                        l.materialname = lnamebase
                        l.thickness = max(0., lay.thickness[i])
                        try:
                            l.angle = lay.angle[i]
                        except:
                            l.angle = 0.

            self.cs2d.append(st2d)
示例#26
0
class SplinedBladePlanform(Assembly):

    x_dist = Array(iotype='in', desc='spanwise resolution of blade')
    nC = Int(8, iotype='in', desc='Number of spline control points along span')
    Cx = Array(iotype='in',
               desc='spanwise distribution of spline control points')

    blade_length = Float(iotype='in')
    blade_length_ref = Float(iotype='in')

    span_ni = Int(50, iotype='in')

    pfIn = VarTree(BladePlanformVT(), iotype='in')
    pfOut = VarTree(BladePlanformVT(), iotype='out')

    def __init__(self):
        super(SplinedBladePlanform, self).__init__()

        self.blade_length_ref = 0.

    def _pre_execute(self):
        super(SplinedBladePlanform, self)._pre_execute()

        # set reference length first time this comp is executed
        if self.blade_length_ref == 0.:
            self.blade_length_ref = self.blade_length

    def configure_splines(self):

        if hasattr(self, 'chord_C'):
            return
        if self.Cx.shape[0] == 0:
            self.Cx = np.linspace(0, 1, self.nC)
        else:
            self.nC = self.Cx.shape[0]

        self.connect('blade_length', 'pfOut.blade_length')

        self.add('compute_x', ComputeDist())
        self.driver.workflow.add('compute_x')
        self.connect('span_ni', 'compute_x.span_ni')

        for vname in self.pfIn.list_vars():
            if vname in ['athick', 'blade_length']:
                continue

            cIn = self.get('pfIn.' + vname)
            cOut = self.get('pfOut.' + vname)
            sname = vname.replace('.', '_')

            if vname == 's':
                self.connect('compute_x.x', 'pfOut.s')
            else:
                spl = self.add(sname, FFDSplineComponentBase(self.nC))
                self.driver.workflow.add(sname)
                # spl.log_level = logging.DEBUG
                self.connect('compute_x.x', sname + '.x')
                self.connect('Cx', sname + '.Cx')
                spl.xinit = self.get('pfIn.s')
                spl.Pinit = cIn
                if vname == 'chord':
                    self.add('scaleC', ScaleChord())
                    self.driver.workflow.add('scaleC')
                    self.connect('chord.P', 'scaleC.cIn')
                    self.connect('blade_length/blade_length_ref',
                                 'scaleC.scaler')
                    self.connect('scaleC.cOut', 'pfOut.chord')
                    # self.connect(sname + '.P'+
                    #     '*blade_length/blade_length_ref', 'pfOut.' + vname)
                else:
                    self.connect(sname + '.P', 'pfOut.' + vname)
                self.create_passthrough(sname + '.C', alias=sname + '_C')
                self.create_passthrough(sname + '.dPds', alias=sname + '_dPds')

        self.add('athick', ComputeAthick())
        self.driver.workflow.add('athick')
        self.connect('chord.P', 'athick.chord')
        self.connect('rthick.P', 'athick.rthick')
        self.connect('athick.athick', 'pfOut.athick')
示例#27
0
    def __init__(self, Ns):
        super(Structures, self).__init__()

        # flags
        self.add('flags', VarTree(Flags(), iotype='in'))

        # inputs for spars
        self.add(
            'yN',
            Array(np.zeros(Ns + 1),
                  iotype='in',
                  desc='node locations for each element along the span'))
        self.add('d', Array(np.zeros(Ns), iotype='in', desc='spar diameter'))
        self.add('theta', Array(np.zeros(Ns), iotype='in', desc='wrap angle'))
        self.add(
            'nTube',
            Array(np.zeros(Ns), iotype='in', desc='number of tube layers'))
        self.add('nCap',
                 Array(np.zeros(Ns), iotype='in', desc='number of cap strips'))
        self.add(
            'lBiscuit',
            Array(np.zeros(Ns), iotype='in',
                  desc='unsupported biscuit length'))

        # joint properties
        self.add('Jprop', VarTree(JointProperties(), iotype='in'))

        # inputs for chord
        self.add('b', Int(0, iotype='in', desc='number of blades'))

        self.add(
            'cE', Array(np.zeros(Ns),
                        iotype='in',
                        desc='chord of each element'))
        self.add('xEA', Array(np.zeros(Ns), iotype='in', desc=''))
        self.add('xtU', Array(np.zeros(Ns), iotype='in', desc=''))

        # inputs for quad
        self.add('dQuad',
                 Float(0., iotype='in', desc='diameter of quad rotor struts'))
        self.add(
            'thetaQuad',
            Float(0., iotype='in', desc='wrap angle of quad rotor struts'))
        self.add(
            'nTubeQuad',
            Int(0,
                iotype='in',
                desc='number of CFRP layers in quad rotor struts'))
        self.add('lBiscuitQuad', Float(0., iotype='in', desc=''))
        self.add(
            'RQuad',
            Float(
                0.,
                iotype='in',
                desc=
                'distance from centre of helicopter to centre of quad rotors'))
        self.add('hQuad',
                 Float(0., iotype='in', desc='height of quad-rotor truss'))

        # inputs for cover
        self.add('ycmax', Float(0., iotype='in', desc=''))

        # inputs for wire
        self.add(
            'yWire',
            Array([0],
                  iotype='in',
                  desc='location of wire attachment along span'))
        self.add('zWire',
                 Float(0., iotype='in', desc='depth of wire attachement'))
        self.add('tWire', Float(0., iotype='in', desc='thickness of wire'))
        self.add('TWire', Array([0], iotype='in', desc=''))
        self.add('TEtension', Float(0., iotype='in', desc=''))

        # inputs for 'other stuff'
        self.add('mElseRotor', Float(0., iotype='in', desc=''))
        self.add('mElseCentre', Float(0., iotype='in', desc=''))
        self.add('mElseR', Float(0., iotype='in', desc=''))
        self.add('R', Float(0., iotype='in', desc='rotor radius'))
        self.add('mPilot', Float(0., iotype='in', desc='mass of pilot'))

        # inputs for FEM
        self.add('fblade', VarTree(Fblade(Ns), iotype='in'))
        self.add('presLoad', VarTree(PrescribedLoad(), iotype='in'))

        # configure
        self.add('spar', SparProperties(Ns))
        self.connect('yN', 'spar.yN')
        self.connect('d', 'spar.d')
        self.connect('theta', 'spar.theta')
        self.connect('nTube', 'spar.nTube')
        self.connect('nCap', 'spar.nCap')
        self.connect('lBiscuit', 'spar.lBiscuit')
        self.connect('flags.CFRPType', 'spar.CFRPType')

        self.add('joint', JointSparProperties(Ns))
        self.connect('flags.CFRPType', 'joint.CFRPType')
        self.connect('Jprop', 'joint.Jprop')

        self.add('chord', ChordProperties(Ns))
        self.connect('yN', 'chord.yN')
        self.connect('cE', 'chord.c')
        self.connect('d', 'chord.d')
        self.connect('flags.GWing', 'chord.GWing')
        self.connect('xtU', 'chord.xtU')

        self.add('quad', QuadSparProperties(Ns))
        self.connect('dQuad', 'quad.dQuad')
        self.connect('thetaQuad', 'quad.thetaQuad')
        self.connect('nTubeQuad', 'quad.nTubeQuad')
        self.connect('lBiscuitQuad', 'quad.lBiscuitQuad')
        self.connect('flags.CFRPType', 'quad.CFRPType')
        self.connect('RQuad', 'quad.RQuad')
        self.connect('hQuad', 'quad.hQuad')

        self.add('mass', MassProperties(Ns))
        self.connect('flags', 'mass.flags')
        self.connect('b', 'mass.b')
        self.connect('spar.mSpar', 'mass.mSpar')
        self.connect('chord.mChord', 'mass.mChord')
        self.connect('chord.xCGChord', 'mass.xCGChord')
        self.connect('quad.mQuad', 'mass.mQuad')
        self.connect('xEA', 'mass.xEA')
        self.connect('ycmax', 'mass.ycmax')
        self.connect('zWire', 'mass.zWire')
        self.connect('yWire', 'mass.yWire')
        self.connect('tWire', 'mass.tWire')
        self.connect('mElseRotor', 'mass.mElseRotor')
        self.connect('mElseCentre', 'mass.mElseCentre')
        self.connect('mElseR', 'mass.mElseR')
        self.connect('R', 'mass.R')
        self.connect('mPilot', 'mass.mPilot')

        self.add('fem', FEM(Ns))
        self.connect('flags', 'fem.flags')
        self.connect('yN', 'fem.yN')
        self.connect('spar.EIx', 'fem.EIx')
        self.connect('spar.EIz', 'fem.EIz')
        self.connect('spar.EA', 'fem.EA')
        self.connect('spar.GJ', 'fem.GJ')
        self.connect('cE', 'fem.cE')
        self.connect('xEA', 'fem.xEA')
        self.connect('spar.mSpar', 'fem.mSpar')
        self.connect('chord.mChord', 'fem.mChord')
        self.connect('mass.xCG', 'fem.xCG')
        self.connect('zWire', 'fem.zWire')
        self.connect('yWire', 'fem.yWire')
        self.connect('TWire', 'fem.TWire')
        self.connect('fblade', 'fem.fblade')
        self.connect('presLoad', 'fem.presLoad')

        self.add('strains', Strains(Ns))
        self.connect('yN', 'strains.yN')
        self.connect('d', 'strains.d')
        self.connect('fem.k', 'strains.k')
        self.connect('fem.F', 'strains.F')
        self.connect('fem.q', 'strains.q')

        self.add('failure', Failures(Ns))
        self.connect('flags', 'failure.flags')
        self.connect('yN', 'failure.yN')
        self.connect('strains.Finternal', 'failure.Finternal')
        self.connect('strains.strain', 'failure.strain')
        self.connect('d', 'failure.d')
        self.connect('theta', 'failure.theta')
        self.connect('nTube', 'failure.nTube')
        self.connect('nCap', 'failure.nCap')
        self.connect('yWire', 'failure.yWire')
        self.connect('zWire', 'failure.zWire')
        self.connect('joint.EIx', 'failure.EIxJ')
        self.connect('joint.EIz', 'failure.EIzJ')
        self.connect('lBiscuit', 'failure.lBiscuit')
        self.connect('dQuad', 'failure.dQuad')
        self.connect('thetaQuad', 'failure.thetaQuad')
        self.connect('nTubeQuad', 'failure.nTubeQuad')
        self.connect('lBiscuitQuad', 'failure.lBiscuitQuad')
        self.connect('RQuad', 'failure.RQuad')
        self.connect('hQuad', 'failure.hQuad')
        self.connect('quad.EIx', 'failure.EIQuad')
        self.connect('quad.GJ', 'failure.GJQuad')
        self.connect('tWire', 'failure.tWire')
        self.connect('TWire', 'failure.TWire')
        self.connect('TEtension', 'failure.TEtension')
        self.connect('b', 'failure.b')
        self.connect('fblade', 'failure.fblade')
        self.connect('spar.mSpar', 'failure.mSpar')
        self.connect('chord.mChord', 'failure.mChord')
        self.connect('mElseRotor', 'failure.mElseRotor')

        # link up the outputs
        self.create_passthrough('mass.Mtot')
        self.create_passthrough('fem.q')
        self.create_passthrough('strains.Finternal')
        self.create_passthrough('strains.strain')
        self.create_passthrough('failure.fail')

        self.driver.workflow.add('chord')
        self.driver.workflow.add('fem')
        self.driver.workflow.add('joint')
        self.driver.workflow.add('mass')
        self.driver.workflow.add('quad')
        self.driver.workflow.add('spar')
        self.driver.workflow.add('strains')
        self.driver.workflow.add('failure')
示例#28
0
class LoftedBladeSurface(Component):

    pf = VarTree(BladePlanformVT(), iotype='in')
    base_airfoils = List(iotype='in')
    blend_var = Array(iotype='in')
    chord_ni = Int(300, iotype='in')
    span_ni = Int(300, iotype='in')

    interp_type = Enum('rthick', ('rthick', 's'), iotype='in')
    surface_spline = Str('akima', iotype='in', desc='Spline')

    rot_order = Array(np.array([2, 1, 0]),
                      iotype='in',
                      desc='rotation order of airfoil sections'
                      'default z,y,x (twist,sweep,dihedral)')

    surfout = VarTree(BladeSurfaceVT(), iotype='out')
    surfnorot = VarTree(BladeSurfaceVT(), iotype='out')

    def execute(self):

        self.interpolator = BlendAirfoilShapes()
        self.interpolator.ni = self.chord_ni
        self.interpolator.spline = self.surface_spline
        self.interpolator.blend_var = self.blend_var
        self.interpolator.airfoil_list = self.base_airfoils
        self.interpolator.initialize()

        self.span_ni = self.pf.s.shape[0]
        x = np.zeros((self.chord_ni, self.span_ni, 3))

        for i in range(self.span_ni):

            s = self.pf.s[i]
            pos_x = self.pf.x[i]
            pos_y = self.pf.y[i]
            pos_z = self.pf.z[i]
            chord = self.pf.chord[i]
            p_le = self.pf.p_le[i]

            # generate the blended airfoil shape
            if self.interp_type == 'rthick':
                rthick = self.pf.rthick[i]
                points = self.interpolator(rthick)
            else:
                points = self.interpolator(s)

            points *= chord
            points[:, 0] += pos_x - chord * p_le

            # x-coordinate needs to be inverted for clockwise rotating blades
            x[:, i, :] = (np.array(
                [-points[:, 0], points[:, 1], x.shape[0] * [pos_z]]).T)

        # save non-rotated blade (only really applicable for straight blades)
        x_norm = x.copy()
        x[:, :, 1] += self.pf.y
        x = self.rotate(x)

        self.surfnorot.surface = x_norm
        self.surfout.surface = x

    def rotate(self, x):
        """
        rotate blade sections accounting for twist and main axis orientation
        
        the blade will be built with a "sheared" layout, ie no rotation around y
        in the case of sweep.
        if the main axis includes a winglet, the blade sections will be
        rotated accordingly. ensure that an adequate point distribution is
        used in this case to avoid sections colliding in the winglet junction!
        """

        main_axis = Curve(points=np.array([self.pf.x, self.pf.y, self.pf.z]).T)

        rot_normals = np.zeros((3, 3))
        x_rot = np.zeros(x.shape)

        for i in range(x.shape[1]):
            points = x[:, i, :]
            rot_center = main_axis.points[i]
            # rotation angles read from file
            angles = np.array([
                self.pf.rot_x[i], self.pf.rot_y[i], self.pf.rot_z[i]
            ]) * np.pi / 180.

            # compute rotation angles of main_axis
            t = main_axis.dp[i]
            rot = np.zeros(3)
            rot[0] = -np.arctan(t[1] / (t[2] + 1.e-20))
            v = np.array([t[2], t[1]])
            vt = np.dot(v, v)**0.5
            rot[1] = (np.arcsin(t[0] / vt))
            angles[0] += rot[0]
            angles[1] += rot[1]

            # compute x-y-z normal vectors of rotation
            n_y = np.cross(t, [1, 0, 0])
            n_y = n_y / norm(n_y)
            rot_normals[0, :] = np.array([1, 0, 0])
            rot_normals[1, :] = n_y
            rot_normals[2, :] = t

            # compute final rotation matrix
            rotation_matrix = np.matrix([[1., 0., 0.], [0., 1., 0.],
                                         [0., 0., 1.]])
            for n, ii in enumerate(self.rot_order):
                mat = np.matrix(RotMat(rot_normals[ii], angles[ii]))
                rotation_matrix = mat * rotation_matrix

            # apply rotation
            x_rot[:, i, :] = dotXC(rotation_matrix, points, rot_center)

        return x_rot
示例#29
0
    def __init__(self, Ns):
        super(FEM, self).__init__()

        # inputs
        self.add('flags', VarTree(Flags(), iotype='in'))

        self.add('yN', Array(np.zeros(Ns + 1), iotype='in', desc=''))

        self.add('EIx', Array(np.zeros(Ns), iotype='in', desc=''))
        self.add('EIz', Array(np.zeros(Ns), iotype='in', desc=''))
        self.add('EA', Array(np.zeros(Ns), iotype='in', desc=''))
        self.add('GJ', Array(np.zeros(Ns), iotype='in', desc=''))

        self.add(
            'cE', Array(np.zeros(Ns),
                        iotype='in',
                        desc='chord of each element'))
        self.add('xEA', Array(np.zeros(Ns), iotype='in', desc=''))

        self.add('fblade', VarTree(Fblade(Ns), iotype='in'))

        self.add('mSpar', Array(np.zeros(Ns),
                                iotype='in',
                                desc='mass of spars'))
        self.add('mChord',
                 Array(np.zeros(Ns), iotype='in', desc='mass of chords'))
        self.add('xCG', Array(np.zeros(Ns), iotype='in', desc=''))

        self.add(
            'yWire',
            Array([0],
                  iotype='in',
                  desc='location of wire attachment along span'))
        self.add('zWire',
                 Float(0., iotype='in', desc='depth of wire attachment'))
        self.add('TWire', Array([0], iotype='in', desc=''))

        self.add('presLoad', VarTree(PrescribedLoad(), iotype='in'))

        # outputs
        self.add(
            'k',
            Array(np.zeros((Ns + 2, Ns + 2, Ns)),
                  iotype='out',
                  desc='local elastic stiffness matrix'))
        self.add(
            'K',
            Array(np.zeros((Ns + 2, Ns + 2, Ns)),
                  iotype='out',
                  desc='global stiffness matrix'))

        self.add(
            'F',
            Array(np.zeros((6 * (Ns + 1), 1)),
                  iotype='out',
                  desc='global force vector'))
        self.add(
            'q',
            Array(np.zeros((6 * (Ns + 1), 1)),
                  iotype='out',
                  desc='deformation'))
class dist_const(Component):

    parameters = VarTree(FLORISParameters(), iotype='in')

    def __init__(self, nTurbines):

        #print 'entering dist_const __init__'

        super(dist_const, self).__init__()

        # Explicitly size input arrays
        self.add('turbineX', Array(np.zeros(nTurbines), iotype='in', \
                                    desc='x coordinates of turbines in wind dir. ref. frame'))
        self.add('turbineY', Array(np.zeros(nTurbines), iotype='in', \
                                    desc='y coordinates of turbines in wind dir. ref. frame'))

        # Explicitly size output array
        self.add('separation', Array(np.zeros(int((nTurbines-1.)*nTurbines/2.)), iotype='out', dtype='float', \
                                        desc='spacing of all turbines in the wind farm'))

    def execute(self):

        #print 'in dist const'

        turbineX = self.turbineX
        turbineY = self.turbineY
        nTurbines = turbineX.size
        separation = np.zeros(int((nTurbines - 1.) * nTurbines / 2.))

        k = 0
        for i in range(0, nTurbines):
            for j in range(i + 1, nTurbines):
                separation[k] = np.sqrt((turbineX[j] - turbineX[i])**2 +
                                        (turbineY[j] - turbineY[i])**2)
                k += 1
        self.separation = separation

    def list_deriv_vars(self):
        return ('turbineX', 'turbineY'), ('separation', )

    def provideJ(self):

        #print 'entering dist const - provideJ'
        tictot = time.time()
        turbineX = self.turbineX
        turbineY = self.turbineY
        nTurbines = turbineX.size
        J = np.zeros(((nTurbines - 1.) * nTurbines / 2., 2 * nTurbines))

        k = 0
        for i in range(0, nTurbines):
            for j in range(i + 1, nTurbines):
                J[k, j] = (turbineX[j] - turbineX[i]) * (
                    (turbineX[j] - turbineX[i])**2 +
                    (turbineY[j] - turbineY[i])**2)**(-0.5)
                J[k, i] = (turbineX[i] - turbineX[j]) * (
                    (turbineX[j] - turbineX[i])**2 +
                    (turbineY[j] - turbineY[i])**2)**(-0.5)
                J[k, j + nTurbines] = (turbineY[j] - turbineY[i]) * (
                    (turbineX[j] - turbineX[i])**2 +
                    (turbineY[j] - turbineY[i])**2)**(-0.5)
                J[k, i + nTurbines] = (turbineY[i] - turbineY[j]) * (
                    (turbineX[j] - turbineX[i])**2 +
                    (turbineY[j] - turbineY[i])**2)**(-0.5)
                k += 1
        toctot = time.time()
        #print 'done %s' % (toctot-tictot)
        return J
示例#31
0
class FstInputReader(FstInputBase):

    fst_infile = Str(desc='Master FAST file')
    fst_directory = Str(desc='Directory of master FAST file set')
    fst_file_type = Enum(0, (0, 1),
                         desc='Fst file type, 0=old FAST, 1 = new FAST')
    ad_file_type = Enum(
        0, (0, 1), desc='Aerodyn file type, 0=old Aerodyn, 1 = new Aerdyn')

    fst_vt = VarTree(FstModel(), iotype='out')

    def __init__(self):
        super(FstInputReader, self).__init__()

    def execute(self):

        self.read_input_file()

    def read_input_file(self):

        fst_file = os.path.join(self.fst_directory, self.fst_infile)
        f = open(fst_file)

        # FAST Inputs
        f.readline()
        f.readline()
        self.fst_vt.description = f.readline().rstrip()
        f.readline()
        f.readline()
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.Echo = False
        else:
            self.fst_vt.Echo = True
        ap = f.readline().split()[0]
        if ap == '1':
            self.fst_vt.ADAMSPrep = 1
        elif ap == '2':
            self.fst_vt.ADAMSPrep = 2
        else:
            self.fst_vt.ADAMSPrep = 3
        am = f.readline().split()[0]
        if am == '1':
            self.fst_vt.AnalMode = 1
        else:
            self.fst_vt.AnalMode = 2
        self.fst_vt.NumBl = int(f.readline().split()[0])
        self.fst_vt.TMax = float(f.readline().split()[0])
        self.fst_vt.DT = float(f.readline().split()[0])
        f.readline()
        ym = f.readline().split()[0]
        if ym == '0':
            self.fst_vt.YCMode = 0
        elif ym == '1':
            self.fst_vt.YCMode = 1
        else:
            self.fst_vt.YCMode = 2
        self.fst_vt.TYCOn = float(f.readline().split()[0])
        pm = f.readline().split()[0]
        if pm == '0':
            self.fst_vt.PCMode = 0
        elif pm == '1':
            self.fst_vt.PCMode = 1
        else:
            self.fst_vt.PCMode = 2
        self.fst_vt.TPCOn = float(f.readline().split()[0])
        vs = f.readline().split()[0]
        if vs == '0':
            self.fst_vt.VSContrl = 0
        elif vs == '1':
            self.fst_vt.VSContrl = 1
        elif vs == '2':
            self.fst_vt.VSContrl = 2
        else:
            self.fst_vt.VSContrl = 3
        self.fst_vt.VS_RtGnSp = float(f.readline().split()[0])
        self.fst_vt.VS_RtTq = float(f.readline().split()[0])
        self.fst_vt.VS_Rgn2K = float(f.readline().split()[0])
        self.fst_vt.VS_SlPc = float(f.readline().split()[0])
        gm = f.readline().split()[0]
        if gm == '1':
            self.fst_vt.GenModel = 1
        elif gm == '2':
            self.fst_vt.GenModel = 2
        else:
            self.fst_vt.GenModel = 3
        self.fst_vt.GenTiStr = bool(f.readline().split()[0])
        self.fst_vt.GenTiStp = bool(f.readline().split()[0])
        self.fst_vt.SpdGenOn = float(f.readline().split()[0])
        self.fst_vt.TimGenOn = float(f.readline().split()[0])
        self.fst_vt.TimGenOf = float(f.readline().split()[0])
        hss = f.readline().split()[0]
        if hss == '1':
            self.fst_vt.HSSBrMode = 1
        else:
            self.fst_vt.HSSBrMode = 2
        self.fst_vt.THSSBrDp = float(f.readline().split()[0])
        self.fst_vt.TiDynBrk = float(f.readline().split()[0])
        self.fst_vt.TTpBrDp1 = float(f.readline().split()[0])
        self.fst_vt.TTpBrDp2 = float(f.readline().split()[0])
        self.fst_vt.TTpBrDp3 = float(f.readline().split()[0])
        self.fst_vt.TBDepISp1 = float(f.readline().split()[0])
        self.fst_vt.TBDepISp2 = float(f.readline().split()[0])
        self.fst_vt.TBDepISp3 = float(f.readline().split()[0])
        self.fst_vt.TYawManS = float(f.readline().split()[0])
        self.fst_vt.TYawManE = float(f.readline().split()[0])
        self.fst_vt.NacYawF = float(f.readline().split()[0])
        self.fst_vt.TPitManS1 = float(f.readline().split()[0])
        self.fst_vt.TPitManS2 = float(f.readline().split()[0])
        self.fst_vt.TPitManS3 = float(f.readline().split()[0])
        self.fst_vt.TPitManE1 = float(f.readline().split()[0])
        self.fst_vt.TPitManE2 = float(f.readline().split()[0])
        self.fst_vt.TPitManE3 = float(f.readline().split()[0])
        self.fst_vt.BlPitch1 = float(f.readline().split()[0])
        self.fst_vt.BlPitch2 = float(f.readline().split()[0])
        self.fst_vt.BlPitch3 = float(f.readline().split()[0])
        self.fst_vt.B1PitchF1 = float(f.readline().split()[0])
        self.fst_vt.B1PitchF2 = float(f.readline().split()[0])
        self.fst_vt.B1PitchF3 = float(f.readline().split()[0])
        f.readline()
        self.fst_vt.Gravity = float(f.readline().split()[0])
        f.readline()
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.FlapDOF1 = False
        else:
            self.fst_vt.FlapDOF1 = True
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.FlapDOF2 = False
        else:
            self.fst_vt.FlapDOF2 = True
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.EdgeDOF = False
        else:
            self.fst_vt.EdgeDOF = True
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.TeetDOF = False
        else:
            self.fst_vt.TeetDOF = True
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.DrTrDOF = False
        else:
            self.fst_vt.DrTrDOF = True
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.GenDOF = False
        else:
            self.fst_vt.GenDOF = True
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.YawDOF = False
        else:
            self.fst_vt.YawDOF = True
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.TwFADOF1 = False
        else:
            self.fst_vt.TwFADOF1 = True
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.TwFADOF2 = False
        else:
            self.fst_vt.TwFADOF2 = True
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.TwSSDOF1 = False
        else:
            self.fst_vt.TwSSDOF1 = True
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.TwSSDOF2 = False
        else:
            self.fst_vt.TwSSDOF2 = True
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.CompAero = False
        else:
            self.fst_vt.CompAero = True
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.CompNoise = False
        else:
            self.fst_vt.CompNoise = True
        f.readline()
        self.fst_vt.OoPDefl = float(f.readline().split()[0])
        self.fst_vt.IPDefl = float(f.readline().split()[0])
        self.fst_vt.TeetDefl = float(f.readline().split()[0])
        self.fst_vt.Azimuth = float(f.readline().split()[0])
        self.fst_vt.RotSpeed = float(f.readline().split()[0])
        self.fst_vt.NacYaw = float(f.readline().split()[0])
        self.fst_vt.TTDspFA = float(f.readline().split()[0])
        self.fst_vt.TTDspSS = float(f.readline().split()[0])
        f.readline()
        self.fst_vt.TipRad = float(f.readline().split()[0])
        self.fst_vt.HubRad = float(f.readline().split()[0])
        self.fst_vt.PSpnElN = int(f.readline().split()[0])
        self.fst_vt.UndSling = float(f.readline().split()[0])
        self.fst_vt.HubCM = float(f.readline().split()[0])
        self.fst_vt.OverHang = float(f.readline().split()[0])
        self.fst_vt.NacCMxn = float(f.readline().split()[0])
        self.fst_vt.NacCMyn = float(f.readline().split()[0])
        self.fst_vt.NacCMzn = float(f.readline().split()[0])
        self.fst_vt.TowerHt = float(f.readline().split()[0])
        self.fst_vt.Twr2Shft = float(f.readline().split()[0])
        self.fst_vt.TwrRBHt = float(f.readline().split()[0])
        self.fst_vt.ShftTilt = float(f.readline().split()[0])
        self.fst_vt.Delta3 = float(f.readline().split()[0])
        self.fst_vt.PreCone1 = float(f.readline().split()[0])
        self.fst_vt.PreCone2 = float(f.readline().split()[0])
        self.fst_vt.PreCone3 = float(f.readline().split()[0])
        self.fst_vt.AzimB1Up = float(f.readline().split()[0])
        f.readline()
        self.fst_vt.YawBrMass = float(f.readline().split()[0])
        self.fst_vt.NacMass = float(f.readline().split()[0])
        self.fst_vt.HubMass = float(f.readline().split()[0])
        self.fst_vt.TipMass1 = float(f.readline().split()[0])
        self.fst_vt.TipMass2 = float(f.readline().split()[0])
        self.fst_vt.TipMass3 = float(f.readline().split()[0])
        self.fst_vt.NacYIner = float(f.readline().split()[0])
        self.fst_vt.GenIner = float(f.readline().split()[0])
        self.fst_vt.HubIner = float(f.readline().split()[0])
        f.readline()
        self.fst_vt.GBoxEff = float(f.readline().split()[0])
        self.fst_vt.GenEff = float(f.readline().split()[0])
        self.fst_vt.GBRatio = float(f.readline().split()[0])
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.GBRevers = False
        else:
            self.fst_vt.GBRevers = True
        self.fst_vt.HSSBrTqF = float(f.readline().split()[0])
        self.fst_vt.HSSBrDT = float(f.readline().split()[0])
        self.fst_vt.DynBrkFi = f.readline().split()[0]
        self.fst_vt.DTTorSpr = float(f.readline().split()[0])
        self.fst_vt.DTTorDmp = float(f.readline().split()[0])
        f.readline()
        self.fst_vt.SIG_SlPc = float(f.readline().split()[0])
        self.fst_vt.SIG_SySp = float(f.readline().split()[0])
        self.fst_vt.SIG_RtTq = float(f.readline().split()[0])
        self.fst_vt.SIG_PORt = float(f.readline().split()[0])
        f.readline()
        self.fst_vt.TEC_Freq = float(f.readline().split()[0])
        self.fst_vt.TEC_NPol = int(f.readline().split()[0])
        self.fst_vt.TEC_SRes = float(f.readline().split()[0])
        self.fst_vt.TEC_RRes = float(f.readline().split()[0])
        self.fst_vt.TEC_VLL = float(f.readline().split()[0])
        self.fst_vt.TEC_SLR = float(f.readline().split()[0])
        self.fst_vt.TEC_RLR = float(f.readline().split()[0])
        self.fst_vt.TEC_MR = float(f.readline().split()[0])
        f.readline()
        pm = f.readline().split()[0]
        if pm == '0':
            self.fst_vt.PtfmModel = 0
        elif pm == '1':
            self.fst_vt.PtfmModel = 1
        elif pm == '2':
            self.fst_vt.PtfmModel = 2
        else:
            self.fst_vt.PtfmModel = 3
        self.fst_vt.PtfmFile = f.readline().split()[0][1:-1]
        f.readline()
        self.fst_vt.TwrNodes = int(f.readline().split()[0])
        self.fst_vt.TwrFile = f.readline().split()[0][1:-1]
        f.readline()
        self.fst_vt.YawSpr = float(f.readline().split()[0])
        self.fst_vt.YawDamp = float(f.readline().split()[0])
        self.fst_vt.YawNeut = float(f.readline().split()[0])
        f.readline()
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.Furling = False
        else:
            self.fst_vt.Furling = True
        self.fst_vt.FurlFile = f.readline().split()[0]
        f.readline()
        tm = f.readline().split()[0]
        if tm == '0':
            self.fst_vt.TeetMod = 0
        elif tm == '1':
            self.fst_vt.TeetMod = 1
        else:
            self.fst_vt.TeetMod = 2
        self.fst_vt.TeetDmpP = float(f.readline().split()[0])
        self.fst_vt.TeetDmp = float(f.readline().split()[0])
        self.fst_vt.TeetCDmp = float(f.readline().split()[0])
        self.fst_vt.TeetSStP = float(f.readline().split()[0])
        self.fst_vt.TeetHStP = float(f.readline().split()[0])
        self.fst_vt.TeetSSSp = float(f.readline().split()[0])
        self.fst_vt.TeetHSSp = float(f.readline().split()[0])
        f.readline()
        self.fst_vt.TBDrConN = float(f.readline().split()[0])
        self.fst_vt.TBDrConD = float(f.readline().split()[0])
        self.fst_vt.TpBrDT = float(f.readline().split()[0])
        f.readline()
        self.fst_vt.BldFile1 = f.readline().split()[0][
            1:-1]  # TODO - different blade files
        self.fst_vt.BldFile2 = f.readline().split()[0][1:-1]
        self.fst_vt.BldFile3 = f.readline().split()[0][1:-1]
        f.readline()
        self.fst_vt.ADFile = f.readline().split()[0][1:-1]
        f.readline()
        self.fst_vt.NoiseFile = f.readline().split()[0]
        f.readline()
        self.fst_vt.ADAMSFile = f.readline().split()[0]
        f.readline()
        self.fst_vt.LinFile = f.readline().split()[0]
        f.readline()
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.SumPrint = False
        else:
            self.fst_vt.SumPrint = True
        if self.fst_file_type == 0:
            ff = f.readline().split()[0]
            if ff == '1':
                self.fst_vt.OutFileFmt = 1
            else:
                self.fst_vt.OutFileFmt = 2
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.TabDelim = False
        else:
            self.fst_vt.TabDelim = True

        self.fst_vt.OutFmt = f.readline().split()[0]
        self.fst_vt.TStart = float(f.readline().split()[0])
        self.fst_vt.DecFact = int(f.readline().split()[0])
        self.fst_vt.SttsTime = float(f.readline().split()[0])
        self.fst_vt.NcIMUxn = float(f.readline().split()[0])
        self.fst_vt.NcIMUyn = float(f.readline().split()[0])
        self.fst_vt.NcIMUzn = float(f.readline().split()[0])
        self.fst_vt.ShftGagL = float(f.readline().split()[0])
        self.fst_vt.NTwGages = int(f.readline().split()[0])
        twrg = f.readline().split(',')
        for i in range(self.fst_vt.NTwGages):
            self.fst_vt.TwrGagNd.append(twrg[i])
        self.fst_vt.TwrGagNd[-1] = self.fst_vt.TwrGagNd[-1][0:2]
        self.fst_vt.NBlGages = int(f.readline().split()[0])
        blg = f.readline().split(',')
        for i in range(self.fst_vt.NBlGages):
            self.fst_vt.BldGagNd.append(blg[i])
        self.fst_vt.BldGagNd[-1] = self.fst_vt.BldGagNd[-1][0:2]

        # Outlist (TODO - detailed categorization)
        f.readline()
        data = f.readline()
        while data.split()[0] != 'END':
            channels = data.split('"')
            channel_list = channels[1].split(',')
            for i in range(len(channel_list)):
                channel_list[i] = channel_list[i].replace(' ', '')
                if channel_list[
                        i] in self.fst_vt.fst_output_vt.wind_mot_vt.__dict__.keys(
                        ):
                    self.fst_vt.fst_output_vt.wind_mot_vt.__dict__[
                        channel_list[i]] = True
            for i in range(len(channel_list)):
                channel_list[i] = channel_list[i].replace(' ', '')
                if channel_list[
                        i] in self.fst_vt.fst_output_vt.blade_mot_vt.__dict__.keys(
                        ):
                    self.fst_vt.fst_output_vt.blade_mot_vt.__dict__[
                        channel_list[i]] = True
            for i in range(len(channel_list)):
                channel_list[i] = channel_list[i].replace(' ', '')
                if channel_list[
                        i] in self.fst_vt.fst_output_vt.hub_nacelle_mot_vt.__dict__.keys(
                        ):
                    self.fst_vt.fst_output_vt.hub_nacelle_mot_vt.__dict__[
                        channel_list[i]] = True
            for i in range(len(channel_list)):
                channel_list[i] = channel_list[i].replace(' ', '')
                if channel_list[
                        i] in self.fst_vt.fst_output_vt.tower_support_mot_vt.__dict__.keys(
                        ):
                    self.fst_vt.fst_output_vt.tower_support_mot_vt.__dict__[
                        channel_list[i]] = True
            for i in range(len(channel_list)):
                channel_list[i] = channel_list[i].replace(' ', '')
                if channel_list[
                        i] in self.fst_vt.fst_output_vt.wave_mot_vt.__dict__.keys(
                        ):
                    self.fst_vt.fst_output_vt.wave_mot_vt.__dict__[
                        channel_list[i]] = True
            for i in range(len(channel_list)):
                channel_list[i] = channel_list[i].replace(' ', '')
                if channel_list[
                        i] in self.fst_vt.fst_output_vt.blade_loads_vt.__dict__.keys(
                        ):
                    self.fst_vt.fst_output_vt.blade_loads_vt.__dict__[
                        channel_list[i]] = True
            for i in range(len(channel_list)):
                channel_list[i] = channel_list[i].replace(' ', '')
                if channel_list[
                        i] in self.fst_vt.fst_output_vt.hub_nacelle_loads_vt.__dict__.keys(
                        ):
                    self.fst_vt.fst_output_vt.hub_nacelle_loads_vt.__dict__[
                        channel_list[i]] = True
            for i in range(len(channel_list)):
                channel_list[i] = channel_list[i].replace(' ', '')
                if channel_list[
                        i] in self.fst_vt.fst_output_vt.tower_support_loads_vt.__dict__.keys(
                        ):
                    self.fst_vt.fst_output_vt.tower_support_loads_vt.__dict__[
                        channel_list[i]] = True
            for i in range(len(channel_list)):
                channel_list[i] = channel_list[i].replace(' ', '')
                if channel_list[
                        i] in self.fst_vt.fst_output_vt.dof_vt.__dict__.keys():
                    self.fst_vt.fst_output_vt.dof_vt.__dict__[
                        channel_list[i]] = True
            data = f.readline()

        self.AeroReader()
        if self.fst_vt.aero_vt.wind_file_type == 'hh':
            self.SimpleWindReader()
        else:
            print "TODO: not simple wind file"
        self.BladeReader()
        self.TowerReader()
        self.PlatformReader()

    def PlatformReader(self):

        platform_file = os.path.join(self.fst_directory, self.fst_vt.PtfmFile)
        f = open(platform_file)

        f.readline()
        f.readline()
        self.fst_vt.platform_vt.description = f.readline().rstrip()

        # FEATURE FLAGS (CONT)
        f.readline()
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.PtfmSgDOF = False
        else:
            self.fst_vt.PtfmSgDOF = True
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.PtfmSwDOF = False
        else:
            self.fst_vt.PtfmSwDOF = True
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.PtfmHvDOF = False
        else:
            self.fst_vt.PtfmHvDOF = True
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.PtfmRDOF = False
        else:
            self.fst_vt.PtfmRDOF = True
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.PtfmPDOF = False
        else:
            self.fst_vt.PtfmPDOF = True
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.PtfmYDOF = False
        else:
            self.fst_vt.PtfmYDOF = True

        # INITIAL CONDITIONS (CONT)
        f.readline()
        self.fst_vt.platform_vt.PtfmSurge = float(f.readline().split()[0])
        self.fst_vt.platform_vt.PtfmSway = float(f.readline().split()[0])
        self.fst_vt.platform_vt.PtfmHeave = float(f.readline().split()[0])
        self.fst_vt.platform_vt.PtfmRoll = float(f.readline().split()[0])
        self.fst_vt.platform_vt.PtfmPitch = float(f.readline().split()[0])
        self.fst_vt.platform_vt.PtfmYaw = float(f.readline().split()[0])

        # TURBINE CONFIGURATION (CONT)
        f.readline()
        self.fst_vt.platform_vt.TwrDraft = float(f.readline().split()[0])
        self.fst_vt.platform_vt.PtfmCM = float(f.readline().split()[0])
        self.fst_vt.platform_vt.PtfmRef = float(f.readline().split()[0])

        # MASS AND INERTIA (CONT)
        f.readline()
        self.fst_vt.platform_vt.PtfmMass = float(f.readline().split()[0])
        self.fst_vt.platform_vt.PtfmRIner = float(f.readline().split()[0])
        self.fst_vt.platform_vt.PtfmPIner = float(f.readline().split()[0])
        self.fst_vt.platform_vt.PtfmYIner = float(f.readline().split()[0])

        # PLATFORM (CONT)
        f.readline()
        pltmd = f.readline().split()[0]
        if pltmd == '0':
            self.fst_vt.platform_vt.PtfmLdMod = 0
        else:
            self.fst_vt.platform_vt.PtfmLdMod = 1

        # TOWER (CONT)
        f.readline()
        twrmd = f.readline().split()[0]
        if twrmd == '0':
            self.fst_vt.platform_vt.TwrLdMod = 0
        elif twrmd == '1':
            self.fst_vt.platform_vt.TwrLdMod = 1
        elif twrmd == '2':
            self.fst_vt.platform_vt.TwrLdMod = 3
        self.fst_vt.platform_vt.TwrDiam = float(f.readline().split()[0])
        self.fst_vt.platform_vt.TwrCA = float(f.readline().split()[0])
        self.fst_vt.platform_vt.TwrCD = float(f.readline().split()[0])

        # WAVES
        f.readline()
        self.fst_vt.platform_vt.WtrDens = float(f.readline().split()[0])
        self.fst_vt.platform_vt.WtrDpth = float(f.readline().split()[0])
        wavemod = f.readline().split()[0]
        if wavemod == '0':
            self.fst_vt.platform_vt.WaveMod = 0
        elif wavemod == '1':
            self.fst_vt.platform_vt.WaveMod = 1
        elif wavemod == '2':
            self.fst_vt.platform_vt.WaveMod = 2
        elif wavemod == '3':
            self.fst_vt.platform_vt.WaveMod = 3
        else:
            self.fst_vt.platform_vt.WaveMod = 4
        wavestmod = f.readline().split()[0]
        if wavestmod == '0':
            self.fst_vt.platform_vt.WaveStMod = 0
        elif wavestmod == '1':
            self.fst_vt.platform_vt.WaveStMod = 1
        elif wavestmod == '2':
            self.fst_vt.platform_vt.WaveStMod = 2
        elif wavestmod == '3':
            self.fst_vt.platform_vt.WaveStMod = 3
        self.fst_vt.platform_vt.WaveTMax = float(f.readline().split()[0])
        self.fst_vt.platform_vt.WaveDT = float(f.readline().split()[0])
        self.fst_vt.platform_vt.WaveHs = float(f.readline().split()[0])
        self.fst_vt.platform_vt.WaveTp = float(f.readline().split()[0])
        wvpk = f.readline().split()[0]
        if wvpk == 'DEFAULT':
            self.fst_vt.platform_vt.WavePkShp = 9999.9
        else:
            self.fst_vt.platform_vt.WavePkShp = float(wvpk)
        self.fst_vt.platform_vt.WaveDir = float(f.readline().split()[0])
        self.fst_vt.platform_vt.WaveSeed1 = int(f.readline().split()[0])
        self.fst_vt.platform_vt.WaveSeed2 = int(f.readline().split()[0])
        self.fst_vt.platform_vt.GHWvFile = f.readline().split()[0]

        # CURRENT
        f.readline()
        currmod = float(f.readline().split()[0])
        if currmod == '0':
            self.fst_vt.platform_vt.CurrMod = 0
        elif currmod == '1':
            self.fst_vt.platform_vt.CurrMod = 1
        elif currmod == '2':
            self.fst_vt.platform_vt.CurrMod = 2
        self.fst_vt.platform_vt.CurrSSV0 = float(f.readline().split()[0])
        currs = f.readline().split()[0]
        if currs == 'DEFAULT':
            self.fst_vt.platform_vt.CurrSSDir = 9999.9
        else:
            self.fst_vt.platform_vt.CurrSSDir = float(currs)
        self.fst_vt.platform_vt.CurrNSRef = float(f.readline().split()[0])
        self.fst_vt.platform_vt.CurrNSV0 = float(f.readline().split()[0])
        self.fst_vt.platform_vt.CurrNSDir = float(f.readline().split()[0])
        self.fst_vt.platform_vt.CurrDIV = float(f.readline().split()[0])
        self.fst_vt.platform_vt.CurrDIDir = float(f.readline().split()[0])

        # OUTPUT (CONT)
        f.readline()
        self.fst_vt.platform_vt.NWaveKin = int(f.readline().split()[0])
        if self.fst_vt.platform_vt.NWaveKin != 0:
            self.fst_vt.platform_vt.WaveKinNd = str(f.readline().split()[0])

    def TowerReader(self):

        tower_file = os.path.join(self.fst_directory, self.fst_vt.TwrFile)
        f = open(tower_file)

        f.readline()
        f.readline()
        self.fst_vt.fst_tower_vt.description = f.readline().rstrip()

        # General Tower Paramters
        f.readline()
        self.fst_vt.fst_tower_vt.NTwInptSt = int(f.readline().split()[0])
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.CalcTMode = False
        else:
            self.fst_vt.CalcTMode = True
        self.fst_vt.fst_tower_vt.TwrFADmp1 = float(f.readline().split()[0])
        self.fst_vt.fst_tower_vt.TwrFADmp2 = float(f.readline().split()[0])
        self.fst_vt.fst_tower_vt.TwrSSDmp1 = float(f.readline().split()[0])
        self.fst_vt.fst_tower_vt.TwrSSDmp2 = float(f.readline().split()[0])

        # Tower Adjustment Factors
        f.readline()
        self.fst_vt.fst_tower_vt.FAStTunr1 = float(f.readline().split()[0])
        self.fst_vt.fst_tower_vt.FAStTunr2 = float(f.readline().split()[0])
        self.fst_vt.fst_tower_vt.SSStTunr1 = float(f.readline().split()[0])
        self.fst_vt.fst_tower_vt.SSStTunr2 = float(f.readline().split()[0])
        self.fst_vt.fst_tower_vt.AdjTwMa = float(f.readline().split()[0])
        self.fst_vt.fst_tower_vt.AdjFASt = float(f.readline().split()[0])
        self.fst_vt.fst_tower_vt.AdjSSSt = float(f.readline().split()[0])

        # Distributed Tower Properties
        x = f.readline()
        y = f.readline()
        z = f.readline()
        self.fst_vt.fst_tower_vt.HtFract = [
            None
        ] * self.fst_vt.fst_tower_vt.NTwInptSt
        self.fst_vt.fst_tower_vt.TMassDen = [
            None
        ] * self.fst_vt.fst_tower_vt.NTwInptSt
        self.fst_vt.fst_tower_vt.TwFAStif = [
            None
        ] * self.fst_vt.fst_tower_vt.NTwInptSt
        self.fst_vt.fst_tower_vt.TwSSStif = [
            None
        ] * self.fst_vt.fst_tower_vt.NTwInptSt
        self.fst_vt.fst_tower_vt.TwGJStif = [
            None
        ] * self.fst_vt.fst_tower_vt.NTwInptSt
        self.fst_vt.fst_tower_vt.TwEAStif = [
            None
        ] * self.fst_vt.fst_tower_vt.NTwInptSt
        self.fst_vt.fst_tower_vt.TwFAIner = [
            None
        ] * self.fst_vt.fst_tower_vt.NTwInptSt
        self.fst_vt.fst_tower_vt.TwSSIner = [
            None
        ] * self.fst_vt.fst_tower_vt.NTwInptSt
        self.fst_vt.fst_tower_vt.TwFAcgOf = [
            None
        ] * self.fst_vt.fst_tower_vt.NTwInptSt
        self.fst_vt.fst_tower_vt.TwSScgOf = [
            None
        ] * self.fst_vt.fst_tower_vt.NTwInptSt
        for i in range(self.fst_vt.fst_tower_vt.NTwInptSt):
            data = f.readline().split()
            self.fst_vt.fst_tower_vt.HtFract[i] = float(data[0])
            self.fst_vt.fst_tower_vt.TMassDen[i] = float(data[1])
            self.fst_vt.fst_tower_vt.TwFAStif[i] = float(data[2])
            self.fst_vt.fst_tower_vt.TwSSStif[i] = float(data[3])
            self.fst_vt.fst_tower_vt.TwGJStif[i] = float(data[4])
            self.fst_vt.fst_tower_vt.TwEAStif[i] = float(data[5])
            self.fst_vt.fst_tower_vt.TwFAIner[i] = float(data[6])
            self.fst_vt.fst_tower_vt.TwSSIner[i] = float(data[7])
            self.fst_vt.fst_tower_vt.TwFAcgOf[i] = float(data[8])
            self.fst_vt.fst_tower_vt.TwSScgOf[i] = float(data[9])

        # Tower Mode Shapes
        f.readline()
        self.fst_vt.fst_tower_vt.TwFAM1Sh = [None] * 5
        self.fst_vt.fst_tower_vt.TwFAM2Sh = [None] * 5
        for i in range(5):
            self.fst_vt.fst_tower_vt.TwFAM1Sh[i] = float(
                f.readline().split()[0])
        for i in range(5):
            self.fst_vt.fst_tower_vt.TwFAM2Sh[i] = float(
                f.readline().split()[0])
        f.readline()
        self.fst_vt.fst_tower_vt.TwSSM1Sh = [None] * 5
        self.fst_vt.fst_tower_vt.TwSSM2Sh = [None] * 5
        for i in range(5):
            self.fst_vt.fst_tower_vt.TwSSM1Sh[i] = float(
                f.readline().split()[0])
        for i in range(5):
            self.fst_vt.fst_tower_vt.TwSSM2Sh[i] = float(
                f.readline().split()[0])

    def BladeReader(self):

        blade_file = os.path.join(self.fst_directory, self.fst_vt.BldFile1)
        f = open(blade_file)

        f.readline()
        f.readline()
        self.fst_vt.fst_blade_vt.description = f.readline().rstrip()
        f.readline()

        self.fst_vt.fst_blade_vt.NBlInpSt = int(f.readline().split()[0])
        boolflag = f.readline().split()[0]
        if boolflag == 'False':
            self.fst_vt.CalcBMode = False
        else:
            self.fst_vt.CalcBMode = True
        self.fst_vt.fst_blade_vt.BldFlDmp1 = float(f.readline().split()[0])
        self.fst_vt.fst_blade_vt.BldFlDmp2 = float(f.readline().split()[0])
        self.fst_vt.fst_blade_vt.BldEdDmp1 = float(f.readline().split()[0])
        f.readline()
        self.fst_vt.fst_blade_vt.FlStTunr1 = float(f.readline().split()[0])
        self.fst_vt.fst_blade_vt.FlStTunr2 = float(f.readline().split()[0])
        self.fst_vt.fst_blade_vt.AdjBlMs = float(f.readline().split()[0])
        self.fst_vt.fst_blade_vt.AdjFlSt = float(f.readline().split()[0])
        self.fst_vt.fst_blade_vt.AdjEdSt = float(f.readline().split()[0])

        f.readline()
        f.readline()
        f.readline()
        self.fst_vt.fst_blade_vt.BlFract = [
            None
        ] * self.fst_vt.fst_blade_vt.NBlInpSt
        self.fst_vt.fst_blade_vt.AeroCent = [
            None
        ] * self.fst_vt.fst_blade_vt.NBlInpSt
        self.fst_vt.fst_blade_vt.StrcTwst = [
            None
        ] * self.fst_vt.fst_blade_vt.NBlInpSt
        self.fst_vt.fst_blade_vt.BMassDen = [
            None
        ] * self.fst_vt.fst_blade_vt.NBlInpSt
        self.fst_vt.fst_blade_vt.FlpStff = [
            None
        ] * self.fst_vt.fst_blade_vt.NBlInpSt
        self.fst_vt.fst_blade_vt.EdgStff = [
            None
        ] * self.fst_vt.fst_blade_vt.NBlInpSt
        self.fst_vt.fst_blade_vt.GJStff = [
            None
        ] * self.fst_vt.fst_blade_vt.NBlInpSt
        self.fst_vt.fst_blade_vt.EAStff = [
            None
        ] * self.fst_vt.fst_blade_vt.NBlInpSt
        self.fst_vt.fst_blade_vt.Alpha = [None
                                          ] * self.fst_vt.fst_blade_vt.NBlInpSt
        self.fst_vt.fst_blade_vt.FlpIner = [
            None
        ] * self.fst_vt.fst_blade_vt.NBlInpSt
        self.fst_vt.fst_blade_vt.EdgIner = [
            None
        ] * self.fst_vt.fst_blade_vt.NBlInpSt
        self.fst_vt.fst_blade_vt.PrecrvRef = [
            None
        ] * self.fst_vt.fst_blade_vt.NBlInpSt
        self.fst_vt.fst_blade_vt.FlpcgOf = [
            None
        ] * self.fst_vt.fst_blade_vt.NBlInpSt
        self.fst_vt.fst_blade_vt.Edgcgof = [
            None
        ] * self.fst_vt.fst_blade_vt.NBlInpSt
        self.fst_vt.fst_blade_vt.FlpEAOf = [
            None
        ] * self.fst_vt.fst_blade_vt.NBlInpSt
        self.fst_vt.fst_blade_vt.EdgEAOf = [
            None
        ] * self.fst_vt.fst_blade_vt.NBlInpSt
        for i in range(self.fst_vt.fst_blade_vt.NBlInpSt):
            data = f.readline().split()
            self.fst_vt.fst_blade_vt.BlFract[i] = float(data[0])
            self.fst_vt.fst_blade_vt.AeroCent[i] = float(data[1])
            self.fst_vt.fst_blade_vt.StrcTwst[i] = float(data[2])
            self.fst_vt.fst_blade_vt.BMassDen[i] = float(data[3])
            self.fst_vt.fst_blade_vt.FlpStff[i] = float(data[4])
            self.fst_vt.fst_blade_vt.EdgStff[i] = float(data[5])
            self.fst_vt.fst_blade_vt.GJStff[i] = float(data[6])
            self.fst_vt.fst_blade_vt.EAStff[i] = float(data[7])
            self.fst_vt.fst_blade_vt.Alpha[i] = float(data[8])
            self.fst_vt.fst_blade_vt.FlpIner[i] = float(data[9])
            self.fst_vt.fst_blade_vt.EdgIner[i] = float(data[10])
            self.fst_vt.fst_blade_vt.PrecrvRef[i] = float(data[11])
            self.fst_vt.fst_blade_vt.FlpcgOf[i] = float(data[12])
            self.fst_vt.fst_blade_vt.Edgcgof[i] = float(data[13])
            self.fst_vt.fst_blade_vt.FlpEAOf[i] = float(data[14])
            self.fst_vt.fst_blade_vt.EdgEAOf[i] = float(data[15])

        f.readline()
        self.fst_vt.fst_blade_vt.BldFl1Sh = [None] * 5
        self.fst_vt.fst_blade_vt.BldFl2Sh = [None] * 5
        self.fst_vt.fst_blade_vt.BldEdgSh = [None] * 5
        for i in range(5):
            self.fst_vt.fst_blade_vt.BldFl1Sh[i] = float(
                f.readline().split()[0])
        for i in range(5):
            self.fst_vt.fst_blade_vt.BldFl2Sh[i] = float(
                f.readline().split()[0])
        for i in range(5):
            self.fst_vt.fst_blade_vt.BldEdgSh[i] = float(
                f.readline().split()[0])

    def AeroReader(self):

        #from airfoil import PolarByRe # only if creating airfoil variable trees

        ad_file = os.path.join(self.fst_directory, self.fst_vt.ADFile)
        f = open(ad_file)

        # skip lines and check if nondimensional
        f.readline()
        self.fst_vt.aero_vt.SysUnits = f.readline().split()[0]
        self.fst_vt.aero_vt.StallMod = f.readline().split()[0]
        self.fst_vt.aero_vt.UseCm = f.readline().split()[0]
        self.fst_vt.aero_vt.InfModel = f.readline().split()[0]
        self.fst_vt.aero_vt.IndModel = f.readline().split()[0]
        self.fst_vt.aero_vt.AToler = float(f.readline().split()[0])
        self.fst_vt.aero_vt.TLModel = f.readline().split()[0]
        self.fst_vt.aero_vt.HLModel = f.readline().split()[0]
        self.fst_vt.aero_vt.WindFile = f.readline().split()[0][1:-1]
        if self.fst_vt.aero_vt.WindFile[-1] == 'h':
            self.fst_vt.aero_vt.wind_file_type = 'hh'
        elif self.fst_vt.aero_vt.WindFile[-1] == 's':
            self.fst_vt.aero_vt.wind_file_type = 'bts'
        else:
            self.fst_vt.aero_vt.wind_file_type = 'wnd'
        self.fst_vt.aero_vt.HH = float(f.readline().split()[0])
        self.fst_vt.aero_vt.TwrShad = float(f.readline().split()[0])
        self.fst_vt.aero_vt.ShadHWid = float(f.readline().split()[0])
        self.fst_vt.aero_vt.T_Shad_Refpt = float(f.readline().split()[0])
        self.fst_vt.aero_vt.AirDens = float(f.readline().split()[0])
        self.fst_vt.aero_vt.KinVisc = float(f.readline().split()[0])
        self.fst_vt.aero_vt.DTAero = float(f.readline().split()[0])

        self.fst_vt.aero_vt.blade_vt.NumFoil = int(f.readline().split()[0])
        self.fst_vt.aero_vt.blade_vt.FoilNm = [
            None
        ] * self.fst_vt.aero_vt.blade_vt.NumFoil
        for i in range(self.fst_vt.aero_vt.blade_vt.NumFoil):
            af_filename = f.readline().split()[0]
            af_filename = fix_path(af_filename)
            print af_filename
            self.fst_vt.aero_vt.blade_vt.FoilNm[i] = af_filename[1:-1]

        self.fst_vt.aero_vt.blade_vt.BldNodes = int(f.readline().split()[0])
        f.readline()
        self.fst_vt.aero_vt.blade_vt.RNodes = [
            None
        ] * self.fst_vt.aero_vt.blade_vt.BldNodes
        self.fst_vt.aero_vt.blade_vt.AeroTwst = [
            None
        ] * self.fst_vt.aero_vt.blade_vt.BldNodes
        self.fst_vt.aero_vt.blade_vt.DRNodes = [
            None
        ] * self.fst_vt.aero_vt.blade_vt.BldNodes
        self.fst_vt.aero_vt.blade_vt.Chord = [
            None
        ] * self.fst_vt.aero_vt.blade_vt.BldNodes
        self.fst_vt.aero_vt.blade_vt.NFoil = [
            None
        ] * self.fst_vt.aero_vt.blade_vt.BldNodes
        self.fst_vt.aero_vt.blade_vt.PrnElm = [
            None
        ] * self.fst_vt.aero_vt.blade_vt.BldNodes
        for i in range(self.fst_vt.aero_vt.blade_vt.BldNodes):
            data = f.readline().split()
            self.fst_vt.aero_vt.blade_vt.RNodes[i] = float(data[0])
            self.fst_vt.aero_vt.blade_vt.AeroTwst[i] = float(data[1])
            self.fst_vt.aero_vt.blade_vt.DRNodes[i] = float(data[2])
            self.fst_vt.aero_vt.blade_vt.Chord[i] = float(data[3])
            self.fst_vt.aero_vt.blade_vt.NFoil[i] = int(data[4])
            self.fst_vt.aero_vt.blade_vt.PrnElm[i] = data[5]

        f.close()

        # create airfoil objects
        for i in range(self.fst_vt.aero_vt.blade_vt.NumFoil):
            self.fst_vt.aero_vt.blade_vt.af_data.append(
                self.initFromAerodynFile(
                    os.path.join(self.fst_directory,
                                 self.fst_vt.aero_vt.blade_vt.FoilNm[i]),
                    self.ad_file_type))

    def initFromAerodynFile(self, aerodynFile,
                            mode):  # kld - added for fast noise
        """
        Construct array of polars from old-style Aerodyn file
        Use this method for FAST (which can't read the new format) 2012 11 12

        Arguments:
        aerodynFile - path/name of a properly formatted old-style Aerodyn file
        """
        # open aerodyn file
        f = open(aerodynFile, 'r')

        airfoil = ADAirfoil()

        # skip through header
        airfoil.description = f.readline().rstrip()  # remove newline
        f.readline()
        if mode == 0:
            f.readline()
        airfoil.number_tables = int(f.readline().split()[0])

        # loop through tables
        for i in range(airfoil.number_tables):

            polar = ADAirfoilPolar()

            polar.IDParam = float(f.readline().split()[0])
            if mode == 0:
                f.readline()
            polar.StallAngle = float(f.readline().split()[0])
            if mode == 1:
                f.readline()
                f.readline()
                f.readline()
            polar.ZeroCn = float(f.readline().split()[0])
            polar.CnSlope = float(f.readline().split()[0])
            polar.CnPosStall = float(f.readline().split()[0])
            polar.CnNegStall = float(f.readline().split()[0])
            polar.alphaCdMin = float(f.readline().split()[0])
            polar.CdMin = float(f.readline().split()[0])

            alpha = []
            cl = []
            cd = []
            cm = []
            # read polar information line by line
            while True:
                line = f.readline()
                if 'EOT' in line:
                    break
                data = [float(s) for s in line.split()]
                if len(data) < 1:
                    break
                alpha.append(data[0])
                cl.append(data[1])
                cd.append(data[2])
                cm.append(data[3])

            polar.alpha = alpha
            polar.cl = cl
            polar.cd = cd
            polar.cm = cm
            airfoil.af_tables.append(polar)

        f.close()

        return airfoil

    def SimpleWindReader(self):

        #from airfoil import PolarByRe # only if creating airfoil variable trees

        wind_file = os.path.join(self.fst_directory,
                                 self.fst_vt.aero_vt.WindFile)
        f = open(wind_file)

        data = []
        while 1:
            line = f.readline()
            if not line:
                break
            line_split = line.split()
            if line_split[0] != '!':
                data.append(line.split())

        self.fst_vt.simple_wind_vt.TimeSteps = len(data)

        self.fst_vt.simple_wind_vt.Time = [None] * len(data)
        self.fst_vt.simple_wind_vt.HorSpd = [None] * len(data)
        self.fst_vt.simple_wind_vt.WindDir = [None] * len(data)
        self.fst_vt.simple_wind_vt.VerSpd = [None] * len(data)
        self.fst_vt.simple_wind_vt.HorShr = [None] * len(data)
        self.fst_vt.simple_wind_vt.VerShr = [None] * len(data)
        self.fst_vt.simple_wind_vt.LnVShr = [None] * len(data)
        self.fst_vt.simple_wind_vt.GstSpd = [None] * len(data)
        for i in range(len(data)):
            self.fst_vt.simple_wind_vt.Time[i] = float(data[i][0])
            self.fst_vt.simple_wind_vt.HorSpd[i] = float(data[i][1])
            self.fst_vt.simple_wind_vt.WindDir[i] = float(data[i][2])
            self.fst_vt.simple_wind_vt.VerSpd[i] = float(data[i][3])
            self.fst_vt.simple_wind_vt.HorShr[i] = float(data[i][4])
            self.fst_vt.simple_wind_vt.VerShr[i] = float(data[i][5])
            self.fst_vt.simple_wind_vt.LnVShr[i] = float(data[i][6])
            self.fst_vt.simple_wind_vt.GstSpd[i] = float(data[i][7])

        f.close()