Example #1
0
def prop(prop,
         maximum_thrust,
         chord_to_radius_ratio=0.1,
         thickness_to_chord=0.12,
         root_to_radius_ratio=0.1,
         moment_to_lift_ratio=0.02,
         spanwise_analysis_points=5,
         safety_factor=1.5,
         margin_factor=1.2,
         forward_web_locations=[0.25, 0.35],
         shear_center=0.25,
         speed_of_sound=340.294,
         tip_max_mach_number=0.65):
    """weight = SUAVE.Methods.Weights.Buildups.Common.prop(
            prop,
            maximum_thrust,
            chord_to_radius_ratio = 0.1,
            thickness_to_chord = 0.12,
            root_to_radius_ratio = 0.1,
            moment_to_lift_ratio = 0.02,
            spanwise_analysis_points = 5,
            safety_factor = 1.5,
            margin_factor = 1.2,
            forward_web_locationss = [0.25, 0.35],
            shear_center = 0.25,
            speed_of_sound = 340.294,
            tip_max_mach_number = 0.65)

        Assumptions:
        Calculates propeller blade pass for an eVTOL vehicle based on assumption
        of a NACA airfoil prop, an assumed cm/cl, tip Mach limit, and structural
        geometry.

        Intended for use with the following SUAVE vehicle types, but may be used
        elsewhere:

            Electric Multicopter
            Electric Vectored_Thrust
            Electric Stopped Rotor

        Originally written as part of an AA 290 project inteded for trade study
        of the above vehicle types.
        
        Sources:
        Project Vahana Conceptual Trade Study

        Inputs:

            prop                        SUAVE Propeller Data Structure
            maximum_thrust              Maximum Design Thrust               [N]
            chord_to_radius_ratio       Chord to Blade Radius               [Unitless]
            thickness_to_chord          Blade Thickness to Chord            [Unitless]
            root_to_radius_ratio        Root Structure to Blade Radius      [Unitless]
            moment_to_lift_ratio        Coeff. of Moment to Coeff. of Lift  [Unitless]
            spanwise_analysis_points    Analysis Points for Sizing          [Unitless]
            safety_factor               Design Safety Factor                [Unitless]
            margin_factor               Allowable Extra Mass Fraction       [Unitless]
            forward_web_locationss      Location of Forward Spar Webbing    [m]
            shear_center                Location of Shear Center            [m]
            speed_of_sound              Local Speed of Sound                [m/s]
            tip_max_mach_number         Allowable Tip Mach Number           [Unitless]

        Outputs:

            weight:                 Propeller Mass                      [kg]
            
        Properties Used:
        Material properties of imported SUAVE Solids
    """

    #-------------------------------------------------------------------------------
    # Unpack Inputs
    #-------------------------------------------------------------------------------

    rProp = prop.tip_radius
    maxThrust = maximum_thrust
    nBlades = prop.number_blades
    chord = rProp * chord_to_radius_ratio
    N = spanwise_analysis_points
    SF = safety_factor
    toc = thickness_to_chord
    fwdWeb = cp.deepcopy(forward_web_locations)
    xShear = shear_center
    rootLength = rProp * root_to_radius_ratio
    grace = margin_factor
    sound = speed_of_sound
    tipMach = tip_max_mach_number
    cmocl = moment_to_lift_ratio

    #-------------------------------------------------------------------------------
    # Unpack Material Properties
    #-------------------------------------------------------------------------------

    BiCF = Bidirectional_Carbon_Fiber()
    BiCF_MGT = BiCF.minimum_gage_thickness
    BiCF_DEN = BiCF.density
    BiCF_UTS = BiCF.ultimate_tensile_strength
    BiCF_USS = BiCF.ultimate_shear_strength
    BiCF_UBS = BiCF.ultimate_bearing_strength

    UniCF = Unidirectional_Carbon_Fiber()
    UniCF_MGT = UniCF.minimum_gage_thickness
    UniCF_DEN = UniCF.density
    UniCF_UTS = UniCF.ultimate_tensile_strength
    UniCF_USS = UniCF.ultimate_shear_strength

    HCMB = Carbon_Fiber_Honeycomb()
    HCMB_MGT = HCMB.minimum_gage_thickness
    HCMB_DEN = HCMB.density

    RIB = Aluminum_Rib()
    RIB_WID = RIB.minimum_width
    RIB_MGT = RIB.minimum_gage_thickness
    RIB_DEN = RIB.density

    ALUM = Aluminum()
    ALUM_DEN = ALUM.density
    ALUM_MGT = ALUM.minimum_gage_thickness
    ALUM_UTS = ALUM.ultimate_tensile_strength

    NICK = Nickel()
    NICK_DEN = NICK.density

    EPOXY = Epoxy()
    EPOXY_MGT = EPOXY.minimum_gage_thickness
    EPOXY_DEN = EPOXY.density

    PAINT = Paint()
    PAINT_MGT = PAINT.minimum_gage_thickness
    PAINT_DEN = PAINT.density

    #-------------------------------------------------------------------------------
    # Airfoil
    #-------------------------------------------------------------------------------

    NACA = np.multiply(5 * toc, [0.2969, -0.1260, -0.3516, 0.2843, -0.1015])
    coord = np.unique(fwdWeb + np.linspace(0, 1, N).tolist())[:, np.newaxis]
    coordMAT = np.concatenate(
        (coord**0.5, coord, coord**2, coord**3, coord**4), axis=1)
    nacaMAT = coordMAT.dot(NACA)[:, np.newaxis]
    coord = np.concatenate((coord, nacaMAT), axis=1)
    coord = np.concatenate(
        (coord[-1:0:-1], coord.dot(np.array([[1., 0.], [0., -1.]]))), axis=0)
    coord[:, 0] = coord[:, 0] - xShear

    #-------------------------------------------------------------------------------
    # Beam Geometry
    #-------------------------------------------------------------------------------

    x = np.linspace(0, rProp, N)
    dx = x[1] - x[0]
    fwdWeb[:] = [round(loc - xShear, 2) for loc in fwdWeb]

    #-------------------------------------------------------------------------------
    # Loads
    #-------------------------------------------------------------------------------

    omega = sound * tipMach / rProp  # Propeller Angular Velocity
    F = SF * 3 * (maxThrust / rProp**3) * (x**
                                           2) / nBlades  # Force Distribution
    Q = F * chord * cmocl  # Torsion Distribution

    #-------------------------------------------------------------------------------
    # Initial Mass Estimates
    #-------------------------------------------------------------------------------

    box = coord * chord
    skinLength = np.sum(np.sqrt(np.sum(np.diff(box, axis=0)**2, axis=1)))
    maxThickness = (np.amax(box[:, 1]) - np.amin(box[:, 1])) / 2
    rootBendingMoment = SF * maxThrust / nBlades * 0.75 * rProp
    m = (UniCF_DEN*dx*rootBendingMoment/
        (2*UniCF_USS*maxThickness))+ \
        skinLength*BiCF_MGT*dx*BiCF_DEN
    m = m * np.ones(N)
    error = 1  # Initialize Error
    tolerance = 1e-8  # Mass Tolerance
    massOld = np.sum(m)

    #-------------------------------------------------------------------------------
    # General Structural Properties
    #-------------------------------------------------------------------------------

    seg = []  # List of Structural Segments

    # Torsion

    enclosedArea = 0.5 * np.abs(
        np.dot(box[:, 0], np.roll(box[:, 1], 1)) -
        np.dot(box[:, 1], np.roll(box[:, 0], 1)))  # Shoelace Formula

    # Flap Properties

    box = coord  # Box Initially Matches Airfoil
    box = box[box[:, 0] <= fwdWeb[1]]  # Trim Coordinates Aft of Aft Web
    box = box[box[:, 0] >= fwdWeb[0]]  # Trim Coordinates Fwd of Fwd Web
    seg.append(box[box[:, 1] > np.mean(box[:, 1])] *
               chord)  # Upper Fwd Segment
    seg.append(box[box[:, 1] < np.mean(box[:, 1])] *
               chord)  # Lower Fwd Segment

    # Flap & Drag Inertia

    capInertia = 0
    capLength = 0

    for i in range(0, 2):
        l = np.sqrt(np.sum(np.diff(seg[i], axis=0)**2,
                           axis=1))  # Segment Lengths
        c = (seg[i][1::] + seg[i][0::-1]) / 2  # Segment Centroids

        capInertia += np.abs(np.sum(l * c[:, 1]**2))
        capLength += np.sum(l)

    # Shear Properties

    box = coord
    box = box[box[:, 0] <= fwdWeb[1]]
    z = box[box[:, 0] == fwdWeb[0], 1] * chord
    shearHeight = np.abs(z[0] - z[1])

    # Core Properties

    box = coord
    box = box[box[:, 0] >= fwdWeb[0]]
    box = box * chord
    coreArea = 0.5 * np.abs(
        np.dot(box[:, 0], np.roll(box[:, 1], 1)) -
        np.dot(box[:, 1], np.roll(box[:, 0], 1)))  # Shoelace Formula

    # Shear/Moment Calculations

    Vz = np.append(np.cumsum((F[0:-1] * np.diff(x))[::-1])[::-1],
                   0)  # Bending Moment
    Mx = np.append(np.cumsum((Vz[0:-1] * np.diff(x))[::-1])[::-1],
                   0)  # Torsion Moment
    My = np.append(np.cumsum((Q[0:-1] * np.diff(x))[::-1])[::-1],
                   0)  # Drag Moment

    #-------------------------------------------------------------------------------
    # Mass Calculation
    #-------------------------------------------------------------------------------

    while error > tolerance:
        CF = (SF * omega**2 * np.append(
            np.cumsum((m[0:-1] * np.diff(x) * x[0:-1])[::-1])[::-1], 0)
              )  # Centripetal Force

        # Calculate Skin Weight Based on Torsion

        tTorsion = My / (2 * BiCF_USS * enclosedArea)  # Torsion Skin Thickness
        tTorsion = np.maximum(tTorsion,
                              BiCF_MGT * np.ones(N))  # Gage Constraint
        mTorsion = tTorsion * skinLength * BiCF_DEN  # Torsion Mass

        # Calculate Flap Mass Based on Bending

        tFlap = CF/(capLength*UniCF_UTS) +   \
            Mx*np.amax(np.abs(box[:,1]))/(capInertia*UniCF_UTS)
        mFlap = tFlap * capLength * UniCF_DEN
        mGlue = EPOXY_MGT * EPOXY_DEN * capLength * np.ones(N)

        # Calculate Web Mass Based on Shear

        tShear = 1.5 * Vz / (BiCF_USS * shearHeight)
        tShear = np.maximum(tShear, BiCF_MGT * np.ones(N))
        mShear = tShear * shearHeight * BiCF_DEN

        # Paint Weight

        mPaint = skinLength * PAINT_MGT * PAINT_DEN * np.ones(N)

        # Core Mass

        mCore = coreArea * HCMB_DEN * np.ones(N)
        mGlue += EPOXY_MGT * EPOXY_DEN * skinLength * np.ones(N)

        # Leading Edge Protection

        box = coord * chord
        box = box[box[:, 0] < (0.1 * chord)]
        leLength = np.sum(np.sqrt(np.sum(np.diff(box, axis=0)**2, axis=1)))
        mLE = leLength * 420e-6 * NICK_DEN * np.ones(N)

        # Section Mass

        m = mTorsion + mCore + mFlap + mShear + mGlue + mPaint + mLE

        # Rib Weight

        mRib = (enclosedArea + skinLength * RIB_WID) * RIB_MGT * RIB_DEN

        # Root Fitting

        box = coord * chord
        rRoot = (np.amax(box[:, 1]) - np.amin(box[:, 1])) / 2
        t = np.amax(CF)/(2*np.pi*rRoot*ALUM_UTS) +    \
            np.amax(Mx)/(3*np.pi*rRoot**2*ALUM_UTS)
        mRoot = 2 * np.pi * rRoot * t * rootLength * ALUM_DEN

        # Total Weight

        mass = nBlades * (np.sum(m[0:-1] * np.diff(x)) + 2 * mRib + mRoot)
        error = np.abs(mass - massOld)
        massOld = mass

    mass = mass * grace

    return mass
Example #2
0
def wing(wing,
         config,
         max_thrust,
         num_analysis_points=10,
         safety_factor=1.5,
         max_g_load=3.8,
         moment_to_lift_ratio=0.02,
         lift_to_drag_ratio=7,
         forward_web_locations=[0.25, 0.35],
         rear_web_locations=[0.65, 0.75],
         shear_center_location=0.25,
         margin_factor=1.2):
    """weight = SUAVE.Methods.Weights.Buildups.Common.wing(
            wing,
            config,
            maxThrust,
            numAnalysisPoints,
            safety_factor,
            max_g_load,
            moment_to_lift_ratio,
            lift_to_drag_ratio,
            forward_web_locations = [0.25, 0.35],
            rear_web_locations = [0.65, 0.75],
            shear_center = 0.25,
            margin_factor = 1.2)

        Calculates the structural mass of a wing for an eVTOL vehicle based on
        assumption of NACA airfoil wing, an assumed L/D, cm/cl, and structural
        geometry.

        Intended for use with the following SUAVE vehicle types, but may be used
        elsewhere:

            Electric Multicopter
            Electric Vectored_Thrust
            Electric Stopped Rotor

        Originally written as part of an AA 290 project intended for trade study
        of the above vehicle types plus an electric Multicopter.
        
        Sources:
        Project Vahana Conceptual Trade Study

        Inputs:

            wing                    SUAVE Wing Data Structure
            config                  SUAVE Confiug Data Structure
            maxThrust               Maximum Thrust                      [N]
            numAnalysisPoints       Analysis Points for Sizing          [Unitless]
            safety_factor           Design Saftey Factor                [Unitless]
            max_g_load              Maximum Accelerative Load           [Unitless]
            moment_to_lift_ratio    Coeff. of Moment to Coeff. of Lift  [Unitless]
            lift_to_drag_ratio      Coeff. of Lift to Coeff. of Drag    [Unitess]
            forward_web_locations   Location of Forward Spar Webbing    [m]
            rear_web_locations      Location of Rear Spar Webbing       [m]
            shear_center            Location of Shear Center            [m]
            margin_factor           Allowable Extra Mass Fraction       [Unitless]

        Outputs:

            weight:                 Wing Mass                           [kg]
    """

    #-------------------------------------------------------------------------------
    # Unpack Inputs
    #-------------------------------------------------------------------------------

    MTOW = config.mass_properties.max_takeoff
    wingspan = wing.spans.projected
    chord = wing.chords.mean_aerodynamic,
    thicknessToChord = wing.thickness_to_chord,
    wingletFraction = wing.winglet_fraction,
    wingArea = wing.areas.reference

    totalWingArea = 0
    for w in config.wings:
        totalWingArea += w.areas.reference
    liftFraction = wingArea / totalWingArea
    motor_spanwise_locations = wing.motor_spanwise_locations

    N = num_analysis_points  # Number of spanwise points
    SF = safety_factor  # Safety Factor
    G_max = max_g_load  # Maximum G's experienced during climb
    cmocl = moment_to_lift_ratio  # Ratio of cm to cl
    LoD = lift_to_drag_ratio  # L/D
    fwdWeb = cp.deepcopy(forward_web_locations)  # Locations of forward spars
    aftWeb = cp.deepcopy(rear_web_locations)  # Locations of aft spars
    xShear = shear_center_location  # Approximate shear center
    grace = margin_factor  # Grace factor for estimation

    nRibs = len(motor_spanwise_locations) + 2
    motor_spanwise_locations = np.multiply(motor_spanwise_locations,
                                           wingspan / 2)

    #-------------------------------------------------------------------------------
    # Unpack Material Properties
    #-------------------------------------------------------------------------------

    BiCF = Bidirectional_Carbon_Fiber()
    BiCF_MGT = BiCF.minimum_gage_thickness
    BiCF_DEN = BiCF.density
    BiCF_UTS = BiCF.ultimate_tensile_strength
    BiCF_USS = BiCF.ultimate_shear_strength
    BiCF_UBS = BiCF.ultimate_bearing_strength

    UniCF = Unidirectional_Carbon_Fiber()
    UniCF_MGT = UniCF.minimum_gage_thickness
    UniCF_DEN = UniCF.density
    UniCF_UTS = UniCF.ultimate_tensile_strength
    UniCF_USS = UniCF.ultimate_shear_strength

    HCMB = Carbon_Fiber_Honeycomb()
    HCMB_MGT = HCMB.minimum_gage_thickness
    HCMB_DEN = HCMB.density

    RIB = Aluminum_Rib()
    RIB_WID = RIB.minimum_width
    RIB_MGT = RIB.minimum_gage_thickness
    RIB_DEN = RIB.density

    ALUM = Aluminum()
    ALUM_DEN = ALUM.density
    ALUM_MGT = ALUM.minimum_gage_thickness
    ALUM_UTS = ALUM.ultimate_tensile_strength

    EPOXY = Epoxy()
    EPOXY_MGT = EPOXY.minimum_gage_thickness
    EPOXY_DEN = EPOXY.density

    PAINT = Paint()
    PAINT_MGT = PAINT.minimum_gage_thickness
    PAINT_DEN = PAINT.density

    #-------------------------------------------------------------------------------
    # Airfoil
    #-------------------------------------------------------------------------------

    NACA = np.multiply(5 * thicknessToChord,
                       [0.2969, -0.1260, -0.3516, 0.2843, -0.1015])
    coord = np.unique(fwdWeb + aftWeb +
                      np.linspace(0, 1, N).tolist())[:, np.newaxis]
    coordMAT = np.concatenate(
        (coord**0.5, coord, coord**2, coord**3, coord**4), axis=1)
    nacaMAT = coordMAT.dot(NACA)[:, np.newaxis]
    coord = np.concatenate((coord, nacaMAT), axis=1)
    coord = np.concatenate(
        (coord[-1:0:-1], coord.dot(np.array([[1., 0.], [0., -1.]]))), axis=0)
    coord[:, 0] = coord[:, 0] - xShear

    #-------------------------------------------------------------------------------
    # Beam Geometry
    #-------------------------------------------------------------------------------

    x = np.concatenate(
        (np.linspace(0, 1, N), np.linspace(1, 1 + wingletFraction[0], N)),
        axis=0)
    x = x * wingspan / 2
    x = np.sort(np.concatenate((x, motor_spanwise_locations), axis=0))
    dx = x[1] - x[0]
    N = np.size(x)
    fwdWeb[:] = [round(locFwd - xShear, 2) for locFwd in fwdWeb]
    aftWeb[:] = [round(locAft - xShear, 2) for locAft in aftWeb]

    #-------------------------------------------------------------------------------
    # Loads
    #-------------------------------------------------------------------------------

    L = (1 - (x / np.max(x))**2)**0.5  # Assumes Elliptic Lift Distribution
    L0 = 0.5 * G_max * MTOW * 9.8 * liftFraction * SF  # Total Design Lift Force
    L = L0 / np.sum(L[0:-1] * np.diff(x)) * L  # Net Lift Distribution

    T = L * chord[0] * cmocl  # Torsion Distribution
    D = L / LoD  # Drag Distribution

    #-------------------------------------------------------------------------------
    # Shear/Moments
    #-------------------------------------------------------------------------------

    Vx = np.append(np.cumsum((D[0:-1] * np.diff(x))[::-1])[::-1],
                   0)  # Drag Shear
    Vz = np.append(np.cumsum((L[0:-1] * np.diff(x))[::-1])[::-1],
                   0)  # Lift Shear
    Vt = 0 * Vz  # Initialize Thrust Shear

    # Calculate shear due to thrust by adding thrust from each motor to each
    # analysis point that's closer to the wing root than the motor. Accomplished
    # by indexing Vt according to a boolean mask of the design points that area
    # less than or aligned with the motor location under consideration in an
    # iterative loop

    for i in range(np.size(motor_spanwise_locations)):
        Vt[x <= motor_spanwise_locations[i]] = Vt[
            x <= motor_spanwise_locations[i]] + max_thrust

    Mx = np.append(np.cumsum((Vz[0:-1] * np.diff(x))[::-1])[::-1],
                   0)  # Bending Moment
    My = np.append(np.cumsum((T[0:-1] * np.diff(x))[::-1])[::-1],
                   0)  # Torsion Moment
    Mz = np.append(np.cumsum((Vx[0:-1] * np.diff(x))[::-1])[::-1],
                   0)  # Drag Moment
    Mt = np.append(np.cumsum((Vt[0:-1] * np.diff(x))[::-1])[::-1],
                   0)  # Thrust Moment
    Mz = np.max((Mz, Mt))  # Worst Case of Drag vs. Thrust Moment

    #-------------------------------------------------------------------------------
    # General Structural Properties
    #-------------------------------------------------------------------------------

    seg = []  # LIST of Structural Segments

    # Torsion

    box = coord  # Box Initally Matches Airfoil
    box = box[box[:, 0] <= aftWeb[1]]  # Inlcude Only Parts Fwd of Aftmost Spar
    box = box[box[:, 0] >= fwdWeb[0]]  # Include Only Parts Aft of Fwdmost Spar
    box = box * chord[0]  # Scale by Chord Length

    # Use Shoelace Formula to calculate box area

    torsionArea = 0.5 * np.abs(
        np.dot(box[:, 0], np.roll(box[:, 1], 1)) -
        np.dot(box[:, 1], np.roll(box[:, 0], 1)))

    torsionLength = np.sum(np.sqrt(np.sum(np.diff(box, axis=0)**2, axis=1)))

    # Bending

    box = coord  # Box Initally Matches Airfoil
    box = box[box[:, 0] <= fwdWeb[1]]  # Inlcude Only Parts Fwd of Aft Fwd Spar
    box = box[box[:, 0] >= fwdWeb[0]]  # Include Only Parts Aft of Fwdmost Spar
    seg.append(box[box[:, 1] > np.mean(box[:, 1])] *
               chord[0])  # Upper Fwd Segment
    seg.append(box[box[:, 1] < np.mean(box[:, 1])] *
               chord[0])  # Lower Fwd Segment

    # Drag

    box = coord  # Box Initally Matches Airfoil
    box = box[box[:, 0] <= aftWeb[1]]  # Inlcude Only Parts Fwd of Aftmost Spar
    box = box[box[:, 0] >= aftWeb[0]]  # Include Only Parts Aft of Fwd Aft Spar
    seg.append(box[box[:, 1] > np.mean(box[:, 1])] *
               chord[0])  # Upper Aft Segment
    seg.append(box[box[:, 1] < np.mean(box[:, 1])] *
               chord[0])  # Lower Aft Segment

    # Bending/Drag Inertia

    flapInertia = 0
    flapLength = 0
    dragInertia = 0
    dragLength = 0

    for i in range(0, 4):
        l = np.sqrt(np.sum(np.diff(seg[i], axis=0)**2,
                           axis=1))  # Segment lengths
        c = (seg[i][1::] + seg[i][0:-1]) / 2  # Segment centroids

        if i < 2:
            flapInertia += np.abs(np.sum(
                l * c[:, 1]**2))  # Bending Inertia per Unit Thickness
            flapLength += np.sum(l)
        else:
            dragInertia += np.abs(np.sum(
                l * c[:, 0]**2))  # Drag Inertia per Unit Thickness
            dragLength += np.sum(l)

    # Shear

    box = coord  # Box Initially Matches Airfoil
    box = box[box[:, 0] <= fwdWeb[1]]  # Include Only Parts Fwd of Aft Fwd Spar
    z = np.zeros(2)
    z[0] = np.interp(fwdWeb[0], box[box[:, 1] > 0, 0],
                     box[box[:, 1] > 0,
                         1]) * chord[0]  # Upper Surface of Box at Fwdmost Spar
    z[1] = np.interp(fwdWeb[0], box[box[:, 1] < 0, 0],
                     box[box[:, 1] < 0,
                         1]) * chord[0]  # Lower Surface of Box at Fwdmost Spar
    h = np.abs(z[0] - z[1])  # Height of Box at Fwdmost Spar

    # Skin

    box = coord * chord  # Box Initially is Airfoil Scaled by Chord
    skinLength = np.sum(np.sqrt(np.sum(np.diff(box, axis=0)**2, axis=1)))
    A = 0.5 * np.abs(
        np.dot(box[:, 0], np.roll(box[:, 1], 1)) - np.dot(
            box[:, 1], np.roll(box[:, 0], 1)))  # Box Area via Shoelace Formula

    #---------------------------------------------------------------------------
    # Structural Calculations
    #---------------------------------------------------------------------------

    # Calculate Skin Weight Based on Torsion

    tTorsion = My * dx / (2 * BiCF_USS * torsionArea)  # Torsion Skin Thickness
    tTorsion = np.maximum(tTorsion, BiCF_MGT * np.ones(N))  # Gage Constraint
    mTorsion = tTorsion * torsionLength * BiCF_DEN  # Torsion Mass
    mCore = HCMB_MGT * torsionLength * HCMB_DEN * np.ones(N)  # Core Mass
    mGlue = EPOXY_MGT * EPOXY_DEN * torsionLength * np.ones(N)  # Epoxy Mass

    # Calculate Flap Mass Based on Bending

    tFlap = Mx * np.max(seg[0][:, 1]) / (flapInertia * UniCF_UTS
                                         )  # Bending Flap Thickness
    mFlap = tFlap * flapLength * UniCF_DEN  # Bending Flap Mass
    mGlue += EPOXY_MGT * EPOXY_DEN * flapLength * np.ones(
        N)  # Updated Epoxy Mass

    # Calculate Drag Flap Mass

    tDrag = Mz * np.max(seg[2][:, 0]) / (dragInertia * UniCF_UTS
                                         )  # Drag Flap Thickness
    mDrag = tDrag * dragLength * UniCF_DEN  # Drag Flap Mass
    mGlue += EPOXY_MGT * EPOXY_DEN * dragLength * np.ones(
        N)  # Updated Epoxy Mass

    # Calculate Shear Spar Mass

    tShear = 1.5 * Vz / (BiCF_USS * h)  # Shear Spar Thickness
    tShear = np.maximum(tShear, BiCF_MGT * np.ones(N))  # Gage constraint
    mShear = tShear * h * BiCF_DEN  # Shear Spar Mass

    # Paint

    mPaint = skinLength * PAINT_MGT * PAINT_DEN * np.ones(N)  # Paint Mass

    # Section Mass Total

    m = mTorsion + mCore + mFlap + mDrag + mShear + mGlue + mPaint

    # Rib Mass

    mRib = (A + skinLength * RIB_WID) * RIB_MGT * RIB_DEN

    # Total Mass

    mass = 2 * (sum(m[0:-1] * np.diff(x)) + nRibs * mRib) * grace

    return mass