以下是一个简化的液体火箭发动机数字仿真系统的Python实现。这个系统包含了基本的推进剂流量、燃烧室、喷管和性能计算模块。
"""
液体火箭发动机数字仿真系统
简化版本 - 教学演示用途
日期: 2026年3月16日
"""
import numpy as np
from dataclasses import dataclass
from typing import Dict, List, Optional, Tuple
import matplotlib.pyplot as plt
from scipy.integrate import odeint
import warnings
warnings.filterwarnings('ignore')
@dataclass
class EngineConfig:
"""发动机配置参数"""
name: str = "RL-10型液氢液氧发动机"
chamber_pressure: float = 3.5e6 # 燃烧室压力, Pa
mixture_ratio: float = 6.0 # 混合比 (氧化剂/燃料)
nozzle_area_ratio: float = 40.0 # 喷管面积比
chamber_temp: float = 3500.0 # 燃烧室温度, K
specific_heat_ratio: float = 1.2 # 比热比
molar_mass: float = 0.022 # 燃气摩尔质量, kg/mol
efficiency_combustion: float = 0.98 # 燃烧效率
efficiency_nozzle: float = 0.96 # 喷管效率
class Propellant:
"""推进剂类"""
def __init__(self, name: str, density: float, specific_heat: float):
self.name = name
self.density = density # kg/m³
self.specific_heat = specific_heat # J/(kg·K)
self.temperature = 293.0 # K, 初始温度
class LiquidRocketEngine:
"""液体火箭发动机仿真主类"""
def __init__(self, config: EngineConfig):
self.config = config
self.propellants = {}
self.mass_flow_rate = 0.0
self.thrust = 0.0
self.isp = 0.0
self.time = 0.0
self.operating = False
# 状态历史记录
self.history = {
'time': [],
'thrust': [],
'pressure': [],
'temperature': [],
'mass_flow': [],
'isp': []
}
def add_propellant(self, prop_type: str, prop: Propellant):
"""添加推进剂"""
self.propellants[prop_type] = prop
def calculate_mass_flow(self, fuel_flow_rate: float) -> Tuple[float, float]:
"""计算质量流量"""
if 'oxidizer' not in self.propellants or 'fuel' not in self.propellants:
raise ValueError("需要先添加氧化剂和燃料")
# 基于混合比计算氧化剂流量
oxidizer_flow_rate = fuel_flow_rate * self.config.mixture_ratio
total_flow_rate = fuel_flow_rate + oxidizer_flow_rate
self.mass_flow_rate = total_flow_rate
return oxidizer_flow_rate, total_flow_rate
def combustion_chamber_model(self, mass_flow: float) -> Dict:
"""燃烧室模型"""
# 简化的燃烧室计算
R_specific = 8314.462618 / self.config.molar_mass # 气体常数, J/(kg·K)
# 燃烧室出口参数
chamber_velocity = np.sqrt(
R_specific * self.config.chamber_temp *
self.config.specific_heat_ratio *
(2 / (self.config.specific_heat_ratio + 1))
)
# 喉部面积计算 (简化)
throat_area = mass_flow * np.sqrt(R_specific * self.config.chamber_temp) / (
self.config.chamber_pressure * np.sqrt(self.config.specific_heat_ratio) *
(1 + (self.config.specific_heat_ratio - 1) / 2) **
(-(self.config.specific_heat_ratio + 1) / (2 * (self.config.specific_heat_ratio - 1)))
)
return {
'throat_area': throat_area,
'chamber_velocity': chamber_velocity,
'characteristic_velocity': np.sqrt(R_specific * self.config.chamber_temp /
self.config.specific_heat_ratio)
}
def nozzle_model(self, chamber_params: Dict, altitude: float = 0.0) -> Dict:
"""喷管模型 - 包括高度补偿"""
# 大气压力随高度变化 (简化模型)
p_ambient = 101325 * np.exp(-altitude / 8500) # Pa
# 喷管膨胀计算
gamma = self.config.specific_heat_ratio
Pc = self.config.chamber_pressure
Pe = Pc * (1 + (gamma - 1) / 2) ** (-gamma / (gamma - 1)) # 出口压力
Ae_At = self.config.nozzle_area_ratio
# 计算推力系数
Cf = np.sqrt(
(2 * gamma ** 2 / (gamma - 1)) *
(2 / (gamma + 1)) ** ((gamma + 1) / (gamma - 1)) *
(1 - (Pe / Pc) ** ((gamma - 1) / gamma))
)
# 考虑环境压力修正
if Pe > p_ambient:
Cf += (Pe - p_ambient) * Ae_At / Pc
Cf *= self.config.efficiency_nozzle
return {
'exit_pressure': Pe,
'ambient_pressure': p_ambient,
'thrust_coefficient': Cf,
'expansion_ratio': Ae_At
}
def calculate_thrust(self, mass_flow: float, nozzle_params: Dict,
chamber_params: Dict) -> float:
"""计算推力"""
# 特征速度
c_star = chamber_params['characteristic_velocity']
# 推力
thrust = mass_flow * c_star * nozzle_params['thrust_coefficient']
# 应用燃烧效率
thrust *= self.config.efficiency_combustion
self.thrust = thrust
return thrust
def calculate_isp(self, thrust: float, mass_flow: float) -> float:
"""计算比冲"""
if mass_flow <= 0:
return 0.0
isp = thrust / (mass_flow * 9.80665) # 地球重力加速度
self.isp = isp
return isp
def transient_model(self, state: List[float], t: float,
control_params: Dict) -> List[float]:
"""瞬态模型 - 用于ODE求解"""
# 状态变量: [燃烧室压力, 燃烧室温度, 涡轮转速]
Pc, Tc, N = state
# 控制参数
valve_position = control_params.get('valve_position', 0.5)
target_pressure = control_params.get('target_pressure',
self.config.chamber_pressure)
# 简化的动态方程
tau_p = 0.1 # 压力时间常数
tau_t = 0.2 # 温度时间常数
tau_n = 0.3 # 转速时间常数
dPc_dt = (target_pressure * valve_position - Pc) / tau_p
dTc_dt = (self.config.chamber_temp - Tc) / tau_t
dN_dt = (1000 - N) / tau_n # 目标转速1000 rad/s
return [dPc_dt, dTc_dt, dN_dt]
def run_transient_simulation(self, duration: float = 10.0,
dt: float = 0.1) -> Dict:
"""运行瞬态仿真"""
if not self.propellants:
raise ValueError("需要先添加推进剂")
# 初始状态
initial_state = [
1e5, # 初始压力 (Pa)
293.0, # 初始温度 (K)
0.0 # 初始转速
]
# 时间点
time_points = np.arange(0, duration, dt)
# 控制参数
control_params = {
'valve_position': 0.0,
'target_pressure': self.config.chamber_pressure
}
# 模拟阀门开启
results = []
for i, t in enumerate(time_points):
# 阀门开启曲线
if t < 1.0:
control_params['valve_position'] = t
else:
control_params['valve_position'] = 1.0
# 使用欧拉法积分
if i == 0:
state = initial_state
else:
derivatives = self.transient_model(state, t, control_params)
state = [s + d * dt for s, d in zip(state, derivatives)]
# 记录结果
results.append({
'time': t,
'pressure': state[0],
'temperature': state[1],
'rpm': state[2] * 9.5493, # 转换为RPM
'valve_position': control_params['valve_position']
})
return results
def run_steady_state(self, fuel_flow: float = 5.0,
altitude: float = 0.0) -> Dict:
"""运行稳态仿真"""
print(f"运行稳态仿真 - 燃料流量: {fuel_flow} kg/s, 高度: {altitude} m")
# 计算质量流量
oxidizer_flow, total_flow = self.calculate_mass_flow(fuel_flow)
# 燃烧室计算
chamber = self.combustion_chamber_model(total_flow)
# 喷管计算
nozzle = self.nozzle_model(chamber, altitude)
# 推力计算
thrust = self.calculate_thrust(total_flow, nozzle, chamber)
# 比冲计算
isp = self.calculate_isp(thrust, total_flow)
# 记录状态
self.history['time'].append(self.time)
self.history['thrust'].append(thrust)
self.history['pressure'].append(self.config.chamber_pressure)
self.history['temperature'].append(self.config.chamber_temp)
self.history['mass_flow'].append(total_flow)
self.history['isp'].append(isp)
results = {
'fuel_flow': fuel_flow,
'oxidizer_flow': oxidizer_flow,
'total_flow': total_flow,
'thrust_N': thrust,
'thrust_kgf': thrust / 9.80665,
'specific_impulse': isp,
'chamber': chamber,
'nozzle': nozzle,
'mixture_ratio': self.config.mixture_ratio
}
return results
def plot_results(self, transient_data: Optional[List] = None):
"""绘制结果"""
fig, axes = plt.subplots(2, 3, figsize=(15, 10))
fig.suptitle(f'{self.config.name} 仿真结果', fontsize=16)
if transient_data and len(transient_data) > 0:
# 绘制瞬态响应
time = [d['time'] for d in transient_data]
pressure = [d['pressure'] / 1e6 for d in transient_data] # 转换为MPa
temperature = [d['temperature'] for d in transient_data]
rpm = [d['rpm'] for d in transient_data]
valve = [d['valve_position'] for d in transient_data]
# 压力响应
axes[0, 0].plot(time, pressure, 'b-', linewidth=2)
axes[0, 0].set_xlabel('时间 (s)')
axes[0, 0].set_ylabel('燃烧室压力 (MPa)')
axes[0, 0].set_title('压力瞬态响应')
axes[0, 0].grid(True, alpha=0.3)
# 温度响应
axes[0, 1].plot(time, temperature, 'r-', linewidth=2)
axes[0, 1].set_xlabel('时间 (s)')
axes[0, 1].set_ylabel('燃烧室温度 (K)')
axes[0, 1].set_title('温度瞬态响应')
axes[0, 1].grid(True, alpha=0.3)
# 阀门和转速
ax2 = axes[0, 2].twinx()
axes[0, 2].plot(time, valve, 'g-', linewidth=2, label='阀门位置')
ax2.plot(time, rpm, 'm-', linewidth=2, label='涡轮转速', alpha=0.7)
axes[0, 2].set_xlabel('时间 (s)')
axes[0, 2].set_ylabel('阀门位置', color='g')
ax2.set_ylabel('转速 (RPM)', color='m')
axes[0, 2].set_title('控制系统响应')
axes[0, 2].legend(loc='upper left')
ax2.legend(loc='upper right')
axes[0, 2].grid(True, alpha=0.3)
if len(self.history['time']) > 0:
# 绘制稳态性能
mixtures = np.linspace(4, 8, 10)
thrusts = []
isps = []
for mr in mixtures:
self.config.mixture_ratio = mr
result = self.run_steady_state(fuel_flow=5.0)
thrusts.append(result['thrust_N'] / 1000) # 转换为kN
isps.append(result['specific_impulse'])
# 推力 vs 混合比
axes[1, 0].plot(mixtures, thrusts, 'b-o', linewidth=2, markersize=6)
axes[1, 0].set_xlabel('混合比 (O/F)')
axes[1, 0].set_ylabel('推力 (kN)')
axes[1, 0].set_title('推力 vs 混合比')
axes[1, 0].grid(True, alpha=0.3)
# 比冲 vs 混合比
axes[1, 1].plot(mixtures, isps, 'r-o', linewidth=2, markersize=6)
axes[1, 1].set_xlabel('混合比 (O/F)')
axes[1, 1].set_ylabel('比冲 (s)')
axes[1, 1].set_title('比冲 vs 混合比')
axes[1, 1].grid(True, alpha=0.3)
# 高度对性能的影响
altitudes = np.linspace(0, 50000, 10)
thrusts_alt = []
for alt in altitudes:
result = self.run_steady_state(fuel_flow=5.0, altitude=alt)
thrusts_alt.append(result['thrust_N'] / 1000)
axes[1, 2].plot(altitudes, thrusts_alt, 'g-o', linewidth=2, markersize=6)
axes[1, 2].set_xlabel('高度 (m)')
axes[1, 2].set_ylabel('推力 (kN)')
axes[1, 2].set_title('推力 vs 高度')
axes[1, 2].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
def print_results(self, results: Dict):
"""打印仿真结果"""
print("\n" + "="*60)
print(f"发动机: {self.config.name}")
print("="*60)
print(f"燃料流量: {results['fuel_flow']:.2f} kg/s")
print(f"氧化剂流量: {results['oxidizer_flow']:.2f} kg/s")
print(f"总质量流量: {results['total_flow']:.2f} kg/s")
print(f"混合比 (O/F): {results['mixture_ratio']:.2f}")
print(f"推力: {results['thrust_N']/1000:.2f} kN")
print(f"推力: {results['thrust_kgf']:.2f} kgf")
print(f"比冲: {results['specific_impulse']:.2f} s")
print(f"特征速度: {results['chamber']['characteristic_velocity']:.2f} m/s")
print(f"推力系数: {results['nozzle']['thrust_coefficient']:.2f}")
print(f"喉部面积: {results['chamber']['throat_area']*10000:.2f} cm²")
print(f"喷管面积比: {results['nozzle']['expansion_ratio']:.2f}")
print(f"出口压力: {results['nozzle']['exit_pressure']/1000:.2f} kPa")
print(f"环境压力: {results['nozzle']['ambient_pressure']/1000:.2f} kPa")
print("="*60)
def main():
"""主函数 - 演示如何使用仿真系统"""
# 1. 创建发动机配置
config = EngineConfig(
name="液氢液氧上面级发动机",
chamber_pressure=4.0e6, # 4 MPa
mixture_ratio=6.0,
nozzle_area_ratio=80.0,
chamber_temp=3600.0,
specific_heat_ratio=1.2,
molar_mass=0.016,
efficiency_combustion=0.99,
efficiency_nozzle=0.97
)
# 2. 创建发动机实例
engine = LiquidRocketEngine(config)
# 3. 添加推进剂
lh2 = Propellant("液氢", density=70.0, specific_heat=14300.0)
lox = Propellant("液氧", density=1141.0, specific_heat=1700.0)
engine.add_propellant("fuel", lh2)
engine.add_propellant("oxidizer", lox)
# 4. 运行稳态仿真
print("正在进行稳态仿真...")
results = engine.run_steady_state(fuel_flow=5.0, altitude=0.0)
engine.print_results(results)
# 5. 运行瞬态仿真
print("\n正在进行瞬态仿真 (启动过程)...")
transient_results = engine.run_transient_simulation(duration=5.0, dt=0.05)
# 6. 绘制结果
print("\n生成仿真图表...")
engine.plot_results(transient_results)
# 7. 运行参数扫描
print("\n进行参数扫描分析...")
print("\n混合比对性能的影响:")
print("-"*50)
print("混合比 | 推力(kN) | 比冲(s)")
print("-"*50)
for mr in [4.0, 5.0, 6.0, 7.0, 8.0]:
engine.config.mixture_ratio = mr
scan_result = engine.run_steady_state(fuel_flow=5.0)
print(f"{mr:6.1f} | {scan_result['thrust_N']/1000:8.2f} | {scan_result['specific_impulse']:7.2f}")
return engine
if __name__ == "__main__":
print("液体火箭发动机数字仿真系统")
print("="*60)
# 运行仿真
engine_sim = main()
print("\n仿真完成!")
系统特性
这个液体火箭发动机数字仿真系统包含以下主要模块:
1. 核心类
EngineConfig: 发动机配置参数Propellant: 推进剂物理属性LiquidRocketEngine: 发动机仿真主类
2. 物理模型
- 质量流量计算(基于混合比)
- 燃烧室热力学计算
- 喷管等熵流动计算
- 推力与比冲计算
- 瞬态响应模拟
3. 仿真功能
- 稳态性能分析
- 瞬态启动过程仿真
- 参数扫描(混合比、高度等)
- 结果可视化
4. 使用示例
# 快速使用示例
config = EngineConfig(
name="自定义发动机",
chamber_pressure=3.0e6, # 3 MPa
mixture_ratio=5.5,
nozzle_area_ratio=50.0
)
engine = LiquidRocketEngine(config)
# 添加推进剂
engine.add_propellant("fuel", Propellant("RP-1", 810, 2090))
engine.add_propellant("oxidizer", Propellant("液氧", 1141, 1700))
# 运行仿真
results = engine.run_steady_state(fuel_flow=10.0)
系统要求
# 所需Python库
numpy>=1.20.0
matplotlib>=3.5.0
scipy>=1.7.0
扩展建议
这个基础系统可以扩展以下功能:
- 真实气体效应 - 添加实际气体状态方程
- 两相流计算 - 考虑燃烧产物的相变
- 传热分析 - 再生冷却和热防护
- 控制系统 - PID控制器和故障模拟
- 优化算法 - 自动优化发动机参数
- 3D可视化 - 使用PyVista或Mayavi进行流场显示
注意事项
- 这是一个教学演示系统,实际工程应用需要更精确的模型
- 考虑了基本的等熵流动假设,实际发动机有各种损失
- 推进剂属性需要根据实际数据进行调整
- 瞬态模型是高度简化的,实际动态响应更复杂
这个系统提供了一个可扩展的框架,您可以根据具体需求添加更多物理模型和仿真功能。