Esempio n. 1
0
    def m0_fn(Ma):
        if Ma <= 0.9:
            return (2 * math.pi) / numpy.sqrt(1 - Ma**2)
        else:
            return (2 * math.pi) / numpy.sqrt(1 - 0.9**2)

    def Cd_fn(Cl):
        return 0.0095 + 0.0040 * (Cl - 0.2)**2

    nn = 101
    h = 0  # m
    v_inf = 70  # m/s
    is_SI = True
    atm = AtmData(v_inf, h, is_SI)
    k = 1.4
    R = 287
    atm.expand(k, R)

    numB = 3
    radius = 2 / 2
    RPM = 2400
    Cl = 0.4
    alp0 = numpy.radians(-2)
    prop = Propeller(radius, numB, RPM, CP=0, CT=0, CQ=0, Cl=Cl, alp0=alp0)

    T_req = 13000 / 8  # N (TOGW/(L/D))
    r_vec, c_vec, beta_vec, P_design, T_design, Q_design, eta_P, theta_vec = prop_design(
        atm, prop, T_req, m0_fn, Cd_fn)
    in_line = [0] * len(r_vec)
    plot_propeller_3D(r_vec, c_vec, beta_vec, prop, in_line)
Esempio n. 2
0
    T_design = [0] * nn
    Q_design = [0] * nn
    eta_P = [0] * nn
    for ii in range(0, nn):
        atm = AtmData(v_inf, h, is_SI)
        atm.expand(1.4, 287)
        prop = Propeller(radius,
                         numB,
                         RPM[ii],
                         eta_P,
                         CP=0,
                         CT=0,
                         CQ=0,
                         Cl=0.4)
        [_, _, _, P_design[ii], T_design[ii], Q_design[ii], eta_P[ii],
         _] = prop_design(atm, prop, T_req, m0_fn, Cd_fn)
    label = "$V_\infty$ = " + str(v_inf) + " (m/s)"
    plt.figure(1)
    plt.plot(RPM, Q_design, label=label)
    plt.figure(2)
    plt.plot(RPM, eta_P, label=label)
    plt.figure(3)
    plt.plot(RPM, P_design, label=label)
    # plt.figure(7)
    # plt.plot(RPM,T_design,label=label)

try:
    import formatfigures
    formatfigures.formatsubfigures()
    latex = True
except:
    RPM = 2400
    alp0 = numpy.radians(-2)
    dens = atm_check.dens
    CT = 0.0509
    T_req = CT * dens * (RPM / 60)**2 * (radius * 2)**4

    v_seq = numpy.arange(v_climb - 30 * 0.3048, v_climb + 126 * 0.3048, 2)
    prop_check = Propeller(radius,
                           numB,
                           RPM,
                           eta_P=0,
                           CP=0,
                           CT=0,
                           CQ=0,
                           Cl=0.4)
    r, prop_check.chord, prop_check.bet, P_design, T_design, Q_design, eta_P, prop_check.theta = prop_design(
        atm_check, prop_check, T_req, m0_fn, Cd_fn)

    ll = numpy.size(v_seq)

    J_var = numpy.zeros((ll, ))
    P_design_var = numpy.zeros((ll, ))
    T_design_var = numpy.zeros((ll, ))
    eta_P_var = numpy.zeros((ll, ))
    deta_P = numpy.zeros((ll, ))
    dT = numpy.zeros((ll, ))
    delta_bet = numpy.zeros((ll, ))
    RPM_fix = numpy.zeros((ll, ))
    for ii in range(ll):
        J_var[ii], P_design_var[ii], T_design_var[ii], Q_design_var[
            ii], eta_P_var[ii], deta_P[ii], dT[ii], delta_bet[ii], RPM_fix[
                ii] = prop_analysis_var_pitch(v_seq[ii], v_des, P_eng_data,
def STOL_power_req(m, dist_to, mot_distr, AtmData, Wing, Propeller_list):
    '''

     Provides calculation for the least required power of STOL aircraft

        Inputs:
            m: kg, airplane mass
            dist_to: m, target rakeoff distance
            motDistr: 1xn vector of motor power distribution
            Wing.S: m^2, wing area
            Wing.CL_max: max CL during takeoff
            AtmData.dens: air density (to get ratio compared to standard sea level atm.)
            Propeller_list: list of class "Propeller" for power calculation in FAR 25



        Outputs:
            outVec: if FAR 23, 1xn vector of motor power (hp)
                    if FAR 25, 1xn vector of motor thrust (N)

    Calls:
        {none}

    Notes:
        1. Function uses empirical expression provided in Roskam Part I
        2. FAR 23/25 based on aircraft mass included
        3. When integrating functions, mute the FAR23/25 fprintf sections
        4. Not well tested yet

    History:
            2.9.2021, created by X.Tang in Matlab
            2.14.2021, translated to Python by X.Tang
            2.14.2021, still has problem in FAR25 power with [1,1] distr, power way too high
   '''

    std_sl_dens_SI = 1.225          # kg/m^3
    std_sl_dens_Brit = 0.002377     # slug/ft^3
    g = 9.81        # m/s^2
    if AtmData.is_SI:
        sigma = AtmData.dens / std_sl_dens_SI
    else:
        sigma = AtmData.dens / std_sl_dens_Brit

    # FAR 23 / 25 check
    dist_to_Brit = dist_to * 3.28084    # meter to feet
    W = m * g                           # N
    W_Brit = W * 0.224809               # N to lbf
    S_Brit = Wing.area * 3.28084 ** 2   # m^2 to ft^2
    bdy = 12500 * 0.453592              # kg
    tol = 1e-3                          # tolerance for compare between double

    if m <= bdy:    # FAR 23
        a1 = 8.134
        a2 = 0.0149
        TOP23 = [0] * 2
        delta = a2 ** 2 - 4 * a1 * (-dist_to_Brit)

        # Check real
        if delta > 0:
            TOP23[0] = (-a2 + numpy.sqrt(delta)) / (2 * a1)
            TOP23[1] = (-a2 - numpy.sqrt(delta)) / (2 * a1)

            # Check positive num
            if TOP23[0] > 0 and TOP23[1] <= 0:
                TOP23_val = TOP23[0]
            elif TOP23[0] <= 0 and TOP23[1] > 0:
                TOP23_val = TOP23[1]
            elif TOP23[0] > 0 and TOP23[1] > 0:
                print("Error: TOP23 has two positive roots")
                return
            else:
                print("Error: TOp23 has two negative roots")
                return

        elif abs(delta) <= tol:
            TOP23_val = numpy.mean(TOP23)
            if TOP23_val <= 0:
                print("Error: TOP23 has one negative root")

        else:   # imaginary
            print("Error: No real root for TOP23")
            return

        # Calculation for power in hp
        PTO = (W_Brit ** 2 / S_Brit) / (TOP23_val * sigma * Wing.CL_max)

        # Power distribution
        if numpy.size(mot_distr) > 1:
            sum_distr = sum(mot_distr)
            power_vec = [0] * len(mot_distr)

            for i in range(len(mot_distr)):
                cur_distr = mot_distr[i] / sum_distr
                power_vec[i] = cur_distr * PTO

        else:
            power_vec = PTO

        # Can mute this following message
        print("Aircraft category: FAR 23, motor POWER vector output")
        return power_vec

    else:       # FAR 25
        a3 = 37.5
        TOP25 = S_Brit / a3
        TTO_lbf = (W_Brit ** 2 / S_Brit) / (TOP25 * sigma * Wing.CL_max)
        TTO = TTO_lbf * 4.44822     # from lbf to N

        print("Thrust is " + str(TTO) + " N")
        # Thrust distribution
        if numpy.size(mot_distr) > 1:
            sum_distr = sum(mot_distr)
            power_vec = [0] * len(mot_distr)
            for i in range(len(mot_distr)):
                cur_distr = mot_distr[i] / sum_distr
                cur_thrust = cur_distr * TTO

                # Calculating power using propeller design function
                _, _, _, power_vec[i], _, _, _, _ = prop_design(AtmData, Propeller_list, cur_thrust)
                power_vec[i] *= 0.00134102      # Converts to hp

        else:
            _, _, _, power_vec, _, _, _, _ = prop_design(AtmData, Propeller_list, TTO)
            power_vec *= 0.00134102     # Converts to hp

        # Can mute this following message
        print("Aircraft category: FAR 25, motor POWER vector output")
        return power_vec
# 3 Blades
numB = 3

# Design condition
T_req = 13000 / 8 * 1.2 * 0.601  # N (TOGW/(L/D))
Cl = 0.4
alp0 = np.radians(-2)

v_design = 30
atm = AtmData(v_design, 0, is_SI)
atm.expand(1.4, 287)

Design_RPM = 3000

prop = Propeller(radius, numB, Design_RPM, eta_P=0, CP=0, CT=0, CQ=0, Cl=Cl)
output = prop_design(atm, prop, T_req, m0_fn, Cd_fn, num=401)
r, prop.chord, prop.bet, P_design, T_design, Q_design, eta_P, prop.theta = output

# Point reduction and interpolation

# Adjustment
num_len = len(prop.bet)
beta_75_index = int(num_len * 0.75)
x = np.linspace(0, 1, num_len)
x_need = x[x >= 0.15]
c_need = prop.chord[x >= 0.15]
AF = 10**5 / 16 * np.trapz(c_need / diameter * x_need**3,
                           x_need)  # activity factor
CL_design = 4 * np.trapz(Cl * x_need**3, x_need)
print(
    '====================== Propeller Design Parameters ======================'
Esempio n. 6
0
def VTOL_power_req(m, g_factor, mot_distr, AtmData, Propeller_list):
    def m0_fn(Ma):
        if Ma <= 0.9:
            return (2 * math.pi) / numpy.sqrt(1 - Ma**2)
        else:
            return (2 * math.pi) / numpy.sqrt(1 - 0.9**2)

    def Cd_fn(Cl):
        return 0.0095 + 0.0040 * (Cl - 0.2)**2

    '''
    VTOL_power_req
    provides data and figures for required power of VTOL aircraft
    
    Input:
            m: kg, aircraft mass
            g_factor = loading factor (1 = hovering)
            mot_distr = Thrust distribution of motors (1xn)
                        Ex. Enter [1,1,1] for same distr. with 3 motors
                        Accepts single value
            AtmData = Class "AtmData" including atmospheric information, see Class130 file
            Propeller_list = list of Class "Propeller" including each propeller information, see Class130 file\
                             Please make sure the sequence are right!
    
    Outputs:
            powerVec = hp, list of power required by each motor
            
    Inner function:
        m0_fn: Kind of like lift curve slope function -- typical:
            m0_fn = @(Ma) (2 * pi ./ sqrt(1 - Ma.^2)) .* (Ma <= 0.9) + (2 * pi ./ ...
            sqrt(1 - 0.9^2)) .* (Ma > 0.9);
        Cd_fn: Blade sectional drag coefficient -- typical:
            Cd_fn = @(Cl) 0.0095 + 0.0040 * (Cl - 0.2).^2;
    
    Calls:
        prop_design_TVG: written by TGreenhill, translated and editted by XTang
    
    History:
        2.09.2021, created by XTang
        2.13.2021, translated by XTang
        2.13.2021, briefly debugged by XTang
    '''

    # Input size check
    if numpy.size(Propeller_list) != numpy.size(mot_distr):
        print("Error: Unequal number of propeller and motors")
        print("Number of propellers: " + str(numpy.size(Propeller_list)))
        print("Number of motors: " + str(numpy.size(mot_distr)))
        return

    g_accel = 9.81  # constant
    T_total = m * g_factor * g_accel

    if numpy.size(mot_distr) != 1:  # Having a list of motor distribution
        for item in mot_distr:
            if item < 0:
                print("Error: mot_distr entry values have to be at least 0")
                return

        sum_distr = sum(mot_distr)
        power_vec = [0] * len(mot_distr)
        eta_vec = [0] * len(mot_distr)

        for i in range(len(mot_distr)):
            cur_distr = mot_distr[i] / sum_distr
            cur_T = cur_distr * T_total
            [_, _, _, power_vec[i], _, _, eta_vec[i],
             _] = prop_design(AtmData, Propeller_list[i], cur_T)
            power_vec[i] *= 0.00134102  # Converts to hp
            return power_vec, eta_vec

    else:  # Having only one motor
        if mot_distr == 0:
            print("Cannot have 0 as value of mot_distr")
            return

        _, _, _, power_vec, _, _, eta_vec, _ = prop_design(
            AtmData, Propeller_list, T_total)
        power_vec *= 0.00134102  # Converts to hp
        return power_vec, eta_vec