def get_specific_heat_ratio_pressure_temperature(pressure, temperature): pressure = convert.pa_to_bar(pressure) # Convert to bar # Usually gets out of range because of the guessing algorithm if pressure < properties.pressure_min: pressure = properties.pressure_min if pressure > properties.pressure_max: pressure = properties.pressure_max if temperature < properties.temperature_min or temperature >= properties.temperature_max: raise ValueError('Temperature out of range:' + str(temperature)) # Get isothermal water Cv and Cp for given temperature (interpolate) data_low, data_high = dataContainer.get_data(temperature) fraction = (temperature % properties.temperature_step) / float(properties.temperature_step) cv = [data_low.cv[i] + fraction * (data_high.cv[i] - data_low.cv[i]) for i in range(len(data_low.cv))] cp = [data_low.cp[i] + fraction * (data_high.cp[i] - data_low.cp[i]) for i in range(len(data_low.cp))] # Cv and Cp are known for the exact temperature, calculate at exact pressure (interpolate) for i, p in enumerate(data_low.pressure): if p == pressure: return cp[i] / cv[i] if p > pressure: # We're in between two pressures that are listed, i and i-1 fraction = (pressure - data_low.pressure[i - 1]) / (data_low.pressure[i] - data_low.pressure[i - 1]) gamma_low = cp[i - 1] / cv[i - 1] gamma_high = cp[i] / cv[i] return gamma_low + fraction * (gamma_high - gamma_low)
def get_specific_heat_ratio(pressure, data): pressure = convert.pa_to_bar(pressure) # Convert to bar for i, p in enumerate(data.pressure): if p == pressure: return data.gamma[i] if p > pressure: # We're in between two pressures that are listed fraction = (pressure - data.pressure[i - 1]) / (data.pressure[i] - data.pressure[i - 1]) return data.gamma[i - 1] + fraction * (data.gamma[i] - data.gamma[i - 1])
def get_density_pressure_temperature(pressure, temperature): pressure = convert.pa_to_bar(pressure) # Convert to bar if pressure < properties.pressure_min or pressure > properties.pressure_max: raise ValueError('Pressure out of range:' + str(pressure)) if temperature < properties.temperature_min: temperature = properties.temperature_min if temperature > properties.temperature_max: temperature = properties.temperature_max - 1 # Get enthalpy for given temperature (interpolate) data_low, data_high = dataContainer.get_data(temperature) fraction = (temperature % properties.temperature_step) / float(properties.temperature_step) density = [data_low.density[i] + fraction * (data_high.density[i] - data_low.density[i]) for i in range(len(data_low.density))] # Enthalpy known for the exact temperature, calculate at exact pressure (interpolate) for i, p in enumerate(data_low.pressure): if p == pressure: return density[i] * 1000 # g/ml to kg/m3 if p > pressure: # We're in between two pressures that are listed, i and i-1 fraction = (pressure - data_low.pressure[i - 1]) / (data_low.pressure[i] - data_low.pressure[i - 1]) return density[i - 1] + fraction * (density[i] - density[i - 1]) * 1000 # g/ml to kg/m3
def performance_by_throat_diameter_area_ratio(power, mass_flow, Dt, De=None, Tc=None, AreaRatio=None, print_results=False): if not De and not AreaRatio: raise StandardError("Either 'De' or 'AreaRatio' has to be defined!") if De is not None and AreaRatio is not None: raise StandardError("Only 'De' OR 'AreaRatio' may be defined!") enthalpy = (power / mass_flow ) / 1000. + H_sto # Enthalpy of the propellant in the chamber def calculate_pc(T): # Guess a chamber pressure Pc = convert.bar_to_pa(1) # 1 bar step = convert.bar_to_pa(0.5) # 0.5 bar direction = 0 while step / Pc > 0.0001: # When the change in stepsize is less then 0.01%, Pc is very accurate gamma = get_specific_heat_ratio_pressure_temperature(Pc, T) At = AreaThroat(mass_flow, gamma, Pc, T) temp_Dt = convert.area_to_diameter(At) difference = temp_Dt - Dt if difference > 0: if direction == -1: step /= 2 if direction == 1: step *= 1.5 direction = 1 Pc += step elif difference < 0: if direction == -1: step *= 1.5 if direction == 1: step /= 2 direction = -1 Pc -= step if Pc <= 0: # Pe can't be negative Pc = 1e-20 return Pc if Tc: Pc = calculate_pc(Tc) else: Tc = Pc = 0 H_min = 1E100 for t in range(temperature_min, temperature_max): Pc_temp = calculate_pc(t) if Pc_temp > convert.bar_to_pa( pressure_max ): # Can't calculate pressures above pressure_max pass enthalpy_temp = get_enthalpy_pressure_temperature(Pc_temp, t) enthalpy_diff = abs(enthalpy - enthalpy_temp) if enthalpy_diff < H_min: Pc = Pc_temp Tc = t H_min = enthalpy_diff if Pc == 0: raise ValueError("Pressure too high!") if Tc == temperature_min: raise ValueError("Temperature too low!") if Tc == temperature_max - 1: raise ValueError("Temperature too high!") gamma = get_specific_heat_ratio_pressure_temperature(Pc, Tc) At = convert.diameter_to_area(Dt) if De is not None: Ae = convert.diameter_to_area(De) elif AreaRatio is not None: Ae = AreaRatio * At De = convert.area_to_diameter(Ae) Pe = ExitPressure(gamma, Ae, At, Pc) Ue = ExhaustVelocity(gamma, Pe, Pc, Tc) Thrust = RocketThrustEquation(mass_flow, Ue, Pe, Pa, Ae) c_star = Pc * At / mass_flow CF = Thrust / (Pc * At) Isp = CF * c_star / g0 if print_results: print "Thrust:", Thrust * 1000, "mN", '\t\t', performance_difference( 2.31386612509, Thrust * 1000) print "Isp:", Isp, "s", '\t\t', performance_difference( 131.082600134, Isp) print "Specific Heat Ratio:", gamma print "Exhaust Velocity:", Ue, "m/s" print "Effective Exhaust Velocity", Thrust / mass_flow, "m/s" print "c*:", c_star, "m/s", '\t\t', performance_difference( 691.043939954, c_star) print "Thrust Coefficient:", CF, '\t\t', performance_difference( 1.86020179945, CF) print "Chamber Temperature:", Tc, "K", '\t\t', performance_difference( 465, Tc) print "Chamber Pressure:", convert.pa_to_bar( Pc), "bar", '\t\t', performance_difference(0.703891577199, convert.pa_to_bar(Pc)) print "Exit Pressure:", convert.pa_to_bar(Pe), "bar" print "Pressure Ratio: 1/" + str(round(Pc / Pe, 2)) print "Throat Diameter:", Dt * 1000, "mm" print "Exit Diameter:", De * 1000, "mm" print "Area Ratio: 1/" + str(Ae / At) print "Mass flow:", mass_flow * 1E6, "mg/s" print "Enthalpy:", enthalpy return Thrust * 1000, Isp, gamma, convert.pa_to_bar(Pc)