1. 从一束激光说起:为什么需要复参数q和ABCD矩阵
如果你做过激光光路搭建或者光学系统仿真,大概率遇到过这样的场景:激光器出射的是一束标准的高斯光束,经过一个透镜聚焦、再经过一段自由空间传输、又碰到一个反射镜折转,最后打到某个探测器或者加工面上。这时候你想知道:最终到达目标位置的光斑半径是多少?波前曲率半径变成多少了?束腰位置又跑到哪里去了?
最笨的办法是老老实实套高斯光束的传输公式,一段一段地算。自由空间传输一个公式,经过薄透镜一个公式,经过球面镜再一个公式。光路稍微复杂一点,比如五六个元件串起来,公式套公式,算到后面自己都不记得哪个R(z)对应哪一段了。更麻烦的是,一旦某个元件的位置微调了,所有中间结果全部作废,得从头再来一遍。
ABCD定律配合复参数q,就是专门解决这个痛点的。它的核心思想非常优雅:把高斯光束在某一截面上的全部信息——光斑半径w和波前曲率半径R——打包成一个复数q,然后每一种光学元件(自由空间、薄透镜、球面镜、介质界面等)都对应一个2×2的矩阵。光束经过一个元件,只需要做一次矩阵乘法,q参数就更新了。多个元件串联,就把各自的ABCD矩阵按顺序乘起来,得到一个总的矩阵,再作用到初始q上,一步到位算出最终结果。
这套方法在激光谐振腔设计、光束整形系统、光纤耦合光路里几乎是标配工具。我见过不少做光学实验的朋友,明明光路不复杂,却因为不会用ABCD定律,每次调光路都靠试错,效率很低。其实只要把复参数q和几个常用矩阵记牢,配合MATLAB写个小脚本,整个光路的光束演化可以秒算出来,而且改参数、扫范围都非常方便。
这篇内容主要面向三类人:一是正在学激光原理或工程光学课程、被q参数和ABCD矩阵搞得有点晕的学生;二是做激光实验或光路设计、需要快速估算光束参数的工程师;三是想用MATLAB把光学计算自动化、但不知道从哪里下手的朋友。我会从复参数q的定义讲起,把物理意义说清楚,然后把自由空间、薄透镜、球面镜、介质界面这几个最常用的ABCD矩阵逐一列出来,每个都配上MATLAB代码和验证算例。最后给一个多元件串联的完整例子,让你能直接抄作业。
提示:这篇是系列的第一篇,重点在复参数q和常用光学系统ABCD矩阵的MATLAB实现。后续会讲高斯光束在谐振腔中的自洽条件、q参数的自再现、以及更复杂的多元件系统优化。
2. 复参数q到底在描述什么:物理意义拆解
2.1 从高斯光束的两个核心参数说起
高斯光束在传播方向上任意一个截面z处,最关心的两个量是光斑半径w(z)和波前曲率半径R(z)。光斑半径描述的是光束有多粗,波前曲率半径描述的是等相位面弯曲得有多厉害。这两个量随z变化的公式,学过激光原理的应该都见过:
w(z) = w0 * sqrt(1 + (z/zR)^2)
R(z) = z * (1 + (zR/z)^2)
其中w0是束腰半径,zR = pi * w0^2 / lambda是瑞利长度,lambda是波长。这两个公式本身不复杂,但问题是它们都是z的函数,而且R(z)在束腰处是无穷大,在别的地方又可能是正也可能是负,处理起来不太方便。
复参数q的巧妙之处在于,它把这两个实数参数合并成一个复数:
1/q(z) = 1/R(z) - i * lambda / (pi * w(z)^2)
这个定义式是整套ABCD定律的基石。你仔细看,实部1/R对应波前曲率,虚部-lambda/(pi*w^2)对应光斑大小。一个复数同时携带了两个实数的信息,而且后面你会发现,它在经过光学系统时的变换规则极其简洁。
2.2 为什么用1/q而不是q本身
这里有个细节值得说一下。定义式写的是1/q,而不是直接定义q。为什么?因为用1/q的话,实部和虚部都有明确的物理意义,而且变换规则是线性的。如果直接定义q,变换公式会变成分式形式,虽然也能用,但不如1/q来得直观。
从1/q出发,可以反解出q的表达式:
q(z) = z + i * zR
这个形式非常漂亮。在束腰处z=0,q = i*zR,纯虚数。随着传播距离增加,q的实部就是z,虚部保持zR不变。也就是说,自由空间传播对q的影响就是实部加上传播距离,这个结论后面会反复用到。
从q反推w和R也很方便:
1/R = Re(1/q) lambda / (pi * w^2) = -Im(1/q)
所以只要知道q,光斑和波前曲率就全有了。MATLAB里用real(1/q)和imag(1/q)两行代码就能提取出来。
2.3 q参数在束腰处的特殊性和符号约定
束腰处R趋于无穷大,1/R = 0,所以1/q是纯虚数,q = i*zR也是纯虚数。这时候光斑半径最小,等于w0。这个位置在光路计算里非常重要,因为很多光学系统的设计目标就是把束腰放在特定位置,或者让束腰半径达到特定值。
关于符号约定,不同教材可能略有差异。我这里采用的是最常见的约定:波前曲率半径R以光束传播方向为正方向,发散光束R为正,会聚光束R为负。虚部方面,1/q的虚部是负的,对应q的虚部为正。这个约定和大多数激光原理教材一致,MATLAB代码里也是按这个来的。
注意:如果你参考的教材或论文用的是相反的符号约定,ABCD矩阵里某些元素的符号可能需要调整。建议在开始计算前先确认一下符号约定,避免后面结果对不上。
2.4 用MATLAB验证q参数的基本性质
光说不练假把式。先用几行MATLAB代码验证一下q参数的基本性质,顺便熟悉一下后面要用的函数结构。
% 基本参数设置 lambda = 1064e-9; % 波长,单位米 w0 = 0.5e-3; % 束腰半径,单位米 zR = pi * w0^2 / lambda; % 瑞利长度 % 在束腰处 z = 0; q0 = z + 1i * zR; fprintf('束腰处 q = %.4f + %.4fi\n', real(q0), imag(q0)); fprintf('束腰处 1/q = %.4e + %.4ei\n', real(1/q0), imag(1/q0)); % 传播一段距离后 z1 = 0.5; % 传播0.5米 q1 = z1 + 1i * zR; w1 = sqrt(lambda / (pi * -imag(1/q1))); R1 = 1 / real(1/q1); fprintf('传播0.5m后 w = %.4f mm, R = %.4f m\n', w1*1e3, R1); % 用公式直接验证 w1_direct = w0 * sqrt(1 + (z1/zR)^2); R1_direct = z1 * (1 + (zR/z1)^2); fprintf('公式验证 w = %.4f mm, R = %.4f m\n', w1_direct*1e3, R1_direct);跑一下这段代码,你会发现两种方法算出来的w和R完全一致。这说明q参数的定义和反推公式是对的。这个验证步骤看起来简单,但实际项目中我建议每次都做一下,尤其是换了符号约定或者单位之后,花几秒钟确认一下能避免后面大量返工。
3. 常用光学系统的ABCD矩阵:从自由空间到球面镜
3.1 自由空间传播矩阵及其MATLAB实现
自由空间传播距离L的ABCD矩阵是最简单的一个:
M_free = [1, L; 0, 1]
这个矩阵作用到q上的效果是q_out = q_in + L,也就是实部增加L,虚部不变。这和我们前面说的“自由空间传播对q的影响就是实部加上传播距离”完全一致。
MATLAB里定义一个自由空间矩阵的函数:
function M = freeSpace(L) % 自由空间传播矩阵 % 输入:L - 传播距离(米) % 输出:2x2 ABCD矩阵 M = [1, L; 0, 1]; end这个函数简单到几乎不需要注释,但把它单独封装成函数的好处是后面串联多个元件时代码更清晰。我见过有人把所有矩阵硬编码在主脚本里,光路一复杂就乱成一团,改一个参数要翻半天。封装成函数之后,主脚本里就是一行一个元件,可读性完全不一样。
3.2 薄透镜矩阵与厚透镜的区别
薄透镜的ABCD矩阵是:
M_lens = [1, 0; -1/f, 1]
其中f是透镜焦距,会聚透镜f为正,发散透镜f为负。这个矩阵的物理意义是:经过薄透镜后,光束的位置不变(所以左上角是1,右上角是0),但波前曲率发生变化(左下角是-1/f)。
厚透镜和薄透镜的区别在于,厚透镜要考虑透镜本身的厚度和两个表面的曲率。如果透镜厚度d远小于焦距f,用薄透镜近似完全够用。但如果厚度和焦距可比,比如一些短焦距的显微物镜,就需要用厚透镜矩阵:
M_thick = [1 - d/(nf2), d/n; -1/f1 - 1/f2 + d/(nf1f2), 1 - d/(nf1)]
其中n是透镜材料折射率,f1和f2分别是前后表面的焦距,d是透镜厚度。这个公式看起来复杂,但实际用的时候直接套就行。大多数激光光路里的透镜都是薄透镜,厚透镜主要出现在精密成像系统里。
function M = thinLens(f) % 薄透镜矩阵 % 输入:f - 焦距(米),会聚为正,发散为负 M = [1, 0; -1/f, 1]; end3.3 球面镜矩阵和介质界面的处理
球面镜的ABCD矩阵和薄透镜形式一样,只是焦距用R/2代替:
M_mirror = [1, 0; -2/R, 1]
其中R是球面镜的曲率半径,凹面镜R为正(会聚),凸面镜R为负(发散)。这里要注意符号约定:如果镜面朝向光束传播方向弯曲,R取正;反之取负。实际光路里反射镜通常会让光束折转,所以计算时要把光路展开成直线,反射镜就等效于一个焦距为R/2的薄透镜。
介质界面的矩阵稍微特殊一点。当光束从折射率n1的介质进入折射率n2的介质,且界面是平面时:
M_interface = [1, 0; 0, n1/n2]
如果是球面界面,曲率半径为R(从n1侧看),则:
M_spherical = [1, 0; (n1-n2)/(n2*R), n1/n2]
这个矩阵在光纤耦合和固体激光器里经常用到,因为光束要从空气进入晶体或者从晶体进入空气。
function M = sphericalMirror(R) % 球面镜矩阵 % 输入:R - 曲率半径(米),凹面镜为正 M = [1, 0; -2/R, 1]; end function M = flatInterface(n1, n2) % 平面介质界面矩阵 % 输入:n1 - 入射侧折射率,n2 - 出射侧折射率 M = [1, 0; 0, n1/n2]; end3.4 常用ABCD矩阵速查表
把上面几个矩阵整理成表格,方便随时查阅:
| 光学元件 | ABCD矩阵 | 关键参数 | 典型应用场景 |
|---|---|---|---|
| 自由空间 | [1, L; 0, 1] | L:传播距离 | 空气光路、真空腔 |
| 薄透镜 | [1, 0; -1/f, 1] | f:焦距 | 聚焦、准直、扩束 |
| 球面镜 | [1, 0; -2/R, 1] | R:曲率半径 | 谐振腔、光束折转 |
| 平面界面 | [1, 0; 0, n1/n2] | n1,n2:折射率 | 空气-晶体界面 |
| 球面界面 | [1, 0; (n1-n2)/(n2R), n1/n2] | R:曲率半径 | 透镜表面、光纤端面 |
这张表建议存下来,实际计算时直接查。我自己的习惯是在MATLAB脚本开头把这些矩阵都定义好,后面串联光路时直接调用函数,代码干净且不容易出错。
4. 用MATLAB串联多个元件:从单透镜到复杂光路
4.1 矩阵乘法的顺序问题:最容易搞错的地方
多个元件串联时,总的ABCD矩阵是各元件矩阵按顺序相乘。但这里有个关键细节:矩阵乘法的顺序是从右到左。也就是说,如果光束先经过元件1,再经过元件2,再经过元件3,总矩阵是:
M_total = M3 * M2 * M1
而不是M1 * M2 * M3。这个顺序问题我见过太多人搞错,包括我自己早期也犯过。原因在于矩阵作用到列向量上时,最右边的矩阵最先作用。q参数可以看作一个列向量[ q; 1 ]的某种变换,所以顺序不能反。
在MATLAB里写的时候,建议按光路顺序从右往左乘,或者用循环从最后一个元件开始往前乘。我个人的习惯是:
% 假设有n个元件,矩阵存在cell数组里 M_total = eye(2); for k = n:-1:1 M_total = M_total * M_list{k}; end这样写不容易出错。如果你习惯从左往右写,那就把循环改成从1到n,但乘法顺序要反过来:
M_total = eye(2); for k = 1:n M_total = M_list{k} * M_total; end两种写法等价,选一种自己不容易搞混的就行。
4.2 单透镜聚焦:经典案例的完整计算
单透镜聚焦是最经典的案例:高斯光束从束腰处出发,传播距离d1到达透镜,经过焦距f的透镜,再传播距离d2到目标面。总矩阵是:
M = freeSpace(d2) * thinLens(f) * freeSpace(d1)
然后q_out = (Aq_in + B) / (Cq_in + D),其中A,B,C,D是总矩阵的四个元素。
% 参数设置 lambda = 1064e-9; w0 = 0.5e-3; zR = pi * w0^2 / lambda; q_in = 1i * zR; % 束腰处 d1 = 0.3; % 束腰到透镜距离 f = 0.1; % 透镜焦距 d2 = 0.15; % 透镜到目标面距离 % 构建总矩阵 M = freeSpace(d2) * thinLens(f) * freeSpace(d1); A = M(1,1); B = M(1,2); C = M(2,1); D = M(2,2); % 计算输出q q_out = (A*q_in + B) / (C*q_in + D); % 提取光斑和波前曲率 w_out = sqrt(lambda / (pi * -imag(1/q_out))); R_out = 1 / real(1/q_out); fprintf('输出光斑半径 w = %.4f mm\n', w_out*1e3); fprintf('输出波前曲率半径 R = %.4f m\n', R_out);这个例子里,你可以试着改一下d2的值,看看光斑半径怎么变化。当d2等于某个值时,光斑最小,那就是聚焦点。用MATLAB扫一遍d2,画个曲线,聚焦位置一目了然。这种扫描在实验前做一次,能省下大量调光路的时间。
4.3 两透镜扩束系统:矩阵方法 vs 逐段计算
两透镜扩束系统是激光光路里非常常见的配置,通常是一个短焦距透镜和一个长焦距透镜组合,用来把光束直径放大或者缩小。用ABCD矩阵算这个系统特别方便。
假设透镜1焦距f1,透镜2焦距f2,间距d,光束从透镜1前某个位置入射。总矩阵是:
M = freeSpace(d) * thinLens(f2) * freeSpace(d) * thinLens(f1)
等等,这里间距是d,但两个透镜之间只有一段自由空间,所以应该是:
M = freeSpace(d) * thinLens(f2) * thinLens(f1)
不对,透镜1和透镜2之间有一段距离d,所以顺序是:先经过透镜1,再传播d,再经过透镜2。总矩阵:
M = thinLens(f2) * freeSpace(d) * thinLens(f1)
这个矩阵乘出来之后,你可以分析扩束比、准直条件等。比如当d = f1 + f2时,系统对入射平行光出射也是平行光,这就是典型的开普勒式扩束。如果d = f1 + f2且f2 > f1,扩束比就是f2/f1。
用MATLAB算这个系统,可以很快验证不同d值下的输出光束参数。我做过一个对比,用矩阵方法算一遍只要几毫秒,而逐段套公式手算至少要十几分钟,还容易出错。尤其是需要扫描多个参数的时候,矩阵方法配合MATLAB循环,效率提升非常明显。
4.4 谐振腔中的往返矩阵:ABCD定律的进阶用法
谐振腔是ABCD定律最重要的应用场景之一。光在腔内往返一次,等效于经过一个往返矩阵。如果光束在腔内稳定传播,那么往返一次后q参数应该自再现,即q = (Aq + B)/(Cq + D)。这个方程解出来就是腔的稳定条件和本征模式。
往返矩阵的构建方法是:从某个参考面出发,沿光路走一圈回到参考面,把沿途所有元件的矩阵按顺序乘起来。比如一个简单的两镜腔,镜1曲率半径R1,镜2曲率半径R2,腔长L,从镜1出发的往返矩阵是:
M_rt = sphericalMirror(R1) * freeSpace(L) * sphericalMirror(R2) * freeSpace(L)
注意这里镜1的矩阵出现了两次,因为往返一次会经过镜1两次(一次是出发时,一次是返回时)。实际上更准确的写法是从镜1表面出发,经过自由空间到镜2,被镜2反射,再经过自由空间回到镜1,被镜1反射。所以:
M_rt = sphericalMirror(R1) * freeSpace(L) * sphericalMirror(R2) * freeSpace(L)
这个矩阵算出来之后,解自再现方程就能得到腔的基模参数。稳定条件通常写成|(A+D)/2| < 1,这个条件在腔设计里是必须满足的,否则光束会跑出腔外。
% 两镜腔往返矩阵示例 R1 = 0.5; % 镜1曲率半径 R2 = 0.5; % 镜2曲率半径 L = 0.3; % 腔长 M_rt = sphericalMirror(R1) * freeSpace(L) * sphericalMirror(R2) * freeSpace(L); A = M_rt(1,1); B = M_rt(1,2); C = M_rt(2,1); D = M_rt(2,2); % 稳定条件 stability = abs((A + D)/2); fprintf('稳定因子 = %.4f\n', stability); if stability < 1 fprintf('腔是稳定的\n'); else fprintf('腔不稳定\n'); end这段代码可以直接用来快速判断一个腔设计是否稳定。实际做腔设计时,我通常会扫一遍L或者R的值,画出稳定区间的图,这样能直观看到哪些参数组合是可行的。
5. 实操中容易踩的坑和验证技巧
5.1 单位不统一:最常见的低级错误
光学计算里单位问题特别容易出错。波长通常用纳米,束腰半径用毫米,传播距离用米,焦距用毫米。如果不统一成同一套单位,算出来的结果会差好几个数量级。
我的建议是全部统一成国际单位制:波长用米,束腰用米,距离用米,焦距用米。MATLAB里输入的时候写成科学计数法,比如1064e-9、0.5e-3。输出的时候再转换成毫米或者微米显示。这样中间计算过程不会因为单位问题出错。
% 推荐的单位处理方式 lambda = 1064e-9; % 米 w0 = 0.5e-3; % 米 d = 0.3; % 米 f = 0.1; % 米 % 输出时转换 fprintf('w = %.4f mm\n', w*1e3); fprintf('R = %.4f m\n', R);5.2 符号约定不一致导致的“结果对不上”
前面提过符号约定的问题,这里再强调一下。不同教材对R的正负定义可能不同,对虚部符号的定义也可能不同。如果你发现用MATLAB算出来的结果和手算或者文献对不上,第一件事就是检查符号约定。
一个简单的验证方法是:自由空间传播后,光斑半径应该增大,波前曲率半径应该从无穷大变成有限值。如果算出来光斑变小了,那肯定是符号或者公式有问题。另一个验证方法是:经过会聚透镜后,波前曲率半径应该变成负的(会聚),如果算出来是正的,也要检查符号。
5.3 用能量守恒和极限情况做交叉验证
ABCD定律本身是线性变换,不涉及能量损失(除非有光阑或者吸收元件)。所以计算前后总功率应该守恒。虽然q参数不直接包含功率信息,但光斑半径的变化趋势应该合理:经过会聚透镜后光斑先变小后变大,经过发散透镜后光斑持续变大。
极限情况也是很好的验证手段。比如焦距趋于无穷大时,薄透镜矩阵应该趋于单位矩阵;传播距离趋于零时,自由空间矩阵应该趋于单位矩阵。把这些极限情况代进去检查一下,能发现很多潜在的错误。
5.4 复数运算中的数值稳定性问题
MATLAB处理复数运算一般没问题,但当q的虚部非常大或者非常小的时候,可能会出现数值精度问题。比如束腰半径非常小的时候,zR = pi*w0^2/lambda会很小,q的虚部就很小,1/q的虚部会很大,计算w的时候可能出现舍入误差。
解决办法是尽量避免直接计算1/q的虚部再开方,而是用q的模和相位来算。不过对于大多数实际光路,w0在0.1mm到几mm之间,zR在几厘米到几米之间,数值稳定性完全够用。只有做微纳光学或者极端参数计算时才需要特别注意。
5.5 把常用计算封装成可复用函数
最后分享一个我自己的习惯:把ABCD定律的核心计算封装成一个函数,输入初始q和元件矩阵列表,输出最终q和中间结果。这样每次算新光路只需要改元件列表,不用重复写计算代码。
function [q_out, q_list] = propagateQ(q_in, M_list) % 计算高斯光束经过多个元件后的q参数 % 输入:q_in - 初始q参数 % M_list - 元件矩阵的cell数组,按光路顺序排列 % 输出:q_out - 最终q参数 % q_list - 每个元件后的q参数(用于调试) n = length(M_list); q_list = zeros(1, n+1); q_list(1) = q_in; q_current = q_in; for k = 1:n M = M_list{k}; A = M(1,1); B = M(1,2); C = M(2,1); D = M(2,2); q_current = (A*q_current + B) / (C*q_current + D); q_list(k+1) = q_current; end q_out = q_current; end这个函数虽然简单,但用起来非常顺手。你可以把光路上每个元件的矩阵按顺序放进cell数组,一行调用就能得到所有中间结果。调试的时候把q_list打出来,看看每一步的变化,很容易定位问题。
6. 一个完整算例:从激光器到加工面的全链路计算
6.1 光路描述和参数设置
假设一个光纤激光器输出波长为1064nm,束腰半径0.3mm,束腰位于输出端面。光路依次经过:自由空间传播0.5m,经过焦距为50mm的准直透镜,再传播0.2m,经过焦距为100mm的聚焦透镜,最后传播0.15m到达加工面。求加工面上的光斑半径和波前曲率半径。
这个光路在激光加工里非常典型:先准直,再聚焦。用ABCD矩阵算一遍,看看最终光斑能不能满足加工要求。
% 参数设置 lambda = 1064e-9; w0 = 0.3e-3; zR = pi * w0^2 / lambda; q_in = 1i * zR; % 光路元件 M_list = { freeSpace(0.5), % 自由空间0.5m thinLens(0.05), % 准直透镜f=50mm freeSpace(0.2), % 自由空间0.2m thinLens(0.1), % 聚焦透镜f=100mm freeSpace(0.15) % 自由空间0.15m }; % 计算 [q_out, q_list] = propagateQ(q_in, M_list); % 提取结果 w_out = sqrt(lambda / (pi * -imag(1/q_out))); R_out = 1 / real(1/q_out); fprintf('加工面光斑半径 w = %.4f mm\n', w_out*1e3); fprintf('加工面波前曲率半径 R = %.4f m\n', R_out);6.2 结果解读和参数扫描
跑完这段代码,你会得到一个光斑半径。如果这个值比预期的大,可以试着调整聚焦透镜的焦距或者最后一段自由空间的距离。用MATLAB写个循环扫一遍d2,画出光斑半径随d2变化的曲线,聚焦位置就一目了然了。
% 扫描最后一段距离 d2_range = linspace(0.05, 0.3, 100); w_range = zeros(size(d2_range)); for k = 1:length(d2_range) M_list_scan = { freeSpace(0.5), thinLens(0.05), freeSpace(0.2), thinLens(0.1), freeSpace(d2_range(k)) }; [q_out, ~] = propagateQ(q_in, M_list_scan); w_range(k) = sqrt(lambda / (pi * -imag(1/q_out))); end plot(d2_range*1e3, w_range*1e3, 'LineWidth', 1.5); xlabel('最后一段距离 (mm)'); ylabel('光斑半径 (mm)'); title('光斑半径随加工面位置的变化'); grid on;这条曲线会显示一个最小值,对应的d2就是最佳聚焦位置。实际调光路的时候,这个曲线能告诉你聚焦透镜应该放在哪里、加工面应该放在哪里。我每次做新光路设计都会先跑一遍这个扫描,心里有数之后再动手调,效率高很多。
6.3 从计算结果反推实验调整方向
如果算出来的光斑半径比目标值大,有几个调整方向:一是换焦距更短的聚焦透镜,二是调整准直透镜和聚焦透镜之间的距离,三是调整激光器输出端的束腰位置。每个调整方向都可以用ABCD矩阵快速评估效果,不用反复试错。
比如把聚焦透镜焦距从100mm换成50mm,重新跑一遍计算,看看光斑能小多少。如果还不够,再试试调整两个透镜之间的距离。这种参数扫描在MATLAB里就是改几个数字的事,几秒钟就能得到结果。相比在实验台上反复拆装透镜,效率完全不是一个量级。
提示:实际光路中透镜有像差,高斯光束的ABCD定律只适用于理想薄透镜近似。如果光斑接近衍射极限或者透镜数值孔径很大,像差的影响不能忽略,这时候需要用更复杂的物理光学仿真工具。但对于大多数常规光路,ABCD定律的精度完全够用。
7. 从这一篇到下一篇:q参数自再现和谐振腔稳定性
把复参数q和常用ABCD矩阵用熟之后,你会发现很多光学系统的问题都可以归结为矩阵乘法。自由空间、透镜、反射镜、介质界面,这几个基本元件组合起来,能覆盖大多数激光光路的计算需求。
下一篇会讲q参数在谐振腔中的自再现条件,也就是q = (Aq + B)/(Cq + D)这个方程怎么解,以及怎么用MATLAB判断腔的稳定性和计算基模参数。那部分内容在激光器设计里非常核心,尤其是做固体激光器或者光纤激光器谐振腔的时候,稳定区间的计算直接决定了腔长和镜片曲率的选择。
如果你现在手头有正在设计的光路,建议先把这篇里的MATLAB函数跑一遍,把自由空间、薄透镜、球面镜这几个矩阵用熟。然后试着把你自己的光路用矩阵串联起来算一遍,和实验值对比一下。如果对得上,说明你的符号约定和单位处理都没问题;如果对不上,检查一下矩阵乘法的顺序和符号约定,大概率是这两个地方出了问题。
我自己刚开始用ABCD定律的时候,最大的收获不是学会了几个矩阵,而是建立了一种“把光路变成矩阵链”的思维方式。一旦习惯了这种思维方式,再复杂的光路都能拆解成基本元件的组合,计算起来心里特别有底。希望这篇内容能帮你建立起同样的直觉。