液体火箭发动机简化数字仿真系统

以下是一个简化的液体火箭发动机数字仿真系统的Python实现。这个系统包含了基本的推进剂流量、燃烧室、喷管和性能计算模块。

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. 使用示例

ini 复制代码
# 快速使用示例
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)

系统要求

shell 复制代码
# 所需Python库
numpy>=1.20.0
matplotlib>=3.5.0
scipy>=1.7.0

扩展建议

这个基础系统可以扩展以下功能:

  1. 真实气体效应 - 添加实际气体状态方程
  2. 两相流计算 - 考虑燃烧产物的相变
  3. 传热分析 - 再生冷却和热防护
  4. 控制系统 - PID控制器和故障模拟
  5. 优化算法 - 自动优化发动机参数
  6. 3D可视化 - 使用PyVista或Mayavi进行流场显示

注意事项

  1. 这是一个教学演示系统,实际工程应用需要更精确的模型
  2. 考虑了基本的等熵流动假设,实际发动机有各种损失
  3. 推进剂属性需要根据实际数据进行调整
  4. 瞬态模型是高度简化的,实际动态响应更复杂

这个系统提供了一个可扩展的框架,您可以根据具体需求添加更多物理模型和仿真功能。

相关推荐
LabVIEW开发1 小时前
LabVIEW QMH 队列消息处理架构
架构·labview·labview知识·labview功能·labview程序
rising start2 小时前
二、全面理解MySQL架构
mysql·架构
麦客奥德彪2 小时前
Android Skills
架构·ai编程
candyTong3 小时前
Claude Code 的 Edit 工具是怎么工作的
javascript·后端·架构
沪漂阿龙4 小时前
面试题详解:智能客服 Agent 系统全栈拆解——Rasa Pro、对话管理、意图识别、GraphRAG、Qwen 与 RAG 优化实战
人工智能·架构
辰海Coding5 小时前
MiniSpring框架学习-完成的 IoC 容器
java·spring boot·学习·架构
云边云科技_云网融合6 小时前
企业大模型时代的网络架构五层演进:从连接到智能的范式重构
网络·重构·架构
Yunzenn6 小时前
字节最新研究cola-DLM第 01 章:语言生成的三次范式之争 —— 从 RNN 到 AR 到扩散
架构·github
她的男孩6 小时前
从零搭一个企业后台,为什么我把能力拆成 Starter 和 Plugin
java·后端·架构
啷里格啷6 小时前
第二章 Fast-DDS 整体架构与分层框架
后端·架构