简介:一套基于MATLAB的热晕相位屏仿真程序,面向光学工程、大气光学与高能激光领域的研究人员、工程师及仿真学习者,用于定量分析大气温度不均匀引起的光波前畸变及其对成像质量的影响。压缩包共13个文件,其中7个m脚本为核心算法,覆盖二维相位屏生成、傅里叶变换、光学传递函数与点扩散函数计算、成像反变换等完整流程;4个bmp图像为仿真输出,便于直接查看结果;另有1个txt说明文档和1个asv备份文件,帮助理解程序结构与参数设置。资源包仅541KB,轻量便携。目前已有254人学习下载。程序内置可调参数,可模拟不同大气条件、温度梯度下的热晕效应,通过点扩散函数反变换重建受扰图像,从而研究热晕对分辨率的影响。脚本还提供自定义正反傅里叶变换函数,便于二次开发,为激光传输优化、望远镜设计或热晕补偿技术提供实验支撑与代码参考。
1. 热晕相位屏仿真:为什么你的光束在长距离传输中总是“化成一团雾”
做激光大气传输的人,十有八九都遇到过这个场面:在实验室里把光束调得漂漂亮亮,一出大气就发散、抖动、能量集中度暴跌。如果只考虑大气湍流,你会发现理论曲线和实测数据总差着一截,尤其在晴天午后、地面热对流强烈的时段,误差大得离谱。这个“差额”就是热晕效应——光束本身加热了它走过的空气路径,形成低密度通道,反过来把光束往外推。功率越高、传输越远,这个自伤效应越明显。
“热晕程序.zip_MATLAB 热晕_matlab 热晕_基于matlab的热晕相位屏仿真程序_热晕仿真程序_相位屏”这个项目,就是一套基于 MATLAB 的热晕相位屏仿真实现。它的核心思路是:把连续大气路径切成若干段,每段用一个随机相位屏模拟湍流扰动,再叠加一个由光束自身能量沉积造成的“热晕相位”修正,然后一步步做衍射传播。适合谁用?做激光传输评估、光通信链路预算、强激光系统设计的工程师,以及光学相关专业做课题的研究生。这套程序最大的价值不是“算得精确”,而是让你在投入昂贵的外场实验之前,先在本地把参数趋势摸清。
下面我会按“原理先立住 → 最小复现 → 参数与算法拆解 → 结果验证 → 踩坑记录 → 进阶改进”的顺序,把这个方案完整讲透。
2. 热晕相位屏的物理背景与建模取舍:稳态解为什么够用
2.1 热晕的物理机制:从吸收到密度变化再到相位延迟
热晕效应可以拆成三步:大气吸收激光能量、空气受热膨胀导致密度下降、密度变化通过 Gladstone-Dale 关系改变折射率。折射率变了,光束走过的光学路径就出现一个“负透镜”效果——中心区域折射率低于边缘,光束能量被往外推。
定量表达上,折射率变化与吸收系数、光束强度分布、风速(或光束扫过速度)密切相关。稳态情况下,热晕引起的折射率扰动可以用一个积分表达:
[ \Delta n(x,y) = -n_0 \frac{(n_0-1)}{\rho_0} \frac{\alpha}{v} \int_{-\infty}^{x} I(x',y) dx' ]
这个式子说的是:沿着风向积分光强分布,乘以吸收系数 (\alpha),除以风速 (v),得到折射率变化。负号代表中心折射率下降。对相位屏而言,我们把这个折射率变化沿传输路径积分,就得到热晕相位:
[ \phi_{thermal}(x,y) = k \int_{0}^{L} \Delta n dz ]
把以上三步拆开建模,就是相位屏法的物理基础。
2.2 为什么要用“稳态近似”:非稳态计算的成本陷阱
严格的热晕是时变过程。激光开启瞬间,空气被加热但还没来得及流动,然后风速或光束扫描把热量带走,建立一个新的稳态。完整的非稳态计算需要求解流体力学方程和波动方程的耦合,时间步长要小到能分辨风速流动,对 MATLAB 这种解释型环境来说,一个中等规模网格(比如 256×256)跑几十个时间步就已经很吃力。
大多数工程评估场景关注的不是瞬态过程,而是连续波激光发射后光束稳定下来的形态——稳态热晕。这个假设的成立条件是:激光持续发射时间远大于气流流过光束特征尺寸的时间,即 (t \gg D/v),其中 (D) 是光束直径,(v) 是横向风速。对直径 10 cm、风速 5 m/s 的典型场景,这个时间是 20 ms,而连续波激光发射通常是秒级以上,所以稳态近似完全合理。
这个取舍的意义是:我们可以把难以处理的时变流体问题,简化成一个固定相位屏分布,放在迭代传播循环里一次性施加。
2.3 相位屏模型:湍流屏和热晕屏为什么要分开叠加
常见的做法是每段路径上同时加两个相位屏:一个代表湍流随机扰动,一个代表热晕确定性扰动。湍流屏每次传输都重新生成随机种子,体现的是“统计平均”意义上的影响;热晕屏则依赖当前传播面上的光强分布,必须先做一次短距离传播得到光强,才能计算相位修正。
这两个屏的叠加顺序是关键:放在同一个网格上、直接相加。因为热晕折射率变化很小,线性近似成立,两个屏的相位可以直接叠加,然后一次性做衍射传播。好处是计算量不增加——只是在湍流屏基础上额外加了一个确定性修正。
2.4 为什么选相位屏而不是直接数值求解波动方程
有人会问:直接对 Helmholtz 方程做三维数值求解不行吗?答案是可以,但对典型的大气传输场景太贵。传输距离是公里级,横向特征是厘米级,三维网格直接爆炸。相位屏法把三维问题拆成“自由空间衍射传播 + 平面上的相位修饰”,用分步法近似,是激光大气传输领域最常见、最经济的做法。
这个方案适合做参数扫描和趋势分析。比如评估“功率提高一倍,焦平面峰值光强变化多少”“风速从 2 m/s 提到 8 m/s,斯特列尔比恢复多少”,相位屏法可以在几分钟内给出可靠趋势,而三维流体求解可能要跑一整天。
3. 复现最小可用版本:MATLAB 中的热晕相位屏仿真主循环
3.1 初始化网格与物理参数:先定标度再写循环
先把我常用的一个最小版本主程序列出来,跑通后再谈改进。
% thermal_blooming_main.m % 最小可用版热晕相位屏仿真 % 物理参数 D = 0.1; % 光束口径 [m] L = 2000; % 传输距离 [m] Nseg = 10; % 路径分段数 lambda = 1.064e-6; % 波长 [m] P0 = 1000; % 激光功率 [W] alpha = 2e-5; % 大气吸收系数 [1/m] v_wind = 5; % 横向风速 [m/s] Cn2 = 1e-15; % 湍流强度 [m^(-2/3)] % 数值参数 N = 256; % 网格点数 Lx = 0.3; % 网格物理宽度 [m] dx = Lx / N; % 空间步长 [x, y] = meshgrid((-N/2:N/2-1) * dx, (-N/2:N/2-1) * dx); r = sqrt(x.^2 + y.^2); k = 2 * pi / lambda; % 光束初始场:超高斯 w0 = 0.05; % 束腰半径 [m] U0 = exp(-(r/w0).^4); % 超高斯光束 U0 = U0 / sqrt(sum(abs(U0(:)).^2) * dx^2); % 归一化这里的关键是归一化:总功率对应网格上所有点的光强之和乘以 dx²,不是峰值光强。不归一化的话,后面计算热晕相位时绝对数值会偏差很大。超高斯光束比高斯光束更接近真实激光器输出,边缘更陡。
3.2 分段传播循环:DFT 衍射与热晕修正的交替
主循环放在下面这段代码里:
dz = L / Nseg; U = U0; for i = 1:Nseg % 第一步:自由空间衍射传播 dz/2 U = propagate_fresnel(U, dz/2, dx, lambda); % 第二步:生成相位屏 % 2a: 湍流相位屏 phi_turb = generate_turbulence_phase(N, dx, Cn2, dz); % 2b: 热晕相位屏(基于当前光强分布) I = abs(U).^2; phi_thermal = thermal_phase_from_intensity(I, P0, alpha, v_wind, dx, k); % 2c: 叠加相位 U = U .* exp(1i * (phi_turb + phi_thermal)); % 第三步:再传播 dz/2 U = propagate_fresnel(U, dz/2, dx, lambda); end逻辑上这是标准的 split-step 方法:半步步进 + 相位屏 + 半步步进。相位屏放在中间而不是端点,对称性更好,二阶精度。热晕相位需要在当前传播面光强已知后才能计算,因此放在衍射传播之后、相位叠加之前。
湍流屏每次用不同的随机种子,代表大气在“换了一幅图”;热晕屏则完全由当前光强决定,是确定性的。两者的叠加顺序不影响结果——相位是线性叠加的,谁先谁后数学上等价。
3.3 衍射传播函数:Fresnel 衍射的一次 FFT 实现
function Uout = propagate_fresnel(Uin, dz, dx, lambda) N = size(Uin, 1); fx = (-N/2:N/2-1) / (N * dx); [FX, FY] = meshgrid(fx, fx); H = exp(-1i * pi * lambda * dz * (FX.^2 + FY.^2)); Uout = ifft2(fft2(Uin) .* H); end这是角谱法的核心:在频域做一次相位乘法,然后逆 FFT 回到空间域。注意频域坐标 FX 的单位是“周期/米”,乘 lambda 和 dz 后得到的是传输距离上的累积相位。
参数说明:
- dz 是单次传播距离,步长越短精度越高,但计算量线性增加。
- dx 和 N 共同决定频域最高频率,网格间距必须满足 (\lambda dz / (N dx^2) < 1) 才能避免混叠,否则会在图样边缘看到虚拟折返。
3.4 湍流相位屏生成:功率谱反演方法
function phi_turb = generate_turbulence_phase(N, dx, Cn2, dz) Lx = N * dx; fx = (-N/2:N/2-1) / Lx; [FX, FY] = meshgrid(fx, fx); f = sqrt(FX.^2 + FY.^2); f(f==0) = 1e-10; % 避免除零 % Kolmogorov 谱 phz = zeros(N); rng('shuffle'); c = randn(N) + 1i * randn(N); S_phi = 0.023 * Cn2 * f.^(-11/3) * dz; % 相位功率谱 phz = real(ifft2(c .* sqrt(S_phi)) * (N^2)); % 归一化到正确方差 phz = phz / std(phz(:)) * sqrt(1.38 * Cn2 * dz / dx^(5/3)); end功率谱反演的基本思路是:在频域构造一个幅度服从指定功率谱的随机场,做逆 FFT 得到空间域相位分布。这里有几个容易出错的细节:
- 频域坐标要正确换算,不能直接用 FFT 的默认索引。
- 零频位置要置一个极小值而不是真正的零,避免除零。
- 归一化系数需要经验校准。我测试过很多种写法,最可靠的办法是生成一次相位屏后检查相位结构函数的斜率,再校准系数。
实际上更推荐用分形叠加法(subharmonic method)补充低频成分,因为 FFT 方法在低频段能量不足,生成的相位屏大尺度起伏偏弱。后面避坑章节会详细说这个问题的现象。
3.5 热晕相位计算:从光强到相位的积分实现
function phi_thermal = thermal_phase_from_intensity(I, P0, alpha, v_wind, dx, k) % 假设风向沿 x 轴正方向 N = size(I, 1); n0 = 1.0003; % 空气折射率 rho0 = 1.225; % 空气密度 [kg/m^3] gamma = 1.4; % 比热比 dn_dT = -1e-6; % 折射率温度系数 [1/K] cp = 1005; % 定压比热 [J/(kg*K)] % 叠加背景强度归一化 I_norm = I / (sum(I(:)) * dx^2) * P0; % 沿风向累积积分 cumI = cumsum(I_norm, 2) * dx; % 温度变化 delta_T = alpha * cumI / (rho0 * cp * v_wind); % 折射率变化 delta_n = dn_dT * delta_T; % 相位 Lseg = 1; % 单段积分长度,由主程序传入更准确 phi_thermal = k * delta_n * Lseg; end这段代码体现的核心是:光强分布被归一化回实际功率量纲,沿风向做累积积分,换算成温度场、折射率场,最终积分为相位。其中 (\Delta T = \alpha I / (\rho_0 c_p v)) 是稳态热晕的经典表达式,风速 v 在分母上意味着风速越大热晕越弱。这里要特别注意各物理量的单位一致性:吸收系数用 1/m,光功率用 W,积分后得到的温度增量是 K 量级,对 1 kW 功率、厘米级光束来说大概是零点几度到几度,折射率变化量级在 1e-7 到 1e-6。
一个值得注意的问题是:这个代码中的 Lseg 参数应该由主程序传入,我更倾向于将其改为实际分段长度 dz。上面为简洁写作 1,实际使用时务必改成 dz,否则热晕强度会整体偏大。这是最常见的“看起来没问题但结果不对”的坑。
4. 关键参数扫描与结果解读:斯特列尔比、功率阈值和风向依赖
4.1 输出指标的约定:斯特列尔比和光束宽度
仿真跑完不能只看光斑图,要用量化指标。最常用的是斯特列尔比 SR(Strehl Ratio):实际焦平面峰值光强与相同口径、无畸变衍射极限峰值光强之比。无畸变情况(Cn2=0、alpha=0)先在主程序里跑一遍,记录峰值 I0;加入热晕后再跑一遍,记录峰值 I,两者相除。
另一个指标是二阶矩光束宽度:
% 计算光束宽度 I_tot = abs(U_final).^2; x_center = sum(x(:) .* I_tot(:)) / sum(I_tot(:)); y_center = sum(y(:) .* I_tot(:)) / sum(I_tot(:)); x2_mean = sum((x(:)-x_center).^2 .* I_tot(:)) / sum(I_tot(:)); y2_mean = sum((y(:)-y_center).^2 .* I_tot(:)) / sum(I_tot(:)); beam_width = 2 * sqrt(x2_mean + y2_mean);这两个指标一个看峰值保真度,一个看能量扩展。热晕的典型特征就是 SR 下跌而波束宽度增大,且光斑向风向的上游方向偏移——因为下游方向的光走过的路径更长,经历的负透镜效应更重。
4.2 功率扫描:热晕阈值的识别方法
你可以固定其他参数,逐渐增加 P0,画出 SR-P0 曲线。典型结果是:在低功率时 SR 基本平坦,接近湍流限制的基线值;功率超过某个阈值后 SR 开始明显下降。这个拐点对应的功率就是工程意义上的“热晕临界功率”。
MATLAB 实现可以用 parfor 加速扫描:
P_list = [100, 500, 1000, 2000, 5000]; SR_list = zeros(size(P_list)); parfor i = 1:numel(P_list) SR_list(i) = run_simulation(P_list(i), ...); % 封装整个主循环 end注意这里 parfor 里不能调用需要 GUI 的函数,并且每个工作进程要能独立访问随机种子。建议在 run_simulation 内部明确设置 rng(i) 保证可复现性。为避免翻车,先按普通 for 循环跑一遍,确认结果合理后再改 parfor 加速。
4.3 风向影响:为什么风速越大、热晕越弱
从热晕相位公式 (\Delta T = \alpha I / (\rho c_p v)) 可以直接看出,风速在分母上。风速提高一倍,热晕强度减半。仿真验证方法:固定功率和吸收系数,扫描 v_wind 从 1 m/s 到 10 m/s,观察 SR 变化。
还有一个常被忽略的点:风向与光束传输方向垂直时,热晕是“单方向推”;风向与光束同向时,等效风速变成空气沿光束路径的流动,如果光束自身也在移动,还要减去光束移动速度。这意味着平台的抖动或移动会改变等效风速——车载或机载激光系统的热晕比固定站的弱,因为平台移动引入了额外相对风。这个结论对工程方案选型有直接参考价值。
4.4 分段数与网格尺寸的收敛性验证
相位屏法有两个数值收敛参数:分段数 Nseg 和网格点数 N。验证方法:固定物理参数,将 Nseg 从 5 逐步提高到 40,观察 SR 是否趋于稳定;同样将 N 从 128 升到 512,观察宽度指标。
典型的观察结果是:Nseg 在 10 以下时结果波动很大,超过 20 基本稳定;N 到 256 时已经能用,512 时精度提升有限而耗时增加 4 倍。一套合理的参数组合是 N=256、Nseg=20,在计算速度和可信度之间取得平衡。网格宽度 Lx 也要至少 3 倍光束直径,否则衍射出去的边缘能量被截断,导致菲涅耳衍射图样人为变化。
5. 热晕仿真的避坑笔记:五个最常见的翻车现场
5.1 FFT 频谱混叠:光斑出现规则性拖尾
现象:光斑图边缘出现一个或多个“鬼影”副本,形状像是横向周期排布。
原因:频域采样间隔不够,即 (\lambda dz / (N dx^2) \ge 1),高频分量折叠回低频。常见于网格宽度过小或分段距离过大。
解决:减小 dz(增加 Nseg),或增大网格宽度 Lx。经验值:保持 (\lambda dz / (N dx^2) < 0.5)。也可以把传播函数改为两步半程 FFT,但对多数场景没必要。
5.2 热晕相位量纲错误:结果对不到理论曲线
现象:热晕效果弱到肉眼看不见,或强到光束直接炸裂溢出网格,明显不合理。
原因:最常见的是功率归一化出错。I 的原始单位是“相对强度”,直接代入热晕公式得到错误幅值;或者把 P0 忘在公式外,导致热晕效果与功率无关。
解决:计算前先用 sum(I(:)) * dx^2 把网格光强归一化回功率单位,再做热晕积分。验证方法:把 P0=0 代入,热晕相位应为全零,SR 应与纯湍流结果一致;把 alpha 设成 0 也应如此。这两个“零测试”每次改代码都先跑一遍。
5.3 湍流屏低频能量不足:SR 系统性偏低
现象:无论怎么调 Cn2,SR 始终低于理论预期值约 10%~20%,且看不出明显的尺度相关性。
原因:FFT 功率谱反演方法天然缺少空间频率极低的分量(对应大尺度涡旋)。Kolmogorov 谱在低频端 f^(-11/3) 趋向无穷,而 FFT 网格的最小非零频率是 1/Lx,比真实的湍流外尺度差好几个量级。
解决:加 subharmonic 低频补偿,或在相位屏外面再叠加一个“大尺度相位斜坡”近似。更简单的替代方案:把分段长度加大,让每段内包含更多大尺度起伏——但这会牺牲纵向分辨率。实际上用分形叠加补低频是标准做法,实现时在频域低频区做更细的插值采样,然后叠加回主屏。
5.4 热晕相位被当成了湍流屏:每次迭代都重新生成
现象:热晕影响比理论预期“更随机”。多次运行同一参数得到的结果差异大得离谱。
原因:代码把热晕相位放进了一个随机生成的 if 分支里,或者热晕相位计算依赖了随机种子。实际上热晕是确定性效应——同样的光强分布,必然产生同样的热晕相位。
解决:检查代码中是否有 rng(‘shuffle’) 或 randn 出现在热晕相位计算路径上。热晕相位函数必须是纯输入输出的确定性函数。如果要做扰动分析(比如模拟大气闪烁导致的光强波动),应该通过湍流屏实现,而不是给热晕屏加随机噪声。
5.5 边界截断与功率损失:长距离传输后能量“神秘消失”
现象:传输一段距离后,网格内总能量明显下降(超过 5%),且光斑边缘出现实心圆环状伪影。
原因:自由空间传播后,一部分能量衍射到了网格边界之外,被 FFT 的周期性边界条件“吃掉”,不再回到网格内部。这和网格宽度不足是同一个问题的两面。
解决:把 Lx 加大到至少 5 倍光束直径,或者每段传播后做一次能量检查和边界吸收层(apodization)。工程做法是先跑一次纯衍射(无大气影响),观察网格内总能量是否守恒;如果不守恒,先调好网格再开始加物理效应。
6. 从“能跑”到“可信”:相位屏仿真的验证铁三角与进阶改进
老话讲“仿真都是假的,只有实验是真的”,但好的仿真应该做到“理论算得出、实验对得上、参数调得动”。我的验证习惯是用三条线交叉确认:
第一是极限退化测试:分别令 Cn2=0、alpha=0、v_wind 趋向无穷,仿真结果必须退化到纯衍射、纯湍流、无热晕这三种已知情况。把对应的理论 SR 算出来对比,误差在 5% 以内才算通过。第二是理论近似:用小吸收系数近似公式 SR_thermal ≈ 1 - 0.0625 * (αP L / (π w0 v))²,看仿真的 SR-P 曲线斜率是否一致。注意这个近似只在热晕很弱时成立,拿来定性校验即可。第三是准直光传输的自洽性:如果光束不聚焦、功率不高,热晕导致的光斑偏移方向必须和公式一致——沿风向积分光强最大的地方折射率最小,光束整体朝上风方向偏移。跑一个简单场景确认偏移方向和量级。
进阶改进可以从三个方向做:加入自适应光学补偿模块,模拟理想校正后的残余热晕,评估“多少阶的 Zernike 校正能把 SR 恢复回 0.8”这种工程问题;把单层相位屏换成多层随机相位屏加时间序列,模拟热晕的时间演化——这需要把稳态公式改成时变形式,加一个驰豫时间常数;更高阶的做法是引入流体力学求解器,在关键场景下对比相位屏近似和完整热对流方程的差异,标定近似方法的误差边界。最后这个方向我已经在跑了,初步结论是:风速大于 3 m/s 时,相位屏近似的 SR 误差在 10% 以内;准静态无风场景下误差会到 20%~30%,说明相位屏法对低风速要格外谨慎。
做这类仿真还有一个容易被忽略的习惯:把每次跑参的输入输出全部存档。我吃过亏——某次微调完网格参数后觉得“结果看着差不多”,两周后回看数据,怎么也想不起来某个中间变量用的是哪一版定义。现在我的做法是用 MATLAB 的 datenum 加参数哈希做文件名,每次运行自动存一份 .mat 文件,包含全部输入参数和输出光场。多花一秒,给自己留条后路。
从工程投入的角度看,热晕相位屏仿真做起来不难,难在把误差来源弄清、把验证做扎实。用这套方法先把“功率翻倍会怎样、风速降到多少会出事”这类问题摸清楚,再上外场实验,能帮你省掉大半的无效测试。希望帮到你。
本文还有配套的精品资源,点击获取