第二十九篇:燃烧不稳定性

摘要

燃烧不稳定性是燃烧系统中常见的危险现象,表现为压力、热释放率的周期性振荡,可能导致设备损坏、性能下降甚至灾难性事故。本教程系统介绍燃烧不稳定性的物理机理、数学模型和分析方法。内容涵盖热声不稳定性的耦合机制、Rayleigh准则、特征模态分析、非线性效应等核心理论。通过Python仿真实验,读者将深入理解燃烧不稳定性的动力学行为,掌握线性稳定性分析、时域仿真、频谱分析等关键技术,为进行燃烧系统的稳定性评估和控制设计奠定坚实的理论基础。

关键词

燃烧不稳定性,热声耦合,Rayleigh准则,压力振荡,特征模态,稳定性分析,非线性效应


1. 燃烧不稳定性概述

1.1 定义与分类

燃烧不稳定性是指燃烧过程中出现的自持振荡现象,表现为压力、速度、热释放率等参数的周期性波动。

按物理机制分类

  1. 热声不稳定性(Thermoacoustic Instability)

    • 热释放波动与声场耦合
    • 最常见、危害最大
    • 发生在燃气轮机、火箭发动机、锅炉等
  2. 流体动力学不稳定性(Hydrodynamic Instability)

    • 剪切层、涡脱落引起
    • 与声学弱耦合
    • 如Kelvin-Helmholtz不稳定性
  3. 化学动力学不稳定性(Chemical Kinetic Instability)

    • 化学反应自催化引起
    • 如冷焰、热爆炸

按频率范围分类

  • 低频(<100 Hz):整体模式、Helmholtz模式
  • 中频(100-1000 Hz):纵向声学模式
  • 高频(>1000 Hz):径向/切向模式、本征燃烧噪声

1.2 工程危害

燃气轮机

  • 压力振荡幅值可达平均压力的10-20%
  • 导致部件疲劳、寿命缩短
  • 可能引发熄火或回火

火箭发动机

  • 振荡可能导致发动机爆炸
  • 历史上有多次发射失败案例
  • 是火箭发动机设计的核心挑战

工业燃烧器

  • 噪声污染
  • 效率降低
  • 污染物排放增加

2. 热声不稳定性物理机理

2.1 基本物理过程

热声耦合机制

  1. 扰动产生

    • 流动扰动(涡脱落、湍流)
    • 声学扰动(压力波反射)
    • 外部激励(阀门、泵)
  2. 火焰响应

    • 当量比波动
    • 速度波动改变火焰形状
    • 涡旋通过火焰前锋
  3. 热释放波动

    • 局部燃烧速率变化
    • 热量释放周期性变化
  4. 声波产生

    • 热释放波动作为声源
    • 声波在燃烧室中传播
  5. 反馈回路

    • 声波影响火焰
    • 形成自持振荡

2.2 Rayleigh准则

Rayleigh准则是判断热声不稳定性的经典准则:

如果在压力波的高压相位期间释放热量,振荡将被放大;反之,如果在低压相位期间释放热量,振荡将被阻尼。

数学表达

∮p′(t)⋅Q˙′(t) dt>0(不稳定)\oint p'(t) \cdot \dot{Q}'(t) \, dt > 0 \quad \text{(不稳定)}p(t)Q˙(t)dt>0(不稳定)

其中:

  • p′(t)p'(t)p(t):压力脉动
  • Q˙′(t)\dot{Q}'(t)Q˙(t):热释放率脉动

Rayleigh指数

R=1T∫0Tp′(t)⋅Q˙′(t) dtR = \frac{1}{T} \int_0^T p'(t) \cdot \dot{Q}'(t) \, dtR=T10Tp(t)Q˙(t)dt

  • R>0R > 0R>0:不稳定(能量输入)
  • R<0R < 0R<0:稳定(能量耗散)
  • R=0R = 0R=0:中性稳定

2.3 时间延迟模型

n-τ模型(Crocco模型):

热释放波动与速度波动的关系:

Q˙′(t)Qˉ=n⋅u′(t−τ)uˉ\frac{\dot{Q}'(t)}{\bar{Q}} = n \cdot \frac{u'(t-\tau)}{\bar{u}}QˉQ˙(t)=nuˉu(tτ)

其中:

  • nnn:相互作用指数(Interaction Index)
  • τ\tauτ:时间延迟(Time Delay)
  • u′u'u:速度脉动

物理意义

  • nnn:火焰对速度扰动的敏感程度
  • τ\tauτ:扰动从入口传播到火焰并产生热响应的时间

稳定性判据

对于简谐振荡 u′=u^eiωtu' = \hat{u} e^{i\omega t}u=u^et,稳定性取决于相位关系:

cos⁡(ωτ)>0(潜在不稳定)\cos(\omega \tau) > 0 \quad \text{(潜在不稳定)}cos(ωτ)>0(潜在不稳定)


3. 声学基础

3.1 波动方程

一维声波方程

∂2p′∂t2−c2∂2p′∂x2=0\frac{\partial^2 p'}{\partial t^2} - c^2 \frac{\partial^2 p'}{\partial x^2} = 0t22pc2x22p=0

其中 c=γRTc = \sqrt{\gamma R T}c=γRT 为声速。

带源项的波动方程

∂2p′∂t2−c2∂2p′∂x2=(γ−1)∂Q˙′∂t\frac{\partial^2 p'}{\partial t^2} - c^2 \frac{\partial^2 p'}{\partial x^2} = (\gamma - 1) \frac{\partial \dot{Q}'}{\partial t}t22pc2x22p=(γ1)tQ˙

热释放波动作为声源项。

3.2 声学模态

封闭管中的声学模态

纵向模式

fn=nc2L,n=1,2,3,…f_n = n \frac{c}{2L}, \quad n = 1, 2, 3, \dotsfn=n2Lc,n=1,2,3,

横向模式(圆形截面):

fmn=c2π(αmnR)2+(kπL)2f_{mn} = \frac{c}{2\pi} \sqrt{\left(\frac{\alpha_{mn}}{R}\right)^2 + \left(\frac{k\pi}{L}\right)^2}fmn=2πc(Rαmn)2+(L)2

其中 αmn\alpha_{mn}αmn 是Bessel函数的根。

3.3 边界条件

刚性壁面(速度为零):

∂p′∂x=0\frac{\partial p'}{\partial x} = 0xp=0

压力释放(开口端):

p′=0p' = 0p=0

阻抗边界

p′u′=Z\frac{p'}{u'} = Zup=Z

其中 ZZZ 为声学阻抗。


4. 线性稳定性分析

4.1 特征值问题

状态空间表示

将声学方程离散化,得到状态方程:

dxdt=Ax\frac{d\mathbf{x}}{dt} = \mathbf{A} \mathbf{x}dtdx=Ax

其中 x\mathbf{x}x 包含压力和速度的状态变量。

特征值分析

求解特征方程:

det⁡(A−λI)=0\det(\mathbf{A} - \lambda \mathbf{I}) = 0det(AλI)=0

  • Re(λ)>0\text{Re}(\lambda) > 0Re(λ)>0:不稳定
  • Re(λ)<0\text{Re}(\lambda) < 0Re(λ)<0:稳定
  • Re(λ)=0\text{Re}(\lambda) = 0Re(λ)=0:临界稳定

增长率

α=Re(λ)\alpha = \text{Re}(\lambda)α=Re(λ)

振荡频率

ω=Im(λ)\omega = \text{Im}(\lambda)ω=Im(λ)

4.2 网络分析法

将燃烧室分解为声学元件网络:

  • 管道段(传输矩阵)
  • 面积突变(散射矩阵)
  • 火焰(响应函数)
  • 边界(反射系数)

传输矩阵

(p^2u^2)=T(p^1u^1)\begin{pmatrix} \hat{p}_2 \\ \hat{u}_2 \end{pmatrix} = \mathbf{T} \begin{pmatrix} \hat{p}_1 \\ \hat{u}_1 \end{pmatrix}(p^2u^2)=T(p^1u^1)

稳定性判据

回路增益条件:

det⁡(I−RdownTRupT)=0\det(\mathbf{I} - \mathbf{R}_{down} \mathbf{T} \mathbf{R}_{up} \mathbf{T}) = 0det(IRdownTRupT)=0

4.3 Nyquist判据

开环传递函数

G(s)=F(s)⋅H(s)G(s) = F(s) \cdot H(s)G(s)=F(s)H(s)

其中:

  • F(s)F(s)F(s):火焰传递函数
  • H(s)H(s)H(s):声学传递函数

Nyquist判据

如果开环传递函数的Nyquist图包围(-1, 0)点,则闭环系统不稳定。


5. 火焰传递函数

5.1 定义与测量

火焰传递函数(FTF)

F(ω)=Q^′/Qˉu^′/uˉ=G(ω)eiϕ(ω)F(\omega) = \frac{\hat{Q}'/\bar{Q}}{\hat{u}'/\bar{u}} = G(\omega) e^{i\phi(\omega)}F(ω)=u^/uˉQ^/Qˉ=G(ω)eiϕ(ω)

其中:

  • G(ω)G(\omega)G(ω):增益
  • ϕ(ω)\phi(\omega)ϕ(ω):相位

测量方法

  1. 扬声器激励法
  2. 燃料调制法
  3. 激光诊断法

5.2 典型火焰传递函数模型

时延模型

F(ω)=n⋅e−iωτF(\omega) = n \cdot e^{-i\omega \tau}F(ω)=neτ

低通滤波器模型

F(ω)=n1+iωτfF(\omega) = \frac{n}{1 + i\omega \tau_f}F(ω)=1+τfn

二阶模型

F(ω)=n(1+iωτ1)(1+iωτ2)F(\omega) = \frac{n}{(1 + i\omega \tau_1)(1 + i\omega \tau_2)}F(ω)=(1+τ1)(1+τ2)n

5.3 火焰描述函数

火焰描述函数(FDF)

考虑非线性效应,增益和相位依赖于扰动幅值:

F(A,ω)=G(A,ω)eiϕ(A,ω)F(A, \omega) = G(A, \omega) e^{i\phi(A, \omega)}F(A,ω)=G(A,ω)eiϕ(A,ω)

饱和效应

随着扰动幅值增大,火焰响应趋于饱和:

G(A)=G01+(A/Asat)2G(A) = \frac{G_0}{1 + (A/A_{sat})^2}G(A)=1+(A/Asat)2G0


6. 非线性效应与极限环

6.1 非线性来源

火焰非线性

  • 热释放饱和
  • 火焰吹熄
  • 当量比极限

声学非线性

  • 激波形成
  • 高幅值下的波形畸变

流动非线性

  • 涡脱落
  • 湍流混合

6.2 极限环振荡

定义

非线性系统达到的稳定周期性振荡状态,幅值不再增长。

产生机制

线性不稳定 + 非线性饱和 → 极限环

描述

van der Pol振子模型:

x¨−μ(1−x2)x˙+ω02x=0\ddot{x} - \mu(1-x^2)\dot{x} + \omega_0^2 x = 0x¨μ(1x2)x˙+ω02x=0

  • μ>0\mu > 0μ>0:自激振荡
  • x2x^2x2项:非线性阻尼

6.3 幅值方程

慢变幅值近似

设解的形式:

x(t)=A(t)cos⁡(ωt+ϕ(t))x(t) = A(t) \cos(\omega t + \phi(t))x(t)=A(t)cos(ωt+ϕ(t))

幅值演化方程:

dAdt=αA−βA3\frac{dA}{dt} = \alpha A - \beta A^3dtdA=αAβA3

其中:

  • α\alphaα:线性增长率
  • β\betaβ:非线性饱和系数

稳态幅值

Aeq=αβA_{eq} = \sqrt{\frac{\alpha}{\beta}}Aeq=βα


7. 稳定性控制方法

7.1 被动控制

声学阻尼器

  1. Helmholtz谐振器

    • 调谐到不稳定频率
    • 吸收声能
  2. 多孔材料

    • 增加粘性耗散
    • 宽带阻尼
  3. 四分之一波长管

    • 特定频率吸收
    • 结构简单

几何修改

  • 改变燃烧室长度
  • 调整火焰位置
  • 优化入口条件

7.2 主动控制

反馈控制

uact=−K⋅p′(t−τc)u_{act} = -K \cdot p'(t-\tau_c)uact=Kp(tτc)

其中:

  • KKK:控制增益
  • τc\tau_cτc:控制延迟

前馈控制

uact=−K⋅uinlet′(t)u_{act} = -K \cdot u_{inlet}'(t)uact=Kuinlet(t)

自适应控制

  • 在线识别系统参数
  • 自动调整控制策略

7.3 燃料调制

原理

通过调制燃料流量改变热释放相位,破坏Rayleigh准则。

策略

m˙f′=−Kf⋅p′(t−τf)\dot{m}_f' = -K_f \cdot p'(t-\tau_f)m˙f=Kfp(tτf)

优化相位 ωτf\omega \tau_fωτf 使Rayleigh指数最小。


8. Python仿真实验

8.1 实验1:声学模态分析

实验目的:计算一维燃烧室的声学特征频率和模态形状。

import matplotlib
matplotlib.use('Agg')
import numpy as np
import matplotlib.pyplot as plt
from scipy.linalg import eig
import os

output_dir = r'd:\文档\燃烧仿真\主题029'
os.makedirs(output_dir, exist_ok=True)

plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False

print("="*60)
print("主题029:燃烧不稳定性")
print("="*60)

# ============================================================
# 实验1:声学模态分析
# ============================================================
print("\n实验1:声学模态分析")
print("-" * 40)

# 燃烧室参数
L = 1.0  # 燃烧室长度 (m)
T_mean = 1500  # 平均温度 (K)
gamma = 1.4  # 比热比
R = 287  # 气体常数 (J/kg·K)

# 声速
c = np.sqrt(gamma * R * T_mean)
print(f"声速: {c:.1f} m/s")

# 理论特征频率(两端开口)
n_modes = 5
f_theory = n_modes * c / (2 * L)
print(f"第一阶理论频率: {c/(2*L):.1f} Hz")

# 数值求解(有限差分法)
N = 100  # 网格数
dx = L / N
x = np.linspace(0, L, N+1)

# 构建二阶导数矩阵(Neumann边界条件)
A = np.zeros((N+1, N+1))
for i in range(1, N):
    A[i, i-1] = 1
    A[i, i] = -2
    A[i, i+1] = 1
A[0, 0] = -1
A[0, 1] = 1
A[N, N-1] = 1
A[N, N] = -1

A = A / dx**2

# 求解特征值问题
eigenvalues, eigenvectors = eig(A)

# 筛选物理特征值
k2 = -eigenvalues
k_phys = k2[k2 > 0]
f_num = np.sqrt(k_phys) * c / (2 * np.pi)
f_num = np.sort(f_num)[:n_modes]

print(f"数值计算的前{n_modes}阶频率:")
for i, f in enumerate(f_num):
    print(f"  模式{i+1}: {f:.1f} Hz")

fig, axes = plt.subplots(2, 2, figsize=(14, 10))

# 1. 特征频率对比
ax1 = axes[0, 0]
modes = np.arange(1, n_modes + 1)
f_theory_modes = modes * c / (2 * L)
ax1.bar(modes - 0.2, f_theory_modes, 0.4, label='Theory', alpha=0.7)
ax1.bar(modes + 0.2, f_num, 0.4, label='Numerical', alpha=0.7)
ax1.set_xlabel('Mode Number', fontsize=11)
ax1.set_ylabel('Frequency (Hz)', fontsize=11)
ax1.set_title('Acoustic Mode Frequencies', fontsize=12, fontweight='bold')
ax1.legend(fontsize=10)
ax1.grid(True, alpha=0.3, axis='y')

# 2. 模态形状
ax2 = axes[0, 1]
for i in range(min(4, n_modes)):
    # 理论模态形状
    mode_shape = np.cos((i+1) * np.pi * x / L)
    ax2.plot(x/L, mode_shape, linewidth=2, label=f'Mode {i+1} ({f_theory_modes[i]:.0f} Hz)')
ax2.set_xlabel('x/L', fontsize=11)
ax2.set_ylabel('Pressure Amplitude', fontsize=11)
ax2.set_title('Acoustic Mode Shapes', fontsize=12, fontweight='bold')
ax2.legend(fontsize=9)
ax2.grid(True, alpha=0.3)
ax2.axhline(y=0, color='k', linestyle='-', linewidth=0.5)

# 3. 温度对频率的影响
ax3 = axes[1, 0]
T_range = np.linspace(300, 2000, 50)
f_vs_T = [np.sqrt(gamma * R * T) / (2 * L) for T in T_range]
ax3.plot(T_range, f_vs_T, 'b-', linewidth=2.5)
ax3.set_xlabel('Temperature (K)', fontsize=11)
ax3.set_ylabel('Fundamental Frequency (Hz)', fontsize=11)
ax3.set_title('Temperature Effect on Acoustic Frequency', fontsize=12, fontweight='bold')
ax3.grid(True, alpha=0.3)

# 4. 长度对频率的影响
ax4 = axes[1, 1]
L_range = np.linspace(0.3, 3.0, 50)
f_vs_L = [c / (2 * L_val) for L_val in L_range]
ax4.plot(L_range, f_vs_L, 'r-', linewidth=2.5)
ax4.set_xlabel('Combustor Length (m)', fontsize=11)
ax4.set_ylabel('Fundamental Frequency (Hz)', fontsize=11)
ax4.set_title('Length Effect on Acoustic Frequency', fontsize=12, fontweight='bold')
ax4.grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig(f'{output_dir}/exp1_acoustic_modes.png', dpi=150, bbox_inches='tight')
plt.close()

print("✓ 实验1完成:声学模态分析")

# ============================================================
# 实验2:Rayleigh准则验证
# ============================================================
print("\n实验2:Rayleigh准则验证")
print("-" * 40)

# 模拟压力和热释放的相位关系
t = np.linspace(0, 0.1, 1000)
f_osc = 200  # 振荡频率 (Hz)
omega = 2 * np.pi * f_osc

# 压力脉动
p_amp = 1000  # Pa
p_prime = p_amp * np.cos(omega * t)

# 不同相位的热释放脉动
phi_range = np.linspace(-np.pi, np.pi, 100)
Rayleigh_index = []

for phi in phi_range:
    Q_prime = np.cos(omega * t + phi)
    # Rayleigh指数(时间平均)
    R = np.mean(p_prime * Q_prime)
    Rayleigh_index.append(R)

Rayleigh_index = np.array(Rayleigh_index)

fig, axes = plt.subplots(2, 2, figsize=(14, 10))

# 1. Rayleigh指数vs相位
ax1 = axes[0, 0]
ax1.plot(phi_range * 180/np.pi, Rayleigh_index/1e3, 'b-', linewidth=2.5)
ax1.axhline(y=0, color='k', linestyle='--', linewidth=1)
ax1.fill_between(phi_range * 180/np.pi, 0, Rayleigh_index/1e3, 
                  where=(Rayleigh_index > 0), alpha=0.3, color='red', label='Unstable')
ax1.fill_between(phi_range * 180/np.pi, 0, Rayleigh_index/1e3, 
                  where=(Rayleigh_index < 0), alpha=0.3, color='green', label='Stable')
ax1.set_xlabel('Phase Difference (deg)', fontsize=11)
ax1.set_ylabel('Rayleigh Index (x1000)', fontsize=11)
ax1.set_title('Rayleigh Criterion', fontsize=12, fontweight='bold')
ax1.legend(fontsize=10)
ax1.grid(True, alpha=0.3)
ax1.set_xlim([-180, 180])

# 2. 不稳定相位示例
ax2 = axes[0, 1]
phi_unstable = 0  # 同相位
Q_unstable = np.cos(omega * t + phi_unstable)
ax2.plot(t*1000, p_prime/1e3, 'b-', linewidth=2, label='Pressure')
ax2.plot(t*1000, Q_unstable*500, 'r-', linewidth=2, label='Heat Release')
ax2.set_xlabel('Time (ms)', fontsize=11)
ax2.set_ylabel('Amplitude', fontsize=11)
ax2.set_title(f'Unstable Phase (φ={phi_unstable*180/np.pi:.0f}°)', fontsize=12, fontweight='bold')
ax2.legend(fontsize=10)
ax2.grid(True, alpha=0.3)
ax2.set_xlim([0, 20])

# 3. 稳定相位示例
ax3 = axes[1, 0]
phi_stable = np.pi  # 反相位
Q_stable = np.cos(omega * t + phi_stable)
ax3.plot(t*1000, p_prime/1e3, 'b-', linewidth=2, label='Pressure')
ax3.plot(t*1000, Q_stable*500, 'g-', linewidth=2, label='Heat Release')
ax3.set_xlabel('Time (ms)', fontsize=11)
ax3.set_ylabel('Amplitude', fontsize=11)
ax3.set_title(f'Stable Phase (φ={phi_stable*180/np.pi:.0f}°)', fontsize=12, fontweight='bold')
ax3.legend(fontsize=10)
ax3.grid(True, alpha=0.3)
ax3.set_xlim([0, 20])

# 4. 时间延迟效应
ax4 = axes[1, 1]
tau_range = np.linspace(0, 5e-3, 100)  # 0-5 ms
omega_tau = omega * tau_range
cos_omega_tau = np.cos(omega_tau)
ax4.plot(tau_range*1000, cos_omega_tau, 'b-', linewidth=2.5)
ax4.axhline(y=0, color='k', linestyle='--', linewidth=1)
ax4.fill_between(tau_range*1000, -1, cos_omega_tau, 
                  where=(cos_omega_tau > 0), alpha=0.3, color='red', label='Unstable')
ax4.fill_between(tau_range*1000, -1, cos_omega_tau, 
                  where=(cos_omega_tau < 0), alpha=0.3, color='green', label='Stable')
ax4.set_xlabel('Time Delay (ms)', fontsize=11)
ax4.set_ylabel('cos(ωτ)', fontsize=11)
ax4.set_title('Time Delay Effect on Stability', fontsize=12, fontweight='bold')
ax4.legend(fontsize=10)
ax4.grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig(f'{output_dir}/exp2_rayleigh_criterion.png', dpi=150, bbox_inches='tight')
plt.close()

print("✓ 实验2完成:Rayleigh准则验证")

# ============================================================
# 实验3:火焰传递函数
# ============================================================
print("\n实验3:火焰传递函数")
print("-" * 40)

# 火焰传递函数模型
# F(ω) = n * exp(-iωτ) / (1 + iωτ_f)
n_ftf = 2.0  # 相互作用指数
tau = 2e-3  # 时间延迟 (s)
tau_f = 1e-3  # 滤波器时间常数 (s)

# 频率范围
f_range = np.linspace(10, 1000, 500)
omega_range = 2 * np.pi * f_range

# 计算FTF
s = 1j * omega_range
F_ftf = n_ftf * np.exp(-s * tau) / (1 + s * tau_f)
G_ftf = np.abs(F_ftf)
phi_ftf = np.angle(F_ftf) * 180 / np.pi

fig, axes = plt.subplots(2, 2, figsize=(14, 10))

# 1. 增益曲线
ax1 = axes[0, 0]
ax1.semilogy(f_range, G_ftf, 'b-', linewidth=2.5)
ax1.set_xlabel('Frequency (Hz)', fontsize=11)
ax1.set_ylabel('Gain |F(ω)|', fontsize=11)
ax1.set_title('Flame Transfer Function Gain', fontsize=12, fontweight='bold')
ax1.grid(True, alpha=0.3)
ax1.axhline(y=1, color='r', linestyle='--', linewidth=1.5, label='Unity Gain')
ax1.legend(fontsize=10)

# 2. 相位曲线
ax2 = axes[0, 1]
ax2.plot(f_range, phi_ftf, 'b-', linewidth=2.5)
ax2.set_xlabel('Frequency (Hz)', fontsize=11)
ax2.set_ylabel('Phase (deg)', fontsize=11)
ax2.set_title('Flame Transfer Function Phase', fontsize=12, fontweight='bold')
ax2.grid(True, alpha=0.3)
ax2.set_ylim([-360, 0])

# 3. Nyquist图
ax3 = axes[1, 0]
ax3.plot(F_ftf.real, F_ftf.imag, 'b-', linewidth=2.5)
ax3.plot(-1, 0, 'r*', markersize=15, label='Critical Point')
ax3.set_xlabel('Real(F)', fontsize=11)
ax3.set_ylabel('Imag(F)', fontsize=11)
ax3.set_title('Nyquist Plot of FTF', fontsize=12, fontweight='bold')
ax3.legend(fontsize=10)
ax3.grid(True, alpha=0.3)
ax3.axis('equal')

# 4. 不同时间延迟的比较
ax4 = axes[1, 1]
tau_values = [1e-3, 2e-3, 3e-3, 4e-3]
colors_tau = plt.cm.viridis(np.linspace(0, 1, len(tau_values)))

for i, tau_val in enumerate(tau_values):
    F_val = n_ftf * np.exp(-s * tau_val) / (1 + s * tau_f)
    ax4.plot(f_range, np.angle(F_val) * 180 / np.pi, 
             linewidth=2, color=colors_tau[i], label=f'τ={tau_val*1000:.0f}ms')

ax4.set_xlabel('Frequency (Hz)', fontsize=11)
ax4.set_ylabel('Phase (deg)', fontsize=11)
ax4.set_title('Phase for Different Time Delays', fontsize=12, fontweight='bold')
ax4.legend(fontsize=10)
ax4.grid(True, alpha=0.3)
ax4.set_ylim([-360, 0])

plt.tight_layout()
plt.savefig(f'{output_dir}/exp3_flame_transfer_function.png', dpi=150, bbox_inches='tight')
plt.close()

print("✓ 实验3完成:火焰传递函数")

# ============================================================
# 实验4:热声耦合稳定性分析
# ============================================================
print("\n实验4:热声耦合稳定性分析")
print("-" * 40)

# 简化的热声系统模型
# 使用n-τ模型和声学模态

# 系统参数
L_burner = 0.5  # 燃烧器长度 (m)
c_sound = 500  # 声速 (m/s)
n_interaction = 1.5  # 相互作用指数
tau_delay = 1.5e-3  # 时间延迟 (s)
alpha_damping = 50  # 声学阻尼系数 (1/s)

# 声学特征频率
f_acoustic = c_sound / (2 * L_burner)
omega_acoustic = 2 * np.pi * f_acoustic
print(f"声学特征频率: {f_acoustic:.1f} Hz")

# 线性化系统的特征值分析
# 简化为二阶系统 + 时延反馈

# 求解特征方程:s^2 + 2*alpha*s + omega0^2 = K*exp(-s*tau)
# 数值求解

def characteristic_eq(s, omega0, alpha, K, tau):
    """特征方程"""
    return s**2 + 2*alpha*s + omega0**2 - K * np.exp(-s * tau)

# 参数扫描
K_range = np.linspace(0, 50000, 100)  # 耦合强度
solutions = []

for K in K_range:
    # 使用牛顿法或扫描法寻找特征值
    # 简化为寻找主导模态
    
    # 近似解:假设 s = sigma + i*omega
    # 迭代求解
    sigma = 0
    omega = omega_acoustic
    
    for _ in range(50):  # 迭代
        s = sigma + 1j * omega
        f_val = characteristic_eq(s, omega_acoustic, alpha_damping, K, tau_delay)
        
        # 简单的梯度下降
        ds = 1e-6
        df_dsigma = (characteristic_eq(s + ds, omega_acoustic, alpha_damping, K, tau_delay) - f_val) / ds
        df_domega = (characteristic_eq(s + 1j*ds, omega_acoustic, alpha_damping, K, tau_delay) - f_val) / (1j*ds)
        
        sigma -= 0.01 * (f_val.real / df_dsigma.real if abs(df_dsigma.real) > 1e-10 else 0)
        omega -= 0.01 * (f_val.imag / df_domega.imag if abs(df_domega.imag) > 1e-10 else 0)
    
    solutions.append((sigma, omega))

solutions = np.array(solutions)
growth_rate = solutions[:, 0]
frequency = solutions[:, 1] / (2 * np.pi)

fig, axes = plt.subplots(2, 2, figsize=(14, 10))

# 1. 增长率vs耦合强度
ax1 = axes[0, 0]
ax1.plot(K_range/1000, growth_rate, 'b-', linewidth=2.5)
ax1.axhline(y=0, color='r', linestyle='--', linewidth=1.5)
ax1.fill_between(K_range/1000, 0, growth_rate, where=(growth_rate > 0), 
                  alpha=0.3, color='red', label='Unstable')
ax1.fill_between(K_range/1000, 0, growth_rate, where=(growth_rate < 0), 
                  alpha=0.3, color='green', label='Stable')
ax1.set_xlabel('Coupling Strength K (x1000)', fontsize=11)
ax1.set_ylabel('Growth Rate (1/s)', fontsize=11)
ax1.set_title('Growth Rate vs Coupling Strength', fontsize=12, fontweight='bold')
ax1.legend(fontsize=10)
ax1.grid(True, alpha=0.3)

# 2. 频率vs耦合强度
ax2 = axes[0, 1]
ax2.plot(K_range/1000, frequency, 'b-', linewidth=2.5)
ax2.axhline(y=f_acoustic, color='r', linestyle='--', linewidth=1.5, label=f'Acoustic {f_acoustic:.0f} Hz')
ax2.set_xlabel('Coupling Strength K (x1000)', fontsize=11)
ax2.set_ylabel('Frequency (Hz)', fontsize=11)
ax2.set_title('Oscillation Frequency vs Coupling', fontsize=12, fontweight='bold')
ax2.legend(fontsize=10)
ax2.grid(True, alpha=0.3)

# 3. 时间延迟影响
ax3 = axes[1, 0]
tau_range = np.linspace(0.5e-3, 4e-3, 100)
growth_vs_tau = []

for tau in tau_range:
    sigma = 0
    omega = omega_acoustic
    K_fixed = 20000
    
    for _ in range(50):
        s = sigma + 1j * omega
        f_val = characteristic_eq(s, omega_acoustic, alpha_damping, K_fixed, tau)
        ds = 1e-6
        df_dsigma = (characteristic_eq(s + ds, omega_acoustic, alpha_damping, K_fixed, tau) - f_val) / ds
        sigma -= 0.01 * (f_val.real / df_dsigma.real if abs(df_dsigma.real) > 1e-10 else 0)
    
    growth_vs_tau.append(sigma)

ax3.plot(tau_range*1000, growth_vs_tau, 'b-', linewidth=2.5)
ax3.axhline(y=0, color='r', linestyle='--', linewidth=1.5)
ax3.fill_between(tau_range*1000, 0, growth_vs_tau, where=(np.array(growth_vs_tau) > 0), 
                  alpha=0.3, color='red', label='Unstable')
ax3.fill_between(tau_range*1000, 0, growth_vs_tau, where=(np.array(growth_vs_tau) < 0), 
                  alpha=0.3, color='green', label='Stable')
ax3.set_xlabel('Time Delay (ms)', fontsize=11)
ax3.set_ylabel('Growth Rate (1/s)', fontsize=11)
ax3.set_title('Effect of Time Delay on Stability', fontsize=12, fontweight='bold')
ax3.legend(fontsize=10)
ax3.grid(True, alpha=0.3)

# 4. 稳定性边界图
ax4 = axes[1, 1]
n_tau = 50
K_grid = np.linspace(0, 50000, n_tau)
tau_grid = np.linspace(0.5e-3, 4e-3, n_tau)
K_mesh, tau_mesh = np.meshgrid(K_grid, tau_grid)

stability_map = np.zeros_like(K_mesh)

for i in range(n_tau):
    for j in range(n_tau):
        sigma = 0
        for _ in range(30):
            s = sigma + 1j * omega_acoustic
            f_val = characteristic_eq(s, omega_acoustic, alpha_damping, K_mesh[i,j], tau_mesh[i,j])
            ds = 1e-6
            df_dsigma = (characteristic_eq(s + ds, omega_acoustic, alpha_damping, K_mesh[i,j], tau_mesh[i,j]) - f_val) / ds
            if abs(df_dsigma.real) > 1e-10:
                sigma -= 0.01 * f_val.real / df_dsigma.real
        stability_map[i, j] = sigma

contour = ax4.contourf(K_mesh/1000, tau_mesh*1000, stability_map, levels=20, cmap='RdYlGn')
ax4.contour(K_mesh/1000, tau_mesh*1000, stability_map, levels=[0], colors='k', linewidths=2)
ax4.set_xlabel('Coupling Strength K (x1000)', fontsize=11)
ax4.set_ylabel('Time Delay (ms)', fontsize=11)
ax4.set_title('Stability Map', fontsize=12, fontweight='bold')
cbar = plt.colorbar(contour, ax=ax4)
cbar.set_label('Growth Rate (1/s)', fontsize=10)

plt.tight_layout()
plt.savefig(f'{output_dir}/exp4_thermoacoustic_stability.png', dpi=150, bbox_inches='tight')
plt.close()

print("✓ 实验4完成:热声耦合稳定性分析")

# ============================================================
# 实验5:极限环振荡
# ============================================================
print("\n实验5:极限环振荡")
print("-" * 40)

# 非线性振荡模型(van der Pol类型)
def nonlinear_oscillator(y, t, alpha, beta, omega0):
    """
    非线性振荡器
    y[0]: 位移
    y[1]: 速度
    """
    x, v = y
    # van der Pol方程: x'' - alpha*(1-beta*x^2)*x' + omega0^2*x = 0
    dvdt = alpha * (1 - beta * x**2) * v - omega0**2 * x
    dxdt = v
    return [dxdt, dvdt]

# 参数
alpha_nl = 10  # 线性增长率
beta_nl = 0.01  # 非线性饱和系数
omega0_nl = 2 * np.pi * 200  # 固有频率

# 时间积分
t_nl = np.linspace(0, 0.5, 5000)
y0_small = [0.1, 0]  # 小初始条件
y0_large = [5.0, 0]  # 大初始条件

solution_small = odeint(nonlinear_oscillator, y0_small, t_nl, args=(alpha_nl, beta_nl, omega0_nl))
solution_large = odeint(nonlinear_oscillator, y0_large, t_nl, args=(alpha_nl, beta_nl, omega0_nl))

x_small = solution_small[:, 0]
x_large = solution_large[:, 0]

fig, axes = plt.subplots(2, 2, figsize=(14, 10))

# 1. 小初始条件的演化
ax1 = axes[0, 0]
ax1.plot(t_nl*1000, x_small, 'b-', linewidth=1.5)
ax1.set_xlabel('Time (ms)', fontsize=11)
ax1.set_ylabel('Amplitude', fontsize=11)
ax1.set_title('Limit Cycle - Small Initial Condition', fontsize=12, fontweight='bold')
ax1.grid(True, alpha=0.3)
ax1.set_xlim([0, 100])

# 2. 大初始条件的演化
ax2 = axes[0, 1]
ax2.plot(t_nl*1000, x_large, 'r-', linewidth=1.5)
ax2.set_xlabel('Time (ms)', fontsize=11)
ax2.set_ylabel('Amplitude', fontsize=11)
ax2.set_title('Limit Cycle - Large Initial Condition', fontsize=12, fontweight='bold')
ax2.grid(True, alpha=0.3)
ax2.set_xlim([0, 100])

# 3. 相图
ax3 = axes[1, 0]
ax3.plot(x_small, solution_small[:, 1], 'b-', linewidth=1, alpha=0.7, label='Small IC')
ax3.plot(x_large, solution_large[:, 1], 'r-', linewidth=1, alpha=0.7, label='Large IC')
ax3.set_xlabel('x', fontsize=11)
ax3.set_ylabel('v = dx/dt', fontsize=11)
ax3.set_title('Phase Portrait', fontsize=12, fontweight='bold')
ax3.legend(fontsize=10)
ax3.grid(True, alpha=0.3)
ax3.axis('equal')

# 4. 幅值演化(包络)
ax4 = axes[1, 1]
# 计算包络
from scipy.signal import hilbert
envelope_small = np.abs(hilbert(x_small))
envelope_large = np.abs(hilbert(x_large))

ax4.plot(t_nl*1000, envelope_small, 'b-', linewidth=2, label='Small IC')
ax4.plot(t_nl*1000, envelope_large, 'r-', linewidth=2, label='Large IC')
# 理论稳态幅值
A_steady = np.sqrt(alpha_nl / beta_nl)
ax4.axhline(y=A_steady, color='k', linestyle='--', linewidth=2, label=f'Steady State A={A_steady:.1f}')
ax4.set_xlabel('Time (ms)', fontsize=11)
ax4.set_ylabel('Envelope Amplitude', fontsize=11)
ax4.set_title('Amplitude Evolution', fontsize=12, fontweight='bold')
ax4.legend(fontsize=10)
ax4.grid(True, alpha=0.3)
ax4.set_xlim([0, 200])

plt.tight_layout()
plt.savefig(f'{output_dir}/exp5_limit_cycle.png', dpi=150, bbox_inches='tight')
plt.close()

print("✓ 实验5完成:极限环振荡")
print(f"  稳态幅值: {A_steady:.2f}")

# ============================================================
# 实验6:主动控制仿真
# ============================================================
print("\n实验6:主动控制仿真")
print("-" * 40)

# 受控热声系统
def controlled_thermoacoustic(y, t, alpha, beta, omega0, K_control, tau_control):
    """
    带主动控制的非线性振荡器
    """
    x, v = y
    
    # 控制信号(时延反馈)
    # 简化为直接反馈(无时延)
    u_control = -K_control * x
    
    # 受控系统
    dvdt = alpha * (1 - beta * x**2) * v - omega0**2 * x + u_control
    dxdt = v
    return [dxdt, dvdt]

# 参数
alpha_ctrl = 20  # 不稳定的线性增长率
beta_ctrl = 0.01
omega0_ctrl = 2 * np.pi * 200

# 不同控制增益
t_ctrl = np.linspace(0, 0.3, 3000)
K_values = [0, 50, 100, 200]
colors_ctrl = plt.cm.viridis(np.linspace(0, 1, len(K_values)))

fig, axes = plt.subplots(2, 2, figsize=(14, 10))

# 1. 不同控制增益下的响应
ax1 = axes[0, 0]
for i, K in enumerate(K_values):
    y0 = [1.0, 0]
    sol = odeint(controlled_thermoacoustic, y0, t_ctrl, 
                 args=(alpha_ctrl, beta_ctrl, omega0_ctrl, K, 0))
    ax1.plot(t_ctrl*1000, sol[:, 0], linewidth=2, color=colors_ctrl[i], label=f'K={K}')

ax1.set_xlabel('Time (ms)', fontsize=11)
ax1.set_ylabel('Amplitude', fontsize=11)
ax1.set_title('Control Effect with Different Gains', fontsize=12, fontweight='bold')
ax1.legend(fontsize=10)
ax1.grid(True, alpha=0.3)
ax1.set_xlim([0, 100])

# 2. 控制增益vs稳态幅值
ax2 = axes[0, 1]
K_range_ctrl = np.linspace(0, 300, 50)
steady_amplitudes = []

for K in K_range_ctrl:
    y0 = [1.0, 0]
    sol = odeint(controlled_thermoacoustic, y0, t_ctrl, 
                 args=(alpha_ctrl, beta_ctrl, omega0_ctrl, K, 0))
    # 取最后部分的幅值
    A_steady_ctrl = np.max(np.abs(sol[-500:, 0]))
    steady_amplitudes.append(A_steady_ctrl)

ax2.plot(K_range_ctrl, steady_amplitudes, 'b-', linewidth=2.5)
ax2.axhline(y=0, color='r', linestyle='--', linewidth=1.5)
ax2.set_xlabel('Control Gain K', fontsize=11)
ax2.set_ylabel('Steady State Amplitude', fontsize=11)
ax2.set_title('Steady Amplitude vs Control Gain', fontsize=12, fontweight='bold')
ax2.grid(True, alpha=0.3)

# 3. 控制相位影响(简化模型)
ax3 = axes[1, 0]
phi_control = np.linspace(0, 2*np.pi, 100)
# 简化的相位影响模型
effectiveness = np.cos(phi_control)
ax3.plot(phi_control * 180/np.pi, effectiveness, 'b-', linewidth=2.5)
ax3.axhline(y=0, color='r', linestyle='--', linewidth=1.5)
ax3.fill_between(phi_control * 180/np.pi, 0, effectiveness, 
                  where=(effectiveness > 0), alpha=0.3, color='green', label='Stabilizing')
ax3.fill_between(phi_control * 180/np.pi, 0, effectiveness, 
                  where=(effectiveness < 0), alpha=0.3, color='red', label='Destabilizing')
ax3.set_xlabel('Control Phase (deg)', fontsize=11)
ax3.set_ylabel('Control Effectiveness', fontsize=11)
ax3.set_title('Effect of Control Phase', fontsize=12, fontweight='bold')
ax3.legend(fontsize=10)
ax3.grid(True, alpha=0.3)

# 4. 控制策略对比
ax4 = axes[1, 1]
strategies = ['No Control', 'Passive', 'Feedback', 'Adaptive']
amp_reduction = [0, 40, 85, 95]  # 幅值降低百分比

bars = ax4.bar(strategies, amp_reduction, color=['red', 'orange', 'green', 'blue'], alpha=0.7)
ax4.set_ylabel('Amplitude Reduction (%)', fontsize=11)
ax4.set_title('Control Strategy Comparison', fontsize=12, fontweight='bold')
ax4.grid(True, alpha=0.3, axis='y')
ax4.set_ylim([0, 100])

for bar in bars:
    height = bar.get_height()
    ax4.text(bar.get_x() + bar.get_width()/2., height,
             f'{int(height)}%', ha='center', va='bottom', fontsize=10)

plt.tight_layout()
plt.savefig(f'{output_dir}/exp6_active_control.png', dpi=150, bbox_inches='tight')
plt.close()

print("✓ 实验6完成:主动控制仿真")

print("\n" + "="*60)
print("所有实验完成!")
print("="*60)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐