In [6]:
from math import pi
g0 = 9.81 # Gravitational acceleration [m/s^2]
# Propellant properties
lox = {'M': 31.999 / 1000, # Molar mass [kg/mol]
'T_e': 90.2, # Propellant temperature [K]
'C_pl': 1.70 * 1000, # Liquid phase specific heat [J/kg*K]
'C_pv': 0.91 * 1000, # Vapor phase secific heat (cosntant pressure) [J/kg*K]
'h_v': 213.05 * 1000, # Heat of vaporization [J/kg]
'T_v': 90.2, # Vaporization temperature [K]
'R_p': R / (31.999 / 1000), # Specific gas constant
'p_t': (350+70) * 1.1 * 6894, # Propellant tank initial pressure [Pa]
'a': 1.382 / 10, # van der Wall constant A [Pa*m^6/mol^2]
'b': 0.03186 / 1000, # van der Wall constant B [m^3/mol]
'rho': 71.38, # [lbf/ft^3]
'mu': 0.000013999, # [lb/s*in]
'mdot': 1.13, # [lbf/s]
'name': 'lox'
}
ipa = {'M': 60.1 / 1000, # Molar mass [kg/mol]
'T_e': 293, # Propellant temperature [K]
'C_pl': 7.25 * 1000 * (60.1 / 1000), # Liquid phase specific heat [J/kg*K]
'C_pv': 1.75 * 1000, # Vapor phase secific heat (cosntant pressure) [J/kg*K]
'h_v': 36800 * (60.1 / 1000), # Heat of vaporization [J/kg]
'T_v': 355.8, # Vaporization temperature [K]
'R_p': R / (60.1 / 1000), # Specific gas constant
'p_t': ((350 #Chamber pressure [psi]
+ 145 # Regen pressure drop [psi]
+ 70) # Injector pressure drop [psi]
* 1.1 * 6894), # Propellant tank initial pressure [Pa]
'a': 12.18 / 10, # van der Wall constant A [Pa*m^6/mol^2]
'b': 0.08407 / 1000, # van der Wall constant B [m^3/mol]
'rho': 55.249, # [lbf/ft^3]
'mu': 0.000067197, #[lb/in*s]
'mdot': 0.94, # [lbf/s]
'name': 'ipa'
}
In [11]:
#constants
P_ch = 350*6894.76 #chamber pressure [Pa]
P_t = {'lox': 750*6894.76,
'ipa': 750*6894.76} #tank pressure
P_inj = {'lox': 0.15*P_ch,
'ipa': 0.15*P_ch} #injector drop
P_cooling = {'lox': 0,
'ipa': 140*6894.76} #regen cooling channel drop
D = {'lox': 0.5*0.0254,
'ipa': 0.5*0.0254 } #tube diameter
l = {'lox':12*3*0.0254,
'ipa': 12*3*0.0254} #tube_length
K_l = {'elbow_90_threaded': 1.5,
'elbow_45_threaded': 0.4,
'tee_line_theaded': 0.9,
'tee_branch_threaded': 2.0}#minor loss coefficients
def Cv():
return
def Q(prop):
return prop['mdot']/prop['rho'] #volumetric flow rate
def U():
return Q/(pi*D**2/4) #flow velocity
def Re(prop):
return rho*U*D/mu #Reynolds number
def blasius():
return 0.316/Re(prop)**0.25 #Basius friction factor
def major_losses(l, V):
return blasius()*l*V**2/(D*2*g0) #Darcy-Weisbach equation
def minor_losses():
return K_l*U**2/(2*g0) #orifices, bends, suddend expansions & contractions
minors = [['ipa', K_l[0], K_l[0], K_l[0], K_l[1], K_l[2], K_l[3]],['lox', K_l[0], K_l[0], K_l[0], K_l[1], K_l[2], K_l[3]]]
valve_list = {'mov': 0.05,
'mfv': 0.05}
for types in minors:
P_minor += minor_losses(types)
for valves in valve_list:
P_valves += Cv(valves)
P_total = sum(P_t) - P_inj[] - P_cooling[] - major_losses() - P_minor[] - P_valves
print('Pressure budget (LOX) = {0:.2f} kpa'.format(P_total['lox']))
print('Pressure budget (IPA) = {0:.2f} kpa'.format(P_total['ipa']))
Most of the following discussion follows from Huzel & Huang (1992) Ch 5. guidlines on gas-pressurized propellant feed systems. We need a starting place, particularly some assumptions and/pr constraints regarding:
The following analysis will also make the following assumptions:
Finally these are the key design requirements:
Initial fill fraction of the propellant tanks will depend of test fire duration, thrust level, and total pressurization time and ambient air temperature among other things. The most conservative estimate is based on the case where an intially full tank (fill fraction is 100%) is completely emptied. If this is the case the pressurant mass required is determined from the equation of state and the isentropic gas equation. Given this ammount of pressurant gas the tank should become empty just as the pressurant supply tank pressure drops to the regulator set point pressure. Some important issues to consider in this analysis are propellant vaporization, and real gass effects.
In [5]:
# Constants
dia = 0.1 # Tank diameter [m]
A = pi * (dia / 2)**2 # Propellant surface area [m^2]
V = 2 # Propellant tank volume [m^3]
t = 60 # Maximum design burn time [s]
y = 1.4 # Pressurant ratio of specific heats (assumed constant)
H = 2 # Heat transfer coefficient not really a constant /
# not sure how to calculate yet
#(the number is ok as 1st approx, actual value is a bit bs)
p_i = 3500 * 6894 # Pressurant tank initial pressure [Pa]
R = 8.3145 # Universal gas constant [Pa*m^3/K*mol]
M_g = 28.01/1000 # Nitrogen molar mass [kg/mol]
R_g = R / M_g
T_i = 293 # Nitrogen initial tank temperature [K]
# Compressibility factor using van der Wall polynomial expansion
def Z(fluid, tank, p, T):
if fluid == 'ipa':
a = ipa['a']
b = ipa['b']
M = ipa['M']
#V_m = # Molar volume
elif fluid == 'lox':
a = lox['a']
b = lox['b']
M = lox['M']
#V_m = # Molar volume
elif fluid == 'N2':
a = 0.1370
b = 3.913E-5
M = 28.01 / 1000
#V_m = R * T / p # Molar volume
else:
print("There's an issue")
if tank == 'prop':
#V = # Whatever the propellant tank volume is [m^3]
V_m = R * T / p # Molar volume
return V_m / (V_m - b) - a / (R * T * V_m)
elif tank == 'pres':
V_m = R * T / p # Molar volume
return V_m / (V_m - b) - a / (R * T * V_m)
# A much more realistic approximation
def pres_tank_volume(prop):
#print(prop['name'])
T_u = (prop['p_t'] / p_i)**((y - 1) / y) * T_i # Isentropic expansion of pressurant [K]
Q = H * A * t * (T_u-prop['T_e']) # Heat transfer from pressurant gas to propellant vapor [J]
m_v = (Q / (prop['C_pl'] * (prop['T_v'] - prop['T_e'])
+ prop['h_v'] + prop['C_pv'] * (T_u - prop['T_v']))) # Mass of vaporized propellant [kg]
V_v = ((m_v * Z(prop['name'], 'prop', prop['p_t'], T_u)
* prop['R_p'] * T_u) / prop['p_t']) # Partial volume of vaporized propellant [m^3]
V_g = V - V_v # Pressurant volume at end of expulsion [m^3]
m_g = ((prop['p_t'] * V_g * Z('N2','pres', prop['p_t'], T_u))
/ (R_g * T_u)) # Required pressurant mass [kg]
V_gtank = (m_g * Z('N2', 'pres', p_i, T_i)
* R_g * T_i) / p_i #Requied pressurant volume (per propellant) [m^3]
return V_gtank, Q, T_u
#might need to solve simult T_u and (do I use N2 partial pressure at end of expulsion in T_u calc?)
sf = 2 # Safety factor
total_volume = (pres_tank_volume(lox)[0] + pres_tank_volume(ipa)[0]) * sf
print('Total required pressurant (for a single burn) = {0:.2f} m^3'.format(total_volume))
print('Final pressurant temperature (LOX) = {0:.2f} K'.format(pres_tank_volume(lox)[2]))
print('Final pressurant temperature (IPA) = {0:.2f} K'.format(pres_tank_volume(ipa)[2]))
print('Trapped LOX volume = {0:.2f} m^3'.format(pres_tank_volume(lox)[1]))
print('Trapped IPA volume = {0:.2f} m^3'.format(pres_tank_volume(ipa)[1]))
This is essential a summary of points made in NASA SP-8097 (Liquid Rocket Valve Assemblies).
Valve response time is defined as the total time elapsed from recipt of of an actuation signal to the time where the valve is either fully opened or fully closed. Various factors impact the valve timing:
Some further considerations follow.
Factors that affect response time of pneumatic actuators include flow capacity of the control valving, line sizes, initial total volume, and actuator swept volume. Another issue it the current thermodynamic state of the prussurant in the case were it is the same as main propellant pressurization gas (as in our design). Obviously near the end of a burn the regulated pressure supplied to the piston will be different than during the intial actuation due to the mostly-isentropic expansion of the pressurant gasses. Any other pressure transient that propagate up to the actuator taps will also affect their response time.
In [ ]: