Exemplo n.º 1
0
    def test_TRP_example(self):
        # Slide 57-51 from Ideal Rocket Motor lecture from Thermal Rocket Propulsion course are used as example (Zandbergen)
        F_expected = 401.8e3
        u_exit_expected = 3021
        m_dot_expected = 132.9
        gamma = 1.3
        R = 390.4
        p_chamber = 5.6e6
        p_back = 6.03e3
        T_chamber = 3400
        AR_exit = 49
        d_exit = 1.6
        A_exit = 0.25 * math.pi * d_exit**2
        A_throat = A_exit / AR_exit

        NS = "isentropically expanded (margin: 0.01)"
        res = 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)
        self.assertAlmostEqual(res['thrust'], F_expected, -3)
        self.assertAlmostEqual(res['m_dot'], m_dot_expected, 0)
        self.assertAlmostEqual(res['u_exit'], u_exit_expected, -1)
        self.assertEqual(res['nozzle_status'], NS)
Exemplo n.º 2
0
    def test_simple_input(self):
        u_exit_expected = 1.0801234497346432
        m_dot_expected = 0.6847314563772704  # Should be equal to Gamma(1.4) (vandankerkhove function)
        p_exit = 0.5282817877171743  # Should be exit pressure for M=1
        AR_exit = 1
        T_chamber = 1
        R = 1
        gamma = 1.4
        p_chamber = 1
        A_throat = 1
        AR_exit = 1
        p_back = 0

        # Expected thrust
        F_expected = m_dot_expected * u_exit_expected + p_exit * A_throat * AR_exit
        # Since the throat is M=1 and the back pressure is vacuum, it is clearly underexpanded
        NS = "underexpanded"
        res = 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)
        self.assertEqual(res['thrust'], F_expected)
        self.assertEqual(res['m_dot'], m_dot_expected)
        self.assertEqual(res['u_exit'], u_exit_expected)
        self.assertEqual(res['nozzle_status'], NS)
Exemplo n.º 3
0
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
    }
Exemplo n.º 4
0
fp = FluidProperties(td['propellant']) # Object to access fluid properties with
p_c = 5e5#td['p_inlet'] # [bar] Chamber pressure
T_c = 600#td['T_chamber_guess'] # [K] Chamber temperature
h_channel = td['h_channel'] # [m] Channel/nozzle depth
w_throat = td['w_throat'] # [m] Throat width
AR_exit = 10 #td['AR_exit'] # [-] Exit area ratio
p_back = 0# td['p_back'] # [Pa] Atmospheric pressire

print("Chamber temperature: {:3.2f} K".format(T_c))

# Calculate throat area, and propellant properties
A_throat = h_channel*w_throat # [m^2] Thrpat area
gamma = fp.get_specific_heat_ratio(T=T_c, p=p_c) # [-] Get gamma at specified gas constant
R = fp.get_specific_gas_constant() # [J/(kg*K)] Specific gas constant

ep = IRT.get_engine_performance(p_chamber=p_c, T_chamber=T_c, A_throat=A_throat, AR_exit=AR_exit, p_back=p_back, gamma=gamma, R=R)
print("\n --- IRT predictions --- ")
print("Isp: {:3.2f} s".format(ep['Isp']))
print("Gamma: {:1.3f} ".format(gamma))
print("Mass flow: {:2.3f} mg/s".format(ep['m_dot']*1e6))
print("Thrust: {:2.3f} mN".format(ep['thrust']*1e3))

zeta_CF = td['F']/ep['thrust']
Isp_real = td['F']/td['m_dot']/g0
zeta_Isp = Isp_real/ep['Isp']
discharge_factor = td['m_dot']/ep['m_dot']

print('\n --- Experimental values ---')
print("Isp: {:3.2f} s (zeta_Isp = {:1.3f})".format(Isp_real, zeta_Isp))
print("Mass flow: {:2.3f} mg/s (Cd = {:1.3f})".format(td['m_dot']*1e6, discharge_factor))
print("Thrust: {:2.3f} mN (zeta_CF ={:1.3f})".format(td['F'], zeta_CF))