def run_tests(cd0 = 0.0221, e = 0.825):
    """
    Run all test cases to compare drag polar model against CAFE results.
    """
    sum_sq = 0
    wt_value_tot = 0
    wing_area = 110
    prop = PM.Prop('7666-4RV')
    for n, test in enumerate(level_test_cases):
        tas = test[0]
        dalt = test[1]
        wt = test[2]
        rpm = test[3]
        mp = test[4]
        wt_value = test[5]
    
        eas = A.tas2eas(tas, dalt, speed_units = 'mph')
        tas_fts = U.speed_conv(tas, from_units = 'mph', to_units = 'ft/s')
        cl = FT.eas2cl(eas, wt, wing_area, speed_units = 'mph')
        cd = FT.cl2cd_test(cl, cd0, e, flap = 0)
        drag = FT.cd2drag(cd, eas, wing_area, speed_units = 'mph')
        
        drag_power = drag * tas_fts / 550.
        power = IO.pwr(rpm, mp, dalt)
        prop_eff = PM.prop_eff(prop, power, rpm, tas, dalt, speed_units = 'mph')
        thrust_power = power * prop_eff
        excess_power = thrust_power - drag_power
        
        print 'Case', n, 'Altitude =', dalt, 'TAS =', tas, 'EAS =', eas, 'Excess power =', excess_power
        
        sum_sq += wt_value * excess_power ** 2
        wt_value_tot += wt_value
        
    print 'Average sum of squares of excess power =', \
        (sum_sq / wt_value_tot) ** 0.5
def cafe_speed():
    """
    Check the calculated speeds against the data from the CAFE tests for the RV-8A
    """
    prop = PM.Prop('7666-4RV')
    for n, test in enumerate(level_test_cases):
        tas = test[0]
        dalt = test[1]
        wt = test[2]
        rpm = test[3]
        mp = test[4]
        wt_value = test[5]
    
        eas = A.tas2eas(tas, dalt, speed_units = 'mph')
        calc_tas = speed(prop, dalt, wt, IO.pwr(rpm, mp, dalt), rpm, \
            speed_units = 'mph')
        print 'Actual TAS =', tas, 'Calc TAS =', calc_tas
Beispiel #3
0
def cafe_speed():
    """
    Check the calculated speeds against the data from the CAFE tests for the RV-8A
    """
    prop = PM.Prop('7666-4RV')
    for n, test in enumerate(level_test_cases):
        tas = test[0]
        dalt = test[1]
        wt = test[2]
        rpm = test[3]
        mp = test[4]
        wt_value = test[5]

        eas = A.tas2eas(tas, dalt, speed_units='mph')
        calc_tas = speed(prop, dalt, wt, IO.pwr(rpm, mp, dalt), rpm, \
            speed_units = 'mph')
        print('Actual TAS =', tas, 'Calc TAS =', calc_tas)
Beispiel #4
0
def p(tas, dalt, wt, rpm, mp, prop):
    """
    test function for RV-8A drag, to compare against CAFE foundation level
    flt data.
    
    prop is a prop_map.Prop instance.
    """

    eas = A.tas2eas(tas, dalt, speed_units='mph')
    #   tas = A.cas2tas(cas, dalt, speed_units = 'mph')
    tas_fts = U.speed_conv(tas, from_units='mph', to_units='ft/s')
    drag = FT.eas2drag(eas, wt, 110, rv='8a', speed_units='mph')
    drag_power = drag * tas_fts / 550.
    power = IO.pwr(rpm, mp, dalt)
    prop_eff = PM.prop_eff(prop, power, rpm, tas, dalt, speed_units='mph')
    thrust_power = power * prop_eff
    excess_power = thrust_power - drag_power
    return excess_power
def p(tas, dalt, wt, rpm, mp, prop):
    """
    test function for RV-8A drag, to compare against CAFE foundation level
    flt data.
    
    prop is a prop_map.Prop instance.
    """
    

    eas = A.tas2eas(tas, dalt, speed_units = 'mph')
#   tas = A.cas2tas(cas, dalt, speed_units = 'mph')
    tas_fts = U.speed_conv(tas, from_units = 'mph', to_units = 'ft/s')
    drag = FT.eas2drag(eas, wt, 110, rv = '8a', speed_units = 'mph')
    drag_power = drag * tas_fts / 550.
    power = IO.pwr(rpm, mp, dalt)
    prop_eff = PM.prop_eff(prop, power, rpm, tas, dalt, speed_units = 'mph')
    thrust_power = power * prop_eff
    excess_power = thrust_power - drag_power
    return excess_power
Beispiel #6
0
def tas2cl(
    tas,
    altitude,
    weight,
    wing_area,
    temperature='std',
    load_factor=1,
    speed_units=default_speed_units,
    alt_units=default_alt_units,
    temp_units=default_temp_units,
    weight_units=default_weight_units,
    area_units=default_area_units,
):
    """
    Returns the coefficient of lift, given true airspeed, altitude, weight, 
    and wing area.  
    
    Temperature and load factor are optional inputs.  The temperature, if 
    not provided, defaults to the standard temperature for the altitude.  
    The load factor, if not provided, defaults to 1.
    """

    eas = A.tas2eas(
        tas,
        altitude,
        temperature,
        speed_units,
        alt_units,
        temp_units,
    )

    Cl = eas2cl(
        eas,
        weight,
        wing_area,
        load_factor,
        speed_units,
        weight_units,
        area_units,
    )

    return Cl
Beispiel #7
0
def tas2cl(
    tas,
    altitude,
    weight,
    wing_area,
    temperature='std',
    load_factor=1,
    speed_units=default_speed_units,
    alt_units=default_alt_units,
    temp_units=default_temp_units,
    weight_units=default_weight_units,
    area_units=default_area_units,
    ):
    """
    Returns the coefficient of lift, given true airspeed, altitude, weight, 
    and wing area.  
    
    Temperature and load factor are optional inputs.  The temperature, if 
    not provided, defaults to the standard temperature for the altitude.  
    The load factor, if not provided, defaults to 1.
    """

    eas = A.tas2eas(
        tas,
        altitude,
        temperature,
        speed_units,
        alt_units,
        temp_units,
        )

    Cl = eas2cl(
        eas,
        weight,
        wing_area,
        load_factor,
        speed_units,
        weight_units,
        area_units,
        )

    return Cl
def alt2FP_speed(engine, prop, blade_angle, alt, weight = 1800, temp = 'std', \
    temp_units = 'C', rv = '8', wing_area = 110, alt_units='ft', speed_units = 'kt' , \
    MP_loss = 1.322, ram = 0.5, pwr_factor=1, mixture='pwr', MP='WOT', wheel_pants=1):
    """
    Returns the predicted speed at full throttle for aircraft with fixed pitch prop.
    
    The MP_loss is the MP lost in the induction tract at full throttle at 2700
    rpm at MSL.  The default value is from the Lycoming power charts.
    The ram is the percentage of available ram recovery pressure that is
    achieved in the MP.
    """
    
    tas_low = 80
    tas_high = 250
    pwr_tolerance = .1
    
    while 1:
        tas_guess = (tas_low + tas_high) / 2.
        tas_guess_fts = U.speed_conv(tas_guess, from_units = speed_units, to_units = 'ft/s')
        rpm = tas2rpm(tas_guess, engine, prop, blade_angle, alt, temp=temp, alt_units=alt_units, temp_units=temp_units, speed_units=speed_units, MP=MP)
        if MP == 'WOT':
            MP = MP_pred(tas_guess, alt, rpm, rpm_base = 2700., MP_loss = MP_loss, ram = ram, temp=temp)
        bhp = engine.pwr(rpm, MP, alt, temp=temp, alt_units=alt_units, temp_units=temp_units)
        prop_eff = PM.prop_eff(prop, bhp, rpm, tas_guess, alt, temp = temp, temp_units = temp_units, speed_units = speed_units)
        power_avail = bhp * prop_eff
        eas_guess = A.tas2eas(tas_guess, alt, temp)
        drag = FT.eas2drag(eas_guess, weight, wing_area, rv = rv, flap = 0, speed_units = speed_units, wheel_pants = wheel_pants)
        power_req = tas_guess_fts * drag / 550.
        
        if M.fabs(power_avail - power_req) < pwr_tolerance:
#            print "MP = %.3f" % MP
#            print "Pwr = %.2f"% bhp 
#            print "Prop Efficiency = %.3f, and power available = %.1f thp" % (prop_eff, power_avail)
            return tas_guess, rpm, bhp
        
        if power_req > power_avail:
            tas_high = tas_guess
        else:
            tas_low = tas_guess
Beispiel #9
0
def run_tests(cd0=0.0221, e=0.825):
    """
    Run all test cases to compare drag polar model against CAFE results.
    """
    sum_sq = 0
    wt_value_tot = 0
    wing_area = 110
    prop = PM.Prop('7666-4RV')
    for n, test in enumerate(level_test_cases):
        tas = test[0]
        dalt = test[1]
        wt = test[2]
        rpm = test[3]
        mp = test[4]
        wt_value = test[5]

        eas = A.tas2eas(tas, dalt, speed_units='mph')
        tas_fts = U.speed_conv(tas, from_units='mph', to_units='ft/s')
        cl = FT.eas2cl(eas, wt, wing_area, speed_units='mph')
        cd = FT.cl2cd_test(cl, cd0, e, flap=0)
        drag = FT.cd2drag(cd, eas, wing_area, speed_units='mph')

        drag_power = drag * tas_fts / 550.
        power = IO.pwr(rpm, mp, dalt)
        prop_eff = PM.prop_eff(prop, power, rpm, tas, dalt, speed_units='mph')
        thrust_power = power * prop_eff
        excess_power = thrust_power - drag_power

        print('Case', n, 'Altitude =', dalt, 'TAS =', tas, 'EAS =', eas,
              'Excess power =', excess_power)

        sum_sq += wt_value * excess_power**2
        wt_value_tot += wt_value

    print('Average sum of squares of excess power =', \
        (sum_sq / wt_value_tot) ** 0.5)
def descent_data(prop, weight=1600., alt_max=20000., fuel_units='USG', \
    alt_interval=500., isa_dev=0, temp_units='C', rv='8',  wing_area=110., \
    tas=180., ROD=-500., angle='', speed_units='kt', rpm=2100., sfc=0.45, output='raw'):
    """
    Returns a table of descent performance vs altitude.

    The items in each row of the table are altitude, time, fuel burned and distance.
    Time is in units of minutes, rounded to the nearest half minute.
    Fuel units are selectable, with a default of USG.
    Distances are in nm.
    
    The output may be specified as raw, latex (a LaTeX table for the POH), or array.
    
    tas is the TAS in descent (overridden by the angle, if the angle is provided).
    angle is the flight path angle in degrees.
    """
    tas_fts = U.speed_conv(tas, speed_units, 'ft/s')

    if angle:
        ROD = tas_fts * 60 * M.sin(angle * M.pi / 180)
        
    rod_fts = ROD / 60

    tas = U.speed_conv(tas, speed_units, 'kt')
    
    alt = alt_max + alt_interval
    temp = SA.isa2temp(isa_dev, alt, temp_units=temp_units)
    time = 0
    fuel_used = 0
    dist = 0
    
    if output == 'raw':
        print S.center('Altitude', 10),
        print S.center('ROD', 10),
        print S.center('Time', 10),
        print S.center('Fuel Used', 10),
        print S.center('Dist', 10),
        print S.center('Speed', 10)
        
        print S.center('(ft)', 10),
        print S.center('(ft/mn)', 10),
        print S.center('(mn)', 10),
        f_units = '(' + fuel_units + ')'
        print S.center(f_units, 10),
        print S.center('(nm)', 10),
        print S.center('(KCAS)', 10)
        
        # # data for max altitude
        # print S.rjust(locale.format('%.0f', alt_max, True), 7),
        # print S.rjust(locale.format('%.0f', round(ROD / 10.) * 10, True), 10),
        # print S.rjust('%.1f' % (0), 10),
        # print S.rjust('%.1f' % (fuel_used), 10),
        # print S.rjust('%.1f' % (dist), 10),
        # print S.rjust('%3d' % (A.tas2cas(tas, alt_max, temp, temp_units=temp_units)), 10)

    # elif output == 'latex':
    #     # temp = 15 + isa_dev
    #     MSL_line = []
    #     MSL_line.append(str(locale.format('%.0f', weight, True)))
    #     MSL_line.append('0')
    #     MSL_line.append(str(locale.format('%.0f', temp)))
    #     MSL_line.append(str(locale.format('%.0f', A.tas2cas(tas, alt, temp, temp_units=temp_units))))
    #     MSL_line.append(str(locale.format('%.0f', round(ROD / 10.) * 10, True)))
    #     MSL_line.append('0')
    #     MSL_line.append(str(fuel_used))
    #     MSL_line.append(str(dist))
    #     
    #     print '&'.join(MSL_line) + '\\\\'
    #     print '\\hline'
    # elif output == 'array':
    #     # no header rows, but make blank array
    #     array = [[alt_max,0,0,0]]
        

    alts = []
    RODs = []
    times_temp = []
    CASs = []
    dists_temp = []
    fuel_useds_temp = []
    temps = []

    calc_alt = alt_max - alt_interval / 2.
    while alt > 0:
        temp = SA.isa2temp(isa_dev, alt, temp_units = temp_units)
        eas = A.tas2eas(tas, alt)
        drag = FT.eas2drag(eas, weight)
        pwr_level_flt = tas_fts * drag / 550
        thrust_power = pwr_level_flt + FT.Pexcess_vs_roc(weight, ROD)
        prop_eff = PM.prop_eff(prop, thrust_power, rpm, tas, alt, temp, temp_units=temp_units)
        calc_pwr = thrust_power / prop_eff        
        #fuel_flow = IO.pwr2ff(calc_pwr, rpm, ff_units = 'lb/hr')
        fuel_flow = calc_pwr * sfc 
        # print "Level flt pwr = %.1f, thrust power = %.1f, prop eff = %.3f, fuel flow = %.3f" % (pwr_level_flt, thrust_power, prop_eff, fuel_flow)
        slice_time = alt_interval / rod_fts * -1.
        slice_dist = tas_fts * slice_time
        slice_fuel = fuel_flow * slice_time / 3600
        fuel_used += slice_fuel
        fuel_out = (U.avgas_conv(fuel_used, from_units = 'lb', \
            to_units = fuel_units))
        weight -= slice_fuel
        alt -= alt_interval
        cas_out = A.tas2cas(tas, alt, temp, temp_units=temp_units)
        temp_out = SA.isa2temp(isa_dev, alt)
        time += slice_time / 60.
        dist += slice_dist / 6076.115

        alts.append(alt)
        CASs.append(cas_out)
        RODs.append(ROD)
        times_temp.append(time)
        fuel_useds_temp.append(fuel_out)
        dists_temp.append(dist)
        temps.append(temp_out)
        
        calc_alt += alt_interval
        
    alts.reverse()
    CASs.reverse()
    RODs.reverse()
    temps.reverse()
    
    times = []
    fuel_useds = []
    dists = []
    
    for n, time in enumerate(times_temp):
        times.append(times_temp[-1] - time)
        fuel_useds.append(fuel_useds_temp[-1] - fuel_useds_temp[n])
        dists.append(dists_temp[-1] - dists_temp[n])
        
    times.reverse()
    fuel_useds.reverse()
    dists.reverse()
    
    if output == 'raw':
        for n, alt in enumerate(alts):            
            print S.rjust(locale.format('%.0f', alt, True), 7),
            # calculate ROC at the displayed altitude
            print S.rjust(locale.format('%.0f', RODs[n], True), 10),
            print S.rjust('%.1f' % (times[n]), 10),
            print S.rjust('%.1f' % (fuel_useds[n]), 10),
            print S.rjust('%.1f' % (dists[n]), 10),
            print S.rjust('%3d' % (int(CASs[n])), 10)
    elif output == 'latex':
        for n, alt in enumerate(alts):                    
            line = []
            line.append(str(locale.format('%.0f', alt, True)))
            line.append(str(locale.format('%.0f', round(temps[n]))))
            line.append(str(locale.format('%.0f', CASs[n])))
            line.append(str(locale.format('%.0f', round(RODs[n] / 10.) * 10, True)))
            line.append(str(locale.format('%.0f', times[n])))
            line.append(str(locale.format('%.1f', fuel_useds[n])))
            line.append(str(locale.format('%.0f', dists[n])))
            print '&' + '&'.join(line) + '\\\\'
            print '\\hline'
    elif output == 'array':
        array = []
        for n, alt in enumerate(alts):
            array.append([alt, times[n], fuel_useds[n], dists[n]])
        return array
Beispiel #11
0
def descent_data(prop, weight=1600., alt_max=20000., fuel_units='USG', \
    alt_interval=500., isa_dev=0, temp_units='C', rv='8',  wing_area=110., \
    tas=180., ROD=-500., angle='', speed_units='kt', rpm=2100., sfc=0.45, output='raw'):
    """
    Returns a table of descent performance vs altitude.

    The items in each row of the table are altitude, time, fuel burned and distance.
    Time is in units of minutes, rounded to the nearest half minute.
    Fuel units are selectable, with a default of USG.
    Distances are in nm.
    
    The output may be specified as raw, latex (a LaTeX table for the POH), or array.
    
    tas is the TAS in descent (overridden by the angle, if the angle is provided).
    angle is the flight path angle in degrees.
    """
    tas_fts = U.speed_conv(tas, speed_units, 'ft/s')

    if angle:
        ROD = tas_fts * 60 * M.sin(angle * M.pi / 180)

    rod_fts = ROD / 60

    tas = U.speed_conv(tas, speed_units, 'kt')

    alt = alt_max + alt_interval
    temp = SA.isa2temp(isa_dev, alt, temp_units=temp_units)
    time = 0
    fuel_used = 0
    dist = 0

    if output == 'raw':
        print(S.center('Altitude', 10), end=' ')
        print(S.center('ROD', 10), end=' ')
        print(S.center('Time', 10), end=' ')
        print(S.center('Fuel Used', 10), end=' ')
        print(S.center('Dist', 10), end=' ')
        print(S.center('Speed', 10))

        print(S.center('(ft)', 10), end=' ')
        print(S.center('(ft/mn)', 10), end=' ')
        print(S.center('(mn)', 10), end=' ')
        f_units = '(' + fuel_units + ')'
        print(S.center(f_units, 10), end=' ')
        print(S.center('(nm)', 10), end=' ')
        print(S.center('(KCAS)', 10))

        # # data for max altitude
        # print S.rjust(locale.format('%.0f', alt_max, True), 7),
        # print S.rjust(locale.format('%.0f', round(ROD / 10.) * 10, True), 10),
        # print S.rjust('%.1f' % (0), 10),
        # print S.rjust('%.1f' % (fuel_used), 10),
        # print S.rjust('%.1f' % (dist), 10),
        # print S.rjust('%3d' % (A.tas2cas(tas, alt_max, temp, temp_units=temp_units)), 10)

    # elif output == 'latex':
    #     # temp = 15 + isa_dev
    #     MSL_line = []
    #     MSL_line.append(str(locale.format('%.0f', weight, True)))
    #     MSL_line.append('0')
    #     MSL_line.append(str(locale.format('%.0f', temp)))
    #     MSL_line.append(str(locale.format('%.0f', A.tas2cas(tas, alt, temp, temp_units=temp_units))))
    #     MSL_line.append(str(locale.format('%.0f', round(ROD / 10.) * 10, True)))
    #     MSL_line.append('0')
    #     MSL_line.append(str(fuel_used))
    #     MSL_line.append(str(dist))
    #
    #     print '&'.join(MSL_line) + '\\\\'
    #     print '\\hline'
    # elif output == 'array':
    #     # no header rows, but make blank array
    #     array = [[alt_max,0,0,0]]

    alts = []
    RODs = []
    times_temp = []
    CASs = []
    dists_temp = []
    fuel_useds_temp = []
    temps = []

    calc_alt = alt_max - alt_interval / 2.
    while alt > 0:
        temp = SA.isa2temp(isa_dev, alt, temp_units=temp_units)
        eas = A.tas2eas(tas, alt)
        drag = FT.eas2drag(eas, weight)
        pwr_level_flt = tas_fts * drag / 550
        thrust_power = pwr_level_flt + FT.Pexcess_vs_roc(weight, ROD)
        prop_eff = PM.prop_eff(prop,
                               thrust_power,
                               rpm,
                               tas,
                               alt,
                               temp,
                               temp_units=temp_units)
        calc_pwr = thrust_power / prop_eff
        #fuel_flow = IO.pwr2ff(calc_pwr, rpm, ff_units = 'lb/hr')
        fuel_flow = calc_pwr * sfc
        # print "Level flt pwr = %.1f, thrust power = %.1f, prop eff = %.3f, fuel flow = %.3f" % (pwr_level_flt, thrust_power, prop_eff, fuel_flow)
        slice_time = alt_interval / rod_fts * -1.
        slice_dist = tas_fts * slice_time
        slice_fuel = fuel_flow * slice_time / 3600
        fuel_used += slice_fuel
        fuel_out = (U.avgas_conv(fuel_used, from_units = 'lb', \
            to_units = fuel_units))
        weight -= slice_fuel
        alt -= alt_interval
        cas_out = A.tas2cas(tas, alt, temp, temp_units=temp_units)
        temp_out = SA.isa2temp(isa_dev, alt)
        time += slice_time / 60.
        dist += slice_dist / 6076.115

        alts.append(alt)
        CASs.append(cas_out)
        RODs.append(ROD)
        times_temp.append(time)
        fuel_useds_temp.append(fuel_out)
        dists_temp.append(dist)
        temps.append(temp_out)

        calc_alt += alt_interval

    alts.reverse()
    CASs.reverse()
    RODs.reverse()
    temps.reverse()

    times = []
    fuel_useds = []
    dists = []

    for n, time in enumerate(times_temp):
        times.append(times_temp[-1] - time)
        fuel_useds.append(fuel_useds_temp[-1] - fuel_useds_temp[n])
        dists.append(dists_temp[-1] - dists_temp[n])

    times.reverse()
    fuel_useds.reverse()
    dists.reverse()

    if output == 'raw':
        for n, alt in enumerate(alts):
            print(S.rjust(locale.format('%.0f', alt, True), 7), end=' ')
            # calculate ROC at the displayed altitude
            print(S.rjust(locale.format('%.0f', RODs[n], True), 10), end=' ')
            print(S.rjust('%.1f' % (times[n]), 10), end=' ')
            print(S.rjust('%.1f' % (fuel_useds[n]), 10), end=' ')
            print(S.rjust('%.1f' % (dists[n]), 10), end=' ')
            print(S.rjust('%3d' % (int(CASs[n])), 10))
    elif output == 'latex':
        for n, alt in enumerate(alts):
            line = []
            line.append(str(locale.format('%.0f', alt, True)))
            line.append(str(locale.format('%.0f', round(temps[n]))))
            line.append(str(locale.format('%.0f', CASs[n])))
            line.append(
                str(locale.format('%.0f',
                                  round(RODs[n] / 10.) * 10, True)))
            line.append(str(locale.format('%.0f', times[n])))
            line.append(str(locale.format('%.1f', fuel_useds[n])))
            line.append(str(locale.format('%.0f', dists[n])))
            print('&' + '&'.join(line) + '\\\\')
            print('\\hline')
    elif output == 'array':
        array = []
        for n, alt in enumerate(alts):
            array.append([alt, times[n], fuel_useds[n], dists[n]])
        return array
Beispiel #12
0
def alt2FP_speed(engine, prop, blade_angle, alt, weight = 1800, temp = 'std', \
    temp_units = 'C', rv = '8', wing_area = 110, alt_units='ft', speed_units = 'kt' , \
    MP_loss = 1.322, ram = 0.5, pwr_factor=1, mixture='pwr', MP='WOT', wheel_pants=1):
    """
    Returns the predicted speed at full throttle for aircraft with fixed pitch prop.
    
    The MP_loss is the MP lost in the induction tract at full throttle at 2700
    rpm at MSL.  The default value is from the Lycoming power charts.
    The ram is the percentage of available ram recovery pressure that is
    achieved in the MP.
    """

    tas_low = 80
    tas_high = 250
    pwr_tolerance = .1

    while 1:
        tas_guess = (tas_low + tas_high) / 2.
        tas_guess_fts = U.speed_conv(tas_guess,
                                     from_units=speed_units,
                                     to_units='ft/s')
        rpm = tas2rpm(tas_guess,
                      engine,
                      prop,
                      blade_angle,
                      alt,
                      temp=temp,
                      alt_units=alt_units,
                      temp_units=temp_units,
                      speed_units=speed_units,
                      MP=MP)
        if MP == 'WOT':
            MP = MP_pred(tas_guess,
                         alt,
                         rpm,
                         rpm_base=2700.,
                         MP_loss=MP_loss,
                         ram=ram,
                         temp=temp)
        bhp = engine.pwr(rpm,
                         MP,
                         alt,
                         temp=temp,
                         alt_units=alt_units,
                         temp_units=temp_units)
        prop_eff = PM.prop_eff(prop,
                               bhp,
                               rpm,
                               tas_guess,
                               alt,
                               temp=temp,
                               temp_units=temp_units,
                               speed_units=speed_units)
        power_avail = bhp * prop_eff
        eas_guess = A.tas2eas(tas_guess, alt, temp)
        drag = FT.eas2drag(eas_guess,
                           weight,
                           wing_area,
                           rv=rv,
                           flap=0,
                           speed_units=speed_units,
                           wheel_pants=wheel_pants)
        power_req = tas_guess_fts * drag / 550.

        if M.fabs(power_avail - power_req) < pwr_tolerance:
            #            print "MP = %.3f" % MP
            #            print "Pwr = %.2f"% bhp
            #            print "Prop Efficiency = %.3f, and power available = %.1f thp" % (prop_eff, power_avail)
            return tas_guess, rpm, bhp

        if power_req > power_avail:
            tas_high = tas_guess
        else:
            tas_low = tas_guess