コード例 #1
0
def fuselage(config,
             maximum_g_load=3.8,
             landing_impact_factor=3.5,
             safety_factor=1.5):
    """ weight = SUAVE.Methods.Weights.Buildups.Common.fuselage(
            config,
            max_g_load = 3.8,
            landing_impact_factor = 3.5,
            safety_factor = 1.5)

        Calculates the structural mass of a fuselage for an eVTOL vehicle,
        assuming a structural keel taking bending an torsional loads.
        
        Assumptions:
        Assumes an elliptical fuselage. 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.
        
        Sources:
        Project Vahana Conceptual Trade Study

        Inputs:

            config                      SUAVE Vehicle Configuration
            max_g_load                  Max Accelerative Load During Flight [Unitless]
            landing_impact_factor       Maximum Load Multiplier on Landing  [Unitless]

        Outputs:

            weight:                 Estimated Fuselage Mass             [kg]
        
        Properties Used:
        Material Properties of Imported SUAVE Solids
    """

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

    fLength = config.fuselages.fuselage.lengths.total
    fWidth = config.fuselages.fuselage.width
    fHeight = config.fuselages.fuselage.heights.maximum
    maxSpan = config.wings['main_wing'].spans.projected
    MTOW = config.mass_properties.max_takeoff
    G_max = maximum_g_load
    LIF = landing_impact_factor
    SF = safety_factor

    #-------------------------------------------------------------------------------
    # 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

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

    ACRYL = Acrylic()
    ACRYL_MGT = ACRYL.minimum_gage_thickness
    ACRYL_DEN = ACRYL.density

    STEEL = Steel()
    STEEL_USS = STEEL.ultimate_shear_strength

    # Calculate Skin Weight Per Unit Area (arealWeight) based on material
    # properties. In this instance we assume the use of
    # Bi-directional Carbon Fiber, a Honeycomb Core, and Paint:

    arealWeight = (BiCF_MGT * BiCF_DEN + HCMB_MGT * HCMB_DEN +
                   PAINT_MGT * PAINT_DEN)

    # Calculate fuselage area (using assumption of ellipsoid), and weight:

    S_wet = 4 * np.pi * (((fLength * fWidth / 4)**1.6 +
                          (fLength * fHeight / 4)**1.6 +
                          (fWidth * fHeight / 4)**1.6) / 3)**(1 / 1.6)
    skinMass = S_wet * arealWeight

    # Calculate the mass of a structural bulkhead

    bulkheadMass = 3 * np.pi * fHeight * fWidth / 4 * arealWeight

    # Calculate the mass of a canopy, assuming Acrylic:

    canopyMass = S_wet / 8 * ACRYL_MGT * ACRYL_DEN

    # Calculate keel mass needed to carry lifting moment, assuming
    # Uni-directional Carbon Fiber used to carry load

    L_max = G_max * MTOW * 9.8 * SF  # Max Lifting Load
    M_lift = L_max * fLength / 2.  # Max Moment Due to Lift
    beamWidth = fWidth / 3.  # Allowable Keel Width
    beamHeight = fHeight / 10.  # Allowable Keel Height

    beamArea = M_lift * beamHeight / (4 * UniCF_UTS * (beamHeight / 2)**2)
    massKeel = beamArea * fLength * UniCF_DEN

    # Calculate keel mass needed to carry wing bending moment, assuming
    # thin walled Bi-directional Carbon Fiber used to carry load

    M_bend = L_max / 2 * maxSpan / 2  # Max Bending Moment
    beamArea = beamHeight * beamWidth  # Enclosed Beam Area
    beamThk = 0.5 * M_bend / (BiCF_USS * beamArea)  # Beam Thickness
    massKeel += 2 * (beamHeight + beamWidth) * beamThk * BiCF_DEN

    # Calculate keel mass needed to carry landing impact load assuming
    # Steel bolts, and Bi-directional Carbon Fiber laminate pads used to carry
    # loads in a side landing

    F_landing = SF * MTOW * 9.8 * LIF * 0.6403  # Side Landing Force
    boltArea = F_landing / STEEL_USS  # Required Bolt Area
    boltDiam = 2 * np.sqrt(boltArea / np.pi)  # Bolt Diameter
    lamThk = F_landing / (boltDiam * BiCF_UBS)  # Laminate Thickness
    lamVol = (np.pi * (20 * lamThk)**2) * (lamThk / 3)  # Laminate Pad volume
    massKeel += 4 * lamVol * BiCF_DEN  # Mass of 4 Pads

    # Calculate total mass as the sum of skin mass, bulkhead mass, canopy pass,
    # and keel mass. Called weight by SUAVE convention

    weight = skinMass + bulkheadMass + canopyMass + massKeel

    return weight
コード例 #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
コード例 #3
0
ファイル: prop.py プロジェクト: themrdjj/SUAVE
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
コード例 #4
0
def fuselage(config,
             maximum_g_load=3.8,
             landing_impact_factor=3.5,
             safety_factor=1.5):
    """ Calculates the structural mass of a fuselage for an eVTOL vehicle,
        assuming a structural keel taking bending an torsional loads.
        
        Assumptions:
        Assumes an elliptical fuselage. 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.

        If vehicle model does not have material properties assigned, appropriate
        assumptions are made based on SUAVE's Solids Attributes library.
        
        Sources:
        Project Vahana Conceptual Trade Study

        Inputs:

            config                      SUAVE Vehicle Configuration
            max_g_load                  Max Accelerative Load During Flight [Unitless]
            landing_impact_factor       Maximum Load Multiplier on Landing  [Unitless]

        Outputs:

            weight:                 Estimated Fuselage Mass             [kg]
        
        Properties Used:
        Material Properties of Imported SUAVE Solids
    """

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

    fuse = config.fuselages.fuselage
    fLength = fuse.lengths.total
    fWidth = fuse.width
    fHeight = fuse.heights.maximum
    maxSpan = config.wings["main_wing"].spans.projected
    MTOW = config.mass_properties.max_takeoff
    G_max = maximum_g_load
    LIF = landing_impact_factor
    SF = safety_factor

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

    try:
        rbmMat = fuse.keel_materials.root_bending_moment_carrier
    except AttributeError:
        rbmMat = Unidirectional_Carbon_Fiber()
    rbmDen = rbmMat.density
    rbmUTS = rbmMat.ultimate_tensile_strength

    try:
        shearMat = fuse.keel_materials.shear_carrier
    except AttributeError:
        shearMat = Bidirectional_Carbon_Fiber()
    shearDen = shearMat.density
    shearUSS = shearMat.ultimate_shear_strength

    try:
        bearingMat = fuse.keel_materials.bearing_carrier
    except AttributeError:
        bearingMat = Bidirectional_Carbon_Fiber()
    bearingDen = bearingMat.density
    bearingUBS = bearingMat.ultimate_bearing_strength

    try:
        boltMat = fuse.materials.bolt_materials.landing_pad_bolt
    except AttributeError:
        boltMat = Steel()
    boltUSS = boltMat.ultimate_shear_strength

    # Calculate Skin & Canopy Weight Per Unit Area (arealWeight) based on material

    try:
        skinArealWeight = np.sum([(mat.minimum_gage_thickness * mat.density)
                                  for mat in fuse.skin_materials])
    except AttributeError:
        skinArealWeight = 1.2995  # Stack of bidirectional CFRP, Honeycomb Core, Paint

    try:
        canopyArealWeight = np.sum([(mat.minimum_gage_thickness * mat.density)
                                    for mat in fuse.canopy_materials])
    except AttributeError:
        canopyArealWeight = 3.7465  # Acrylic

    # Calculate fuselage area (using assumption of ellipsoid), and weight:

    S_wet = 4 * np.pi * (((fLength * fWidth / 4)**1.6 +
                          (fLength * fHeight / 4)**1.6 +
                          (fWidth * fHeight / 4)**1.6) / 3)**(1 / 1.6)
    skinMass = S_wet * skinArealWeight

    # Calculate the mass of a structural bulkhead

    bulkheadMass = 3 * np.pi * fHeight * fWidth / 4 * skinArealWeight

    # Calculate the mass of a canopy

    canopyMass = S_wet / 8 * canopyArealWeight

    # Calculate keel mass needed to carry lifting moment

    L_max = G_max * MTOW * 9.8 * SF  # Max Lifting Load
    M_lift = L_max * fLength / 2.  # Max Moment Due to Lift
    beamWidth = fWidth / 3.  # Allowable Keel Width
    beamHeight = fHeight / 10.  # Allowable Keel Height

    beamArea = M_lift * beamHeight / (4 * rbmUTS * (beamHeight / 2)**2)
    massKeel = beamArea * fLength * rbmDen

    # Calculate keel mass needed to carry wing bending moment shear

    M_bend = L_max / 2 * maxSpan / 2  # Max Bending Moment
    beamArea = beamHeight * beamWidth  # Enclosed Beam Area
    beamThk = 0.5 * M_bend / (shearUSS * beamArea)  # Beam Thickness
    massKeel += 2 * (beamHeight + beamWidth) * beamThk * shearDen

    # Calculate keel mass needed to carry landing impact load assuming

    F_landing = SF * MTOW * 9.8 * LIF * 0.6403  # Side Landing Force
    boltArea = F_landing / boltUSS  # Required Bolt Area
    boltDiam = 2 * np.sqrt(boltArea / np.pi)  # Bolt Diameter
    lamThk = F_landing / (boltDiam * bearingUBS)  # Laminate Thickness
    lamVol = (np.pi * (20 * lamThk)**2) * (lamThk / 3)  # Laminate Pad volume
    massKeel += 4 * lamVol * bearingDen  # Mass of 4 Pads

    # Calculate total mass as the sum of skin mass, bulkhead mass, canopy pass,
    # and keel mass. Called weight by SUAVE convention

    weight = skinMass + bulkheadMass + canopyMass + massKeel

    return weight