简介:这套程序包是一套面向光纤通信与光纤传感领域研究人员、工程师及学生的光纤光栅仿真工具,覆盖均匀光纤光栅、啁啾光纤光栅与长周期光纤光栅等常用类型的建模与性能分析,可帮助用户研究光栅的反射谱、透射谱与时延特性。包内共30个文件,以MATLAB的m脚本为主,配合fig图形交互文件,便于直观操作和结果可视化,另含少量asv自动备份文件,方便比对调试过程;压缩包整体约181KB,轻量易部署。已有1291人学习浏览,在同类仿真资源中具备一定参考价值,也是教学演示和工程预研的实用选择。通过该程序包,使用者可以快速搭建不同结构参数的仿真模型,理解折射率调制、周期、啁啾度等因素对光谱响应的影响,为光纤光栅器件的设计优化与实验验证提供理论支撑。 如果你跟我一样,实验前习惯先跑一遍仿真,那你大概率也折腾过自己的光纤光栅程序。一支FBG(光纤布拉格光栅)的反射谱长什么样、峰值反射率有多高、旁瓣会不会干扰解调,这些不该等光栅写完了才从解调仪上看到,而应该在电脑里先“预演”一遍。这篇文章就聊聊我那套多种光纤光栅仿真程序是怎么组织的,以及从均匀FBG到啁啾、相移、取样、长周期光栅,仿真逻辑分别该怎么改。
做光纤光栅仿真不是为了发论文才用,它是实实在在的“虚拟实验台”。设计一支光栅,周期、长度、折射率调制量各不相同,写进去还要花时间和成本,哪个参数组合值得写一排?光谱里出现的毛刺是光栅本身的问题还是解调仪的问题?这些问题没有仿真做基准,就只能靠猜。我写这套程序的目标很简单:换光栅类型不用重写框架,只改一个参数,就能得到对应的反射谱和透射谱,并且结果能跟实验室里的解调仪对得上。
1. 为什么仿真这一步省不掉:从一次失败的标定实验说起
前几年做温度应变标定,我在一支均匀FBG上反复试了三种切趾参数,焊好跳线丢到解调仪上,测出来的3 dB带宽和理论差了一倍,旁瓣还不对称。拆掉重写来回折腾了两天,最后才意识到问题不在光栅本身,而是我用到的解调仪分辨率和仿真时的高斯展宽没对上。如果有仿真程序提前把光谱形状跑出来,这一步根本不会浪费那么多时间。
从那以后我就养成了一个习惯:任何光栅设计,先仿真再下单。这个习惯在几个地方特别值钱。
第一是参数设计阶段。光栅长度L、有效折射率n_eff、周期Λ、折射率调制幅度Δn,这五个量直接影响光谱的峰值反射率、带宽和旁瓣结构。仿真可以快速把光谱随这些参数的变化趋势扫出来,比如Δn增加时反射率上升、主瓣变宽,L增加时带宽变窄但旁瓣变高,这就给了“该下单哪种规格”一个明确依据。
第二是解调算法验证阶段。做温度和应变传感时,核心是跟踪波长移动量。如果手头没有解调仪,仿真程序可以直接生成不同温度、应变下的FBG光谱,喂给寻峰算法去算波长,提前把算法精度和鲁棒性测出来。我做相移光栅解调时就靠着仿真生成的大量光谱样本,测出寻峰误差,没有多花一分钱光栅样品费用。
第三是排错阶段。实验光谱出现异常,比如反射率下降、波形分裂,到底是光栅写入不均匀,还是解调仪分辨率不够,还是应力分布不均?在没有仿真基准的情况下,你分不清是谁的锅。我的习惯是把已知的参数输进仿真程序,先看理想光谱长什么样,再拿实测光谱和它做差,偏差大的地方再去分析实验环节哪里出了问题。
这套程序我主要服务三类读者:正在学FBG原理的学生,拿仿真结果对比教材上的耦合模理论;做光纤传感系统开发的工程师,需要一个能快速出光谱的工具;还有研究非均匀光栅(啁啾、相移、取样)的人,需要灵活改参数看效果。接下来我把仿真核心逻辑和不同光栅类型的建模差异拆开讲。
2. 传输矩阵法是怎么把光栅变成一堆矩阵的
FBG的原理初中物理就能理解一半:光栅是一段有周期折射率调制的光纤,满足布拉格条件λ_B = 2 n_eff Λ的波长会被反射回来。制造工艺千变万化,但仿真时不需要关心氩离子激光怎么写栅格,只需要把这个周期折射率结构数字化。
工程上最通用的仿真方法是传输矩阵法(Transfer Matrix Method, TMM),思路特别直白:把整段光栅沿轴向切成N小段,每一段长度足够短,可以近似为均匀光栅。对每一小段用2×2矩阵描述入射光和反射光的关系,然后把所有小段的矩阵按顺序乘起来,就得到整个光栅的反射和透射特性。
每一小段的矩阵里包含两个关键物理量:本地失谐δ和耦合系数κ。失谐量描述入射波长偏离本地布拉格波长的程度:
δ = 2π n_eff (1/λ - 1/λ_B)
λ_B是这个光栅段的局部布拉格波长,λ是当前计算的入射波长。耦合系数描述折射率调制强度对光波的前后向耦合能力:
κ = π Δn / λ
对于均匀光栅,这两个量在整段上是常数,整个光栅本质上就是同一个矩阵的N次方,甚至可以直接用解析解。但对于啁啾、相移、取样这类非均匀光栅,每一段的λ_B和Δn都可能不同,解析解不存在的,必须老老实实一段一段算,这正是TMM最大的价值所在——它把“任意非均匀光栅”转化成了“大量均匀小段的堆积”,每一段用什么参数都行。
每小段的传输矩阵长这样(2×2形式,A+为前向波振幅,A-为后向波振幅):
第一个元素:cosh(γΔz) + j(δ/γ)sinh(γΔz) 第二个元素:j(κ/γ)sinh(γΔz) 第三个元素:-j(κ/γ)sinh(γΔz) 第四个元素:cosh(γΔz) - j(δ/γ)sinh(γΔz)
其中γ² = κ² - δ²,Δz是这一段的小段长度。这个矩阵的实际含义可以理解成:一束前向波走完这一段后,有一部分变成后向波反射回来,而原本的后向波也会透射过去一部分,矩阵的四个元素分别对应这四种“转化路径”的系数。
整段光栅的总矩阵把每一段的矩阵从入射端到出射端依次相乘得到。计算反射系数时需要用边界条件:光栅出射端不存在后向波(没有反射镜),因此反射振幅由总矩阵的第二列决定,反射率等于|T21/T22|²。注意矩阵相乘的顺序——很多人第一次写程序时顺序搞反,结果反射谱怎么都不对,这一点在第四章代码里我会再强调。
把连续光栅分段处理,就像把一段蜿蜒山路切成很多小直线台阶。台阶切得越细,走起来越贴近原路;光栅分段数N越大,仿真结果越接近真实光谱,但计算量也在涨。实践中N取300到1000就够用,太小的N会在反射谱旁瓣上出现明显的伪振荡。
3. 不同类型光纤光栅的建模差异:从矩阵写法说起
“多种光纤光栅仿真程序”这个需求,核心难点在这里——不同光栅类型对仿真程序来说,就是“哪些参数在空间上发生变化”的区别。搞明白这一点,程序框架可以一次搭好,之后只是填参数。
3.1 均匀FBG:最简单的基线
均匀光栅周期固定,折射率调制幅度固定。它是最基础的传感器,反射谱是中间一个主峰、两侧一串旁瓣。仿真时只需要设固定的Λ和Δn就行,主峰中心波长直接等于2n_effΛ。这是验证程序正确性的第一关,如果均匀光栅的峰值波长都算不对,后面所有类型都不靠谱。
3.2 啁啾光栅(CFBG):周期沿长度变化
啁啾光栅的周期沿轴向线性变化,每一段的本地布拉格波长都不同,所以反射谱不再是窄峰,而是一个宽平台。仿真时唯一的区别就是计算每小段的λ_B时加一个跟位置有关的偏置项:
λ_B(z) = λ_B0 + chirp_rate × (z / L - 0.5)
这里的chirp_rate决定波长展宽范围。啁啾光栅常见应用是宽带反射镜和色散补偿,仿真时要注意z的零点位置。如果光栅从z=0开始写入,长周期端在入射侧还是出射侧,反射谱会完全不一样。我习惯把光栅参数从“设计目标”反推:想要多宽的反射带宽,就设多大的chirp_rate,想要中心位于哪个波长,就设对应的λ_B0。
3.3 相移光栅(PS-FBG):在矩阵序列里插一个相移
相移光栅在均匀光栅的中间位置插入一个相位突变,典型效果是反射谱的透射窗口从一条深谷变成窄透射峰——也就是反射谱中心打开一个极窄的陷波窗口。这个窗口对折射率变化极敏感,所以常用于高精度传感和解调。
仿真的实现方式是在传输矩阵链中插一个额外的相移矩阵:
exp(-jφ/2) 0 0 exp(jφ/2)
φ是相移量,对应光栅中间插入的一段额外光程。最常见的相移量是π,此时透射窗口最深最窄。程序实现时在光栅矩阵链的中间位置乘上这个矩阵就行,符号的正负取决于相移点的定义方向。这个细节比较容易写错,后续我会专门提到一个排错经历。
3.4 取样光栅(SFBG):均匀光栅上加一个周期开关
取样光栅在制作时周期性开关激光,等效于用方波包络调制均匀光栅,光谱上是多个反射峰组成的梳状谱,波长间隔跟取样周期成反比。仿真的实现也很简单,分段时让某些段折射率调制为0、某些段正常,交替排列。
多峰间距的仿真精度取决于每段内取样周期的点数。如果每个取样周期只分成2段,峰值波长定位会明显偏;建议每个取样周期至少10段以上。取样光栅在多波长光纤激光器、波分复用传感解调里用得很多。
3.5 长周期光栅(LPFG):别直接一套TMM走天下
长周期光栅的周期通常在几百微米量级,比FBG大了三个数量级,它耦合的不是前向模和后向模,而是纤芯基模和包层模,光谱表现为透射谱中的多个损耗峰,对折射率、弯曲都非常灵敏。
这里要特别提醒:严格的长周期光栅仿真需要多模耦合分析,简单的两模式TMM会给不出准确的包层模损耗峰位置。如果你只是做粗略设计,可以用相位匹配条件估算谐振波长,但完整光谱建议使用更完善的多模传输矩阵或数值模式算法。我的程序里LPFG单独列了一个模块,没有跟FBG混用,避免拿到误导性光谱。
| 光栅类型 | 结构特征 | 仿真中改哪个参数 | 典型用途 |
|---|---|---|---|
| 均匀FBG | 周期恒定 | 固定参数 | 温度/应变传感、窄带反射 |
| 啁啾CFBG | 周期线性变化 | λ_B(z) | 宽带反射、色散补偿 |
| 相移PS-FBG | 中间相位突变 | 插入相移矩阵 | 窄带滤波、高精度传感 |
| 取样SFBG | 周期开关调制 | 分层分段开关 | 梳状谱、多波长激光器 |
| 长周期LPFG | 百微米级周期 | 包层模耦合模型 | 折射率传感、增益均衡 |
4. 从零搭一个可复现的FBG仿真程序
我推荐用Python + NumPy + Matplotlib的组合,原因很实际:免费、随处可跑,而且后期跟数据采集、标定脚本能无缝衔接。MATLAB当然也能做,但如果你要批量跑几百组参数做算法验证,Python的生态优势更明显。
4.1 核心代码骨架
下面这段代码是我常用框架的精简版,保留了最关键的部分:传输矩阵计算、分段参数生成、反射率输出。它支持均匀、啁啾、相移三种类型,取样光栅只需在上面的循环里加个“跳过某些段”的判断,这里不展开赘述了。
import numpy as np def unit_matrix(dz, delta, kappa): """单段光栅的2x2传输矩阵""" gamma = np.sqrt(kappa**2 - delta**2 + 0j) c = np.cosh(gamma * dz) s = np.sinh(gamma * dz) return np.array([ [c + 1j * delta / gamma * s, 1j * kappa / gamma * s], [-1j * kappa / gamma * s, c - 1j * delta / gamma * s] ]) def fbg_spectrum(wl, n_eff=1.45, L=10e-3, lambda_B=1550e-9, dn=2e-4, chirp_nm=0.0, phase=None, N=500): """ 计算多种光纤光栅的反射谱 wl : 波长数组,单位 m chirp_nm : 啁啾量,单位 nm,0 表示均匀光栅 phase : 相移量,单位 rad,None 表示无相移 N : 分段数 """ dz = L / N Rs = [] for lam in wl: T = np.eye(2) for i in range(N): z = (i + 0.5) * dz # 啁啾光栅:本地布拉格波长随位置变化 if chirp_nm != 0: Lb = lambda_B + chirp_nm * 1e-9 * (z / L - 0.5) else: Lb = lambda_B # 相移光栅:在中间点插入相移矩阵 if phase is not None and i == N // 2: Tp = np.array([ [np.exp(-1j * phase / 2), 0], [0, np.exp(1j * phase / 2)] ]) T = Tp @ T # 本地失谐量与耦合系数 delta = 2 * np.pi * n_eff * (1 / lam - 1 / Lb) kappa = np.pi * dn / lam T = unit_matrix(dz, delta, kappa) @ T # 反射系数,边界条件:光栅末端无后向波 r = -T[1, 0] / T[1, 1] Rs.append(np.abs(r)**2) return np.array(Rs) # 使用示例:均匀光栅反射谱 wl = np.linspace(1549e-9, 1551e-9, 2001) R_uniform = fbg_spectrum(wl, N=500) # 相移光栅反射谱 R_phase = fbg_spectrum(wl, phase=np.pi, N=500)跑出来的结果先用均匀光栅做个自检:反射峰应该落在1550 nm附近,3dB带宽在几十pm到几百pm之间,取决于L和Δn的乘积。如果峰值波长偏了,先检查布拉格条件;如果旁瓣不对称,大概率是矩阵相乘顺序或边界条件的问题。
4.2 参数怎么取才不踩坑
代码能跑通很简单,但要跑出来的光谱有意义,几个关键参数得根据自己的场景调。
分段数N:我建议至少取300。N太小,反射谱主瓣形状还凑合,但旁瓣位置会出现计算伪影,严重时会误判成“次峰”。N太大,比如5000,算起来就慢了,尤其你要扫几百个波长点的时候,双层循环会卡到怀疑人生。建议先N=200快速验证趋势,确定参数范围后N=800跑精细谱。
折射率调制量Δn:普通紫外写入的FBG,Δn一般在1e-5到5e-3之间。Δn太小反射率很低,不适合当传感元件;Δn太大,光谱会明显展宽,旁瓣结构也变了。我第一次写程序时随手填了个0.01,反射谱宽得离谱,还以为是代码写错了。所以要根据实际工艺范围取值。
波长扫描范围与点数:均匀FBG的反射带宽通常很窄,扫描范围设成带宽的10倍以上,比如从中心波长±1 nm开始,点数2000左右足够光滑。啁啾光栅要覆盖整个反射平台,需要按chirp总宽度扩展范围。
还有一点经验之谈:Python里的双层循环在N和波长点数都大时会非常慢。我后来用numba加了个@jit装饰器,同样参数从几秒降到零点几秒。如果你要批量扫参,这一步优化很重要。具体做法就是给fbg_spectrum函数加上@njit,再处理一下NumPy数组的类型标注——这个小改动能让你的批量仿真体验完全不同。
5. 仿真结果如何指导实验:光谱对比与参数反推的经验
仿真程序写出来不是终点,能拿它指导实验才是真的值钱。我常用的工作流是:先用仿真确定光栅设计参数,写好栅之后实测光谱,再把仿真光谱“处理”成和解调仪一样的分辨率,最后两者对齐比对,找出偏差来源。
5.1 仿真光谱要对齐解调仪分辨率
这里是最容易踩坑的一步。很多人把仿真光谱跟解调仪实测光谱放一起比,发现实测谱明显更“胖”、更圆,就怀疑仿真或光栅有问题。其实问题是解调仪和光谱仪本身有分辨率极限,通常几个pm到几十pm,它会像高斯滤波器一样把光谱磨平。
解决办法是给仿真光谱做一个高斯卷积,核的FWHM等于你设备的分辨率。假设解调仪分辨率是10 pm,对应波长间隔约1.0e-11 m,那么在仿真波长网格上构建高斯权重,卷积一下反射谱。做完这一步,仿真和实测的主瓣宽度、幅度通常能对得很齐。如果还是对不上,下一步才去怀疑光栅参数。
5.2 用实测光谱反推光栅参数
实验光谱和仿真光谱对不齐时,可以反过来做:把L、Δn、切趾轮廓当作待定参数,在仿真里扫描,找到跟实测最接近的一组。这个操作本质上是最小化问题,我用得最多的场景是反推Δn——因为写入工艺不同,实际Δn跟设计值往往有偏差。
具体办法:固定L和周期,改变Δn在1e-4到2e-3的范围内扫仿真谱,计算每个仿真谱和实测谱的均方误差,选择误差最小的Δn。这个方法比肉眼比对靠谱得多。有一次我用这个流程发现写栅后的Δn比设计值低了20%,后续调整曝光时间,光谱一致性立刻提升了。
5.3 温度和应变传感的仿真预测
传感应用里,仿真最大的价值是预测波长灵敏度并帮助设计解调方案。石英光纤的FBG温度系数约10 pm/°C,应变系数约1.2 pm/με。仿真时不需要真的改变n_eff和Λ的物理耦合,直接把λ_B按比例平移就行,比如温度变化10°C,λ_B整体移动0.1 nm。
更有意思的是相移光栅。它的透射窗口极窄,温度和应变变化时窗口位置跟着移动,分辨能力比均匀FBG主峰移动高一个量级。我在做高精度应变传感时,先用仿真把不同应变下的透射窗口位置跑出来,再据此选择窄线宽激光器和寻峰策略,实测效果和仿真预测吻合得非常好。
关于相移光栅,说一个我自己的排错经历。第一次写PS-FBG仿真时,相移矩阵插对了位置,但矩阵正负号反了,出来的光谱对称性看着没问题,可是透射窗口不在布拉格中心,偏了几十个pm。我一度以为是相移量算错了,折腾半天才发现是相移方向定义问题。这种错误有个特点——光谱形状完全正常,只有位置偏差,极容易忽略。后来我的习惯是:仿真里把正负号两种结果都跑出来,对比哪个和实测一致,别想当然。
5.4 旁瓣与切趾
均匀FBG反射谱的旁瓣,在弱反射时可能到-20 dB,强反射时甚至超过-10 dB。这在传感里会造成误判,比如寻峰算法把旁瓣当成了次峰。仿真程序里如果发现旁瓣超标,可以引入切趾处理:让折射率调制幅度沿长度呈钟形分布(比如高斯型或余弦型),而不是均匀矩形。
实现方式很简单,把代码里的固定dn改成随z变化的数组:dn(z) = dn * exp(-((z - L/2)/σ)²),σ控制切趾强度。切趾之后主瓣会略微增宽,但旁瓣能压到-30 dB甚至更低。我在仿真程序里把切趾函数作为可选参数后,跟实际写入光栅的匹配度又上了一个台阶。
综合下来,一套好用的光纤光栅仿真程序,不只是一段能画光谱的代码,它是设计、验证、排错的共享基座。均匀FBG练手,啁啾和相移光栅练方法,取样和长周期光栅练边界意识——每换一种光栅类型,你都会对这个物理过程多一层理解。我现在的习惯还是那样:新光栅设计方案先扔进仿真程序里跑一遍,再决定怎么下单、怎么设置测量系统。搞定了这一步,实验台上少熬的夜,绝对比当初写仿真程序付出的时间多。
本文还有配套的精品资源,点击获取