def aoc(prop, altitude, eas, weight, power, rpm, temp = 'std', temp_units = 'C', \ rv = '8', wing_area = 110, speed_units = 'kt', flap = 0): """ Returns the climb or descent gradient. Runs with zero power at 1800 lb show best glide speed for RV-8 of: 98 kt at 1800 lb 86 kt at 1400 lb best angle of climb: 66 kt at 1800 lb """ tas = A.eas2tas(eas, altitude, temp=temp, speed_units=speed_units) tas_fts = U.speed_conv(tas, from_units=speed_units, to_units='ft/s') prop_eff = PM.prop_eff(prop, power, rpm, tas, altitude, temp = temp, \ temp_units = 'C', speed_units = speed_units) power_avail = power * prop_eff drag = FT.eas2drag(eas, weight, wing_area, rv = rv, flap = flap, \ speed_units = speed_units) power_req = tas_fts * drag / 550. excess_power = power_avail - power_req roc = excess_power * 550 / weight gradient = roc / tas_fts return gradient
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 aoc(prop, altitude, eas, weight, power, rpm, temp = 'std', temp_units = 'C', \ rv = '8', wing_area = 110, speed_units = 'kt', flap = 0): """ Returns the climb or descent gradient. Runs with zero power at 1800 lb show best glide speed for RV-8 of: 98 kt at 1800 lb 86 kt at 1400 lb best angle of climb: 66 kt at 1800 lb """ tas = A.eas2tas(eas, altitude, temp = temp, speed_units = speed_units) tas_fts = U.speed_conv(tas, from_units = speed_units, to_units = 'ft/s') prop_eff = PM.prop_eff(prop, power, rpm, tas, altitude, temp = temp, \ temp_units = 'C', speed_units = speed_units) power_avail = power * prop_eff drag = FT.eas2drag(eas, weight, wing_area, rv = rv, flap = flap, \ speed_units = speed_units) power_req = tas_fts * drag / 550. excess_power = power_avail - power_req roc = excess_power * 550 / weight gradient = roc / tas_fts return gradient
def _pwr_error(prop, eas_guess, altitude, weight, power, rpm, temp = 'std', \ temp_units = 'C', rv = '8', wing_area = 110, speed_units = 'kt', \ flap = 0, wheel_pants = 1): tas_guess = A.eas2tas(eas_guess, altitude, temp = temp, \ speed_units = speed_units, temp_units = temp_units) tas_guess_fts = U.speed_conv(tas_guess, from_units = speed_units, \ to_units = 'ft/s') prop_eff = PM.prop_eff(prop, power, rpm, tas_guess, altitude, temp = temp,\ temp_units = temp_units, speed_units = speed_units) power_avail = power * prop_eff drag = FT.eas2drag(eas_guess, weight, wing_area, rv = rv, flap = flap,\ speed_units = speed_units, wheel_pants = wheel_pants) power_req = tas_guess_fts * drag / 550. error = power_avail - power_req return error, tas_guess
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
def roc(prop, altitude, eas, weight, power, rpm, temp = 'std', temp_units = 'C', \ rv = '8', wing_area = 110, speed_units = 'kt', flap = 0, \ load_factor = 1, wheel_pants = 1, prop_factor=1): """ Returns the rate of climb or descent. """ # PM.read_data_files_csv(base_name = prop) tas = A.eas2tas(eas, altitude, temp = temp, speed_units = speed_units) tas_fts = U.speed_conv(tas, from_units = speed_units, to_units = 'ft/s') prop_eff = PM.prop_eff(prop, power, rpm, tas, altitude, temp = temp, \ temp_units = 'C', speed_units = speed_units) * prop_factor power_avail = power * prop_eff drag = FT.eas2drag(eas, weight, wing_area, rv = rv, flap = flap, \ speed_units = speed_units, load_factor = load_factor, wheel_pants = wheel_pants) power_req = tas_fts * drag / 550. excess_power = power_avail - power_req roc = excess_power * 33000 / weight return roc
def roc(prop, altitude, eas, weight, power, rpm, temp = 'std', temp_units = 'C', \ rv = '8', wing_area = 110, speed_units = 'kt', flap = 0, \ load_factor = 1, wheel_pants = 1, prop_factor=1): """ Returns the rate of climb or descent. """ # PM.read_data_files_csv(base_name = prop) tas = A.eas2tas(eas, altitude, temp=temp, speed_units=speed_units) tas_fts = U.speed_conv(tas, from_units=speed_units, to_units='ft/s') prop_eff = PM.prop_eff(prop, power, rpm, tas, altitude, temp = temp, \ temp_units = 'C', speed_units = speed_units) * prop_factor power_avail = power * prop_eff drag = FT.eas2drag(eas, weight, wing_area, rv = rv, flap = flap, \ speed_units = speed_units, load_factor = load_factor, wheel_pants = wheel_pants) power_req = tas_fts * drag / 550. excess_power = power_avail - power_req roc = excess_power * 33000 / weight return roc
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
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
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
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