def plot_condensation_curve(AR_min, AR_max, p_c, fp, T_ref): gamma = fp.get_specific_heat_ratio(T=T_ref, p=p_c) # [-] Specific heat ratio # Determine maximum Mach number at exit M_exit_max = IRT.Mach_from_area_ratio( AR=AR_max, gamma=gamma) # [-] Max. Mach number at exit M_exit_min = IRT.Mach_from_area_ratio( AR=AR_min, gamma=gamma) # [-] Min. Mach number at exit M_exit = np.linspace(start=M_exit_min, stop=M_exit_max, num=50) # [-] Range of exit Mach numbers to evalulate # Determine pressure at exit PR_exit = IRT.pressure_ratio(M=M_exit, gamma=gamma) # [-] Pressure ratio at exit p_exit = p_c / PR_exit # [-] Exit pressure # Determine saturation temperature at exit T_sat_exit = fp.get_saturation_temperature( p=p_exit) # [K] Saturation temperature at exit # print(p_exit) # print(T_sat_exit) TR_exit = IRT.temperature_ratio( M=M_exit, gamma=gamma) # [-] Temperature ratio at exit T_chamber = T_sat_exit * TR_exit # [K] Chamber temperature that would result precisely in saturation temperature at nozzle exit AR = IRT.area_ratio( M=M_exit, gamma=gamma ) # [-] Area ratios corresponding to all specified mach numbers plt.plot( AR, T_chamber, label="$p_c ={:2.0f}$ bar , $T_c={:3.0f}$ K, $\\gamma={:1.3f}$".format( p_c * 1e-5, T_ref, gamma))
def test_simple_input(self): M = 1 gamma = 2 expected_temperature_ratio = 1.5 expected_pressure_ratio = 2.25 res_temperature_ratio = IRT.temperature_ratio(M=M, gamma=gamma) res_pressure_ratio = IRT.pressure_ratio(M=M, gamma=gamma) self.assertEqual(expected_temperature_ratio, res_temperature_ratio) self.assertEqual(expected_pressure_ratio, res_pressure_ratio)
def test_anderson_table(self): # Table in back of Anderson book gives values for gamma=1.4 gamma = 1.4 in_out = ((0.2e-1, 0.1e1, 3, 0.1e1, 3), (0.24e0, 0.1041e1, 3, 0.1012e1, 3), (0.56e0, 0.1237e1, 3, 0.1063e1, 3), (1, 0.1893e1, 3, 0.12e1, 3), (1.64e0, 0.4511e1, 3, 0.1538e1, 3), (2.45e0, 0.1581e2, 2, 0.22e1, 3), (50, 0.2815e10, -6, 0.5010e3, 1)) for M, expected_PR, PR_places, expected_TR, TR_places in in_out: res_PR = IRT.pressure_ratio(M=M, gamma=gamma) res_TR = IRT.temperature_ratio(M=M, gamma=gamma) self.assertAlmostEqual(res_PR, expected_PR, PR_places) self.assertAlmostEqual(res_TR, expected_TR, TR_places)
def plot_pressure_curve(AR_min, AR_max, p_c, fp, T_ref): gamma = fp.get_specific_heat_ratio(T=T_ref, p=p_c) # [-] Specific heat ratio # Determine maximum Mach number at exit M_exit_max = IRT.Mach_from_area_ratio( AR=AR_max, gamma=gamma) # [-] Max. Mach number at exit M_exit_min = IRT.Mach_from_area_ratio( AR=AR_min, gamma=gamma) # [-] Min. Mach number at exit M_exit = np.linspace(start=M_exit_min, stop=M_exit_max, num=50) # [-] Range of exit Mach numbers to evalulate # Determine pressure at exit PR_exit = IRT.pressure_ratio(M=M_exit, gamma=gamma) # [-] Pressure ratio at exit p_exit = p_c / PR_exit # [-] Exit pressure AR = IRT.area_ratio( M=M_exit, gamma=gamma ) # [-] Area ratios corresponding to all specified mach numbers plt.plot(AR, p_exit * 1e-5, label="{:2.0f} bar , $\\gamma={:1.2f}$".format(p_c * 1e-5, gamma))
def Rajeev_complete(p_chamber, T_chamber, w_throat, h_throat, throat_roc, AR_exit, p_back, divergence_half_angle, fp: FluidProperties, is_cold_flow): """ Function that implements all corrections proposed by Makhan2018 Args: p_chamber (Pa): Chamber pressure T_chamber (K): Chamber temperature w_throat (m): Throat width h_throat (m): Throat heigh (or channel depth) throat_roc (m): Throat radius of curvature AR_exit (-): Area ratio of nozzle exit area divided by throat area p_back (Pa): Back pressure divergence_half_angle (rad): Divergence half angle of nozzle fp (FluidProperties): Object to access fluid properties is_cold_flow (bool): Reynolds number is adjusted depending on whether the chamber is heated or cooled Raises: ValueError: Is raised for hot flow, since no verification is done yet on that equation """ # Get the (assumed to be) constant fluid properties gamma = fp.get_specific_heat_ratio(T=T_chamber, p=p_chamber) # [-] Specific heat ratio R = fp.get_specific_gas_constant() # [J/kg] Specific gas constant # Report calculated values for verification and comparison purposes print("Gamma: {:1.4f}".format(gamma)) print("R: {:3.2f} J/kg\n".format(R)) # Calculate basic peformance parameters A_throat = w_throat * h_throat # [m] Throat area ## IDEAL PERFORMANCE # First get ideal performance, and check if the nozzle is properly expanded. ep = IRT.get_engine_performance(p_chamber=p_chamber, T_chamber=T_chamber, A_throat=A_throat, AR_exit=AR_exit, p_back=p_back, gamma=gamma, R=R) # Report ideal performance print("Thrust: {:.2f} mN".format(ep['thrust'] * 1e3)) print("Isp_ideal: {:.1f} s".format(ep['thrust'] / ep['m_dot'] / 9.80655)) print("Mass flow: {:.3f} mg/s".format(ep['m_dot'] * 1e6)) m_dot_ideal = ep['m_dot'] # [kg/s] Ideal mass flow #F_ideal = ep['thrust'] # [N] Ideal thrust ## CALCULATING THE CORRECTION FACTORS # Calculate the divergence loss and report it CF_divergence_loss = divergence_loss_conical_2D( alpha=divergence_half_angle) print("\n -- DIVERGENCE LOSS for {:2.2f} deg divergence half-angle".format( math.degrees(divergence_half_angle))) print( " Divergence loss (2D concical): {:.5f} ".format(CF_divergence_loss)) # Calculate the viscous loss # To determine the Reynolds number at the throat, the hydraulic diameter at the throat and nozzle conditions must be determined # Get hydraulic diameter of the nozzle from the wetted perimeter and nozzle area wetted_perimeter_throat = 2 * (w_throat + h_throat ) # [m] Wetted perimeter throat Dh_throat = hydraulic_diameter(A=A_throat, wetted_perimeter=wetted_perimeter_throat ) # [m] Hydraulic diameter at throat p_throat = p_chamber / IRT.pressure_ratio( M=1, gamma=gamma) # [Pa] pressure in throat T_throat = T_chamber / IRT.temperature_ratio( M=1, gamma=gamma) # [K] Temperature in throat viscosity_throat = fp.get_viscosity(T=T_throat, p=p_throat) # Throat reynolds based on ideal mass flow? Re_throat = reynolds(m_dot=m_dot_ideal, A=A_throat, D_hydraulic=Dh_throat, viscosity=viscosity_throat) if is_cold_flow: Re_throat_wall = Reynolds_throat_wall_cold(reynolds_throat=Re_throat) else: Re_throat_wall = Reynolds_throat_wall_hot(reynolds_throat=Re_throat) print("\n-- THROAT CONDITIONS --") print(" p = {:2.4f} bar, T = {:4.2f} K".format( p_throat * 1e-5, T_throat)) print(" mu = {:2.4f} [microPa*s] Dh = {:3.4f} [microm]".format( viscosity_throat * 1e6, Dh_throat * 1e6)) print(" Reynolds: {:6.6f} ".format(Re_throat)) CF_viscous_loss = viscous_loss(area_ratio=AR_exit, reynolds_throat_wall=Re_throat_wall) print(" CF_viscous_loss: {:1.5f}".format(CF_viscous_loss)) # Calculating throat boundary layer loss, which causes a reduction in effective throat area/mass flow Cd_throat_boundary_loss = throat_boundary_loss(gamma=gamma, reynolds_throat=Re_throat, throat_radius=0.5 * Dh_throat, throat_roc=throat_roc) print("\n-- DISCHARGE FACTOR --") print(" Throat boundary layer: {:1.4f}".format(Cd_throat_boundary_loss)) ## APPLYING THE CORRECTION FACTORS # Now all these loss factors must be combined into a new "real" thrust # The divergence loss only applies to the jet/momentum thrust and not the pressure, so jet thrust is needed # This is equal to the exit velocity times corrected mass flow. The returned exit velocity does not include pressure terms! # First we must know the corrected mass flow m_dot_real = ep['m_dot'] * Cd_throat_boundary_loss # [kg/s] # Secondly, we must know the pressure thrust to add to the jet thrust again F_pressure = IRT.pressure_thrust(p_chamber=p_chamber, p_back=p_back, A_throat=A_throat, AR=AR_exit, gamma=gamma) F_divergence = m_dot_real * ep[ 'u_exit'] * CF_divergence_loss + F_pressure # [N] Thrust decreased by divergence loss, pressure term must be added again, since divergence only applies to jet thrust # This jet thrust is then again corrected by viscous losses, which are subtracted from the current CF CF_jet_divergence = F_divergence / ( p_chamber * A_throat ) # [-] Thrust coefficient after taking into account discharge factor and divergence loss CF_real_final = CF_jet_divergence - CF_viscous_loss # [-] The final thrust coefficient, also taking into account viscous loss F_real = CF_real_final * p_chamber * A_throat # [N] Real thrust, after taking into account of all the three proposed correction factors # Report "real" results print("\n === CORRECTED PERFORMANCE PARAMETERS === ") print(" Real mass flow: {:3.4f} mg/s".format(m_dot_real * 1e6)) print(" CF with divergence loss {:1.5f}".format(CF_jet_divergence)) print(" Real CF: {:1.5f}".format(CF_real_final)) print(" Real thrust: {:2.4f} mN".format(F_real * 1e3)) print(" Real Isp: {:3.2f}".format(F_real / m_dot_real / 9.80655)) return { 'm_dot_real': m_dot_real, 'm_dot_ideal': ep['m_dot'], 'F_real': CF_real_final }