4. 传输矩阵法(TMM)实现:矩阵构建、边界条件、反射谱与透射谱计算、Python代码实现
传输矩阵法,圈里人常叫它 TMM。说实话,这是我做光栅设计时最趁手的工具之一。你想想看,DFB 激光器的光栅结构,说白了就是一层层折射率不同的材料堆叠起来。每一层对光场的影响,都可以用一个 2×2 的矩阵来描述。把所有这些矩阵乘起来,整个器件的传输特性就出来了。
我个人习惯用 TMM 来快速验证光栅设计。比起那些复杂的数值仿真,TMM 计算快、物理图像清晰。我在项目中遇到过好几次,用 FDTD 算半天发现结果不对,回头用 TMM 一检查,原来是边界条件设错了。嗯,这方法虽然老,但真管用。
4.1 矩阵构建:从单层到多层
先说说最基本的。每一层均匀介质,光波在其中传播,可以用一个传输矩阵来表示:
M_i = [cos(k_i * d_i), (j / n_i) * sin(k_i * d_i)]
[j * n_i * sin(k_i * d_i), cos(k_i * d_i)]
这里:
- k_i = 2π * n_i / λ,波数
- d_i 是这一层的厚度
- n_i 是折射率(可以是复数,考虑吸收)
- j 是虚数单位
整个光栅结构,假设有 N 层,那总的传输矩阵就是:
M_total = M_N * M_{N-1} * ... * M_1
注意乘法顺序!从入射端开始,一层层乘过去。我曾经在这上面栽过跟头,矩阵乘法的顺序搞反了,结果反射谱完全不对。排查了一下午才发现。
核心要点:传输矩阵的乘法顺序是从入射面到出射面,千万别搞反。
4.2 边界条件:连接物理世界
矩阵搭好了,怎么跟实际的入射光、反射光联系起来?这就需要边界条件了。
假设光从左侧入射,左侧介质折射率为 n_0,右侧为 n_s。那么:
- 左侧边界:入射光场 E_in + 反射光场 E_r
- 右侧边界:只有透射光场 E_t(假设右侧没有反射回来)
写成矩阵形式:
[E_in + E_r] = M_total * [E_t]
[n_0*(E_in - E_r)] [n_s * E_t]
解这个方程组,就能得到反射系数 r 和透射系数 t:
r = E_r / E_in
t = E_t / E_in
注意:如果光栅两侧的介质折射率不同,一定要在边界矩阵中正确引入。我见过有人直接用 M_total 算,忽略了边界折射率跳变,结果反射谱的纹波周期全错了。
4.3 反射谱与透射谱计算
有了 r 和 t,反射率和透射率就简单了:
R = |r|^2
T = |t|^2 * (n_s / n_0)
为什么要乘 n_s / n_0?因为光功率流在不同介质中要守恒。这个细节,很多教材上一笔带过,但实际计算时漏掉它,结果就不对了。
扫一波波长,把每个波长下的 R 和 T 算出来,就是反射谱和透射谱。DFB 光栅的反射谱会在布拉格波长附近出现一个高反射峰,这个峰的宽度和高度,直接决定了激光器的性能。
我的经验:计算反射谱时,波长扫描范围要覆盖布拉格波长两侧至少 50 nm。太窄了,你可能看不到完整的反射带边沿。
4.4 Python 代码实现
说了这么多,上代码。这是我常用的 TMM 实现,简洁够用:
import numpy as np
def tmm_layer(n, d, lam):
"""单层传输矩阵"""
k = 2 * np.pi * n / lam
cos_kd = np.cos(k * d)
sin_kd = np.sin(k * d)
M = np.array([
[cos_kd, 1j * sin_kd / n],
[1j * n * sin_kd, cos_kd]
])
return M
def tmm_total(layers, lam, n0, ns):
"""计算多层结构的反射率和透射率
layers: [(n1, d1), (n2, d2), ...]
"""
M_total = np.eye(2, dtype=complex)
for n, d in layers:
M_layer = tmm_layer(n, d, lam)
M_total = M_layer @ M_total
# 边界条件
A = M_total[0,0] + M_total[0,1] * ns
B = M_total[1,0] + M_total[1,1] * ns
r = (n0 - B / A) / (n0 + B / A)
t = 2 * n0 / (n0 * A + B)
R = np.abs(r)**2
T = np.abs(t)**2 * np.real(ns) / np.real(n0)
return R, T
# 示例:计算均匀布拉格光栅的反射谱
lam_range = np.linspace(1.5e-6, 1.6e-6, 1000)
n_high, n_low = 3.5, 3.3
d_high, d_low = 0.22e-6, 0.22e-6 # 四分之一波长厚度
num_periods = 20
layers = []
for _ in range(num_periods):
layers.append((n_high, d_high))
layers.append((n_low, d_low))
R_spectrum = []
for lam in lam_range:
R, _ = tmm_total(layers, lam, n0=1.0, ns=1.0)
R_spectrum.append(R)
# 找到反射峰
peak_idx = np.argmax(R_spectrum)
print(f"峰值反射率: {R_spectrum[peak_idx]:.4f}")
print(f"峰值波长: {lam_range[peak_idx]*1e9:.2f} nm")
代码说明:
tmm_layer()生成单层矩阵tmm_total()组装多层并计算 R、T- 示例中用了 20 个周期的均匀光栅,折射率差 0.2
- 输出峰值反射率和对应的波长
4.5 知识体系总览
下面这张图,把 TMM 的核心逻辑串起来了。从单层矩阵到多层级联,再到边界条件和谱线计算,每一步都环环相扣。
实用建议:刚开始写 TMM 代码时,先用一个简单的法布里-珀罗腔(两层反射镜夹一层介质)验证。如果算出来的透射峰位置和理论值对得上,那你的矩阵构建和边界条件就基本没问题了。
好了,TMM 的核心内容就这些。矩阵构建、边界条件、谱线计算,再加上 Python 代码,足够你上手做 DFB 光栅的初步设计了。记住,工具是死的,思路是活的。遇到复杂结构时,多想想每一层物理上发生了什么,矩阵自然就写对了。