☰
贝塞尔波束CST到FDTD仿真全流程:相位计算、电场导出与验证
2026/10/21 6:59:34 网站建设 项目流程

贝塞尔波束在仿真圈里是那种“概念不复杂、跑通要半天”的东西。公式里J0函数、锥面相位一看就懂,等你真的要把一个零阶贝塞尔波束从相位计算一路做到CST仿真、导出电场、再用FDTD复现,才会发现细节全藏在参数衔接和数据处理里。这篇文章就把这条链路完整走一遍:先用Python把口径相位算好,讲清楚CST里怎么设激励和边界,再手写脚本把导出的电场文件解析成验证曲线,最后说说FDTD复现时最容易翻车的几个地方。适合正在做太赫兹成像、无线能量传输、微波定向辐照这类无衍射波束仿真的工程师,也适合刚接触CST想找一个完整案例练手的学习者。

1. 贝塞尔波束的物理图像与仿真目标

1.1 无衍射的本质:无数个平面波在锥面上相干叠加

零阶贝塞尔波束的电场可以写成:

E(r, z) = A · J0(k_r · r) · e^(-j k_z z)

其中J0是第一类零阶贝塞尔函数,k_r = k·sinθ,k_z = k·cosθ,k = 2π/λ。这个式子很短,但信息量非常大:横向截面形状只跟径向距离r有关,不随传播距离z变化,所以叫“无衍射”。别被这个名字唬住,它不是真的永不发散,而是把无数个传播方向相同、与z轴夹角同为θ的平面波在轴线上相干叠加。单个平面波都在正常传播,但叠加之后,干涉让其他方向相互抵消,只有轴线附近持续加强,于是形成一根稳定的亮轴。

用一个生活类比:一堆手电筒同时朝同一个锥面方向照,在锥顶附近光线交叉叠加,形成一条特别亮的“光轴”;离得远了,各家手电筒的光各走各的,亮轴就散了。有限口径的贝塞尔波束也一样,它的无衍射距离约等于 z_max ≈ R / tanθ,口径半径R越大、锥角θ越小,这段稳定区域越长。J0函数的旁瓣特征也值得记住:第一旁瓣峰值约为主瓣的40%,换算成dB大约-8dB。后面判断仿真波束质量时,这个旁瓣比是硬指标。

1.2 仿真要交付的三样东西

做贝塞尔波束的CST仿真,不要一上来就开软件建模。我在项目里习惯先把交付物列清楚,否则很容易“模型跑完了,但不知道仿得对不对”。一个完整的仿真流程通常要产出三样东西:

  1. 口径相位分布:这是设计相位板、超表面或阵列馈电的依据,本质上是一个二维数组,每个坐标点对应一个相位值。
  2. 三维电场数据:在观测区域内验证是否存在无衍射区,至少需要若干个横向截面和一个过轴的纵向截面。
  3. 对比曲线:把仿真得到的轴向强度、径向剖面、相位剖面跟理论J0曲线放一起,定量说明“像不像贝塞尔”。

有了这三样,后续无论是写报告、做评审还是投文章,都能直接拿数据说话。下面每一章都围绕这三样交付物展开。

2. 先把口径相位算对:公式、参数与Python生成

2.1 相位公式与一个可复现的参数基准

假设用一块透射型相位板,垂直入射的平面波穿过口径后,每个半径r处所需的相位延迟是:

φ(r) = -k_r · r = -(2π/λ) · r · sinθ

符号取决于时谐约定。CST这类软件里导出的是复场量,实部/虚部对应的通常是e^(jωt)约定,所以相位滞后为负号。实际操作时,如果发现波束往反方向倾斜,把相位取反再跑一轮即可,这个后面会说怎么排查。

为了方便复现,我建议选定一组具体的参数基准。下面这组是我做太赫兹验证时常用的:

参数数值说明
频率 f0.3 THz典型太赫兹频段
波长 λ1.0 mmc/f
锥角 θ10°锥面半角
k_r约1090 rad/mk·sinθ
口径半径 R50 mm相位板/阵列外径
z_max约284 mmR/tanθ

这组参数下,中心亮斑第一零点在 r ≈ 2.405 / k_r ≈ 2.2 mm,也就是说毫米波长的波束被压到了毫米量级的亮轴,用来做近场成像或无线传能都挺典型。z_max大约284 mm,CST模型沿传播方向至少得留到这个长度再往后再加几个波长,否则截断边界会吃掉无衍射区。

2.2 相位网格生成的Python脚本

相位计算本身不复杂,但网格分辨率、坐标单位这些细节容易出错。下面的脚本会生成一个2001×2001的方形相位网格,并把结果存成方便导入CST的三列文件(x_mm, y_mm, phase_deg):

import numpy as np f = 0.3e12 c = 299792458.0 lam = c / f theta = np.deg2rad(10.0) kr = 2 * np.pi / lam * np.sin(theta) R = 0.05 # 口径半径,单位 m N = 2001 x = np.linspace(-R, R, N) X, Y = np.meshgrid(x, x) r = np.sqrt(X**2 + Y**2) phi = -kr * r # 锥面相位 phi_mod = np.mod(phi, 2*np.pi) # 包裹到 [0, 2π) # 口径外置为 NaN,方便后面判断有效区域 phi_out = np.where(r <= R, phi_mod, np.nan) data_out = np.stack([X*1000, Y*1000, np.degrees(phi_out)], axis=-1) np.savetxt("bessel_phase_mask.txt", data_out.reshape(-1, 3), fmt="%.6f", header="x_mm y_mm phase_deg")

网格密度怎么定?这里取2001个点覆盖100 mm的方形区域,间距50 μm,大约每波长20个点,足够描述2.2 mm的中心亮斑。如果网格只有每波长5个点,第一零点位置会被抹掉,后面径向剖面对比一定对不上。

2.3 相位文件如何变成CST里的激励

算好相位之后,怎么把它变成CST里的源,是很多人卡住的地方。常见做法有三种:

  • 场源导入法:在CST的源设置里选择口径场/场源类型,把(x, y, phase)表格以复振幅exp(j·phase)的形式作为z=0平面上的电场分布导入。这是最接近理论模型的方案,也是验证“相位→电场”流程的捷径。
  • 阵列馈电法:不用场源,而是在口径面上按同心圆布置一组离散激励端口。同一半径环上的所有端口相位相同,第m环相位为-k_r·r_m。径向采样间距建议不大于λ/2,对应到上面这组参数就是0.5 mm一档。
  • 相位板实体模型:如果最终工程交付物是介质相位板,则把相位换算成厚度 h(r) = φ_mod · λ / (2π(n-1)),n为介质折射率,然后直接建模。

第一次验证流程,我强烈建议先用场源导入法,因为它不引入阵列互耦、介质损耗这些额外变量,物理最纯粹。工程化阶段再换成阵列或相位板方案。

3. CST建模:激励方式、求解器与关键设置

3.1 两条建模路线:相位板与阵列馈电

前面提到的相位板实体模型和阵列馈电模型,对应两种完全不同的建模路线,选择标准很简单:你是要做物理验证还是做工程设计。

相位板路线更适合输出工程图纸。模型结构是一个中心薄、边缘厚的圆片,厚度按h(r)分布,用平面波垂直照射。它的优点是直接对应加工件,缺点是网格量大,尤其是介质边缘和厚度突变处需要加密,仿真时间成倍增加。阵列馈电路线则是用几十到几百个离散端口直接辐射,不建介质结构,仿真速度快,但结果里包含了阵列单元方向图和互耦效应,跟理想贝塞尔有一点偏差。

我的建议是分两轮做:第一轮用场源/阵列快速验证波束形成,把频域和时域结果对齐;第二轮再用相位板实体模型做工程化验证。两轮共用同一套监视器和后处理脚本,省事且可比。

3.2 求解器选择与FDTD复现的时间安排

CST里有频域求解器和时域求解器两类主力。频域求解器擅长窄带单频点,收敛快,对应“相位计算→单频电场导出”这条主线;时域求解器采用宽带脉冲激励,本质就是FDTD方法,适合做交叉验证。

一个稳妥的排期是:先跑频域,确认中心轴线有稳定的无衍射区,径向剖面接近J0;然后用完全相同的模型切到时域求解器再跑一遍,比较同一监视器上的电场幅值和相位。频域和时域结果在z_max范围内幅度差应小于0.5 dB,相位差只允许一个常数偏移(来自时间参考点的不同)。这一步做完,才敢说“CST结果可复现”。

3.3 边界条件、网格与监视器参考参数

下面这组设置是我在类似项目里验证过比较稳的起步参数,新项目可以先照着抄,再按需调整:

设置项推荐值说明
频率范围0.25~0.35 THz(时域)/ 0.3 THz单点(频域)宽带覆盖便于看色散
边界条件四周 open (add space),+z方向留z_max+5λ防止截断吃掉无衍射区
网格类型六面体网格,10~15 cells/λ中心轴线区域建议加密至20 cells/λ
E场监视器z=0, 50, 100, 150, 200, 250, 290 mm覆盖整个无衍射区
纵向截面监视器xz平面(y=0)画出亮轴的完整形态
轴对称处理若模型关于x和y方向对称,可开对称面能省3/4计算量

提一个容易忽略的点:时域求解器的仿真总时间不是随便给的,要让脉冲从源面传播到z_max再留出返回余量,然后看能量曲线衰减到-40 dB以下再停。否则截断效应会让后半段轴向强度出现明显的驻波纹波。

4. 电场导出与后处理:从ASCII文件到贝塞尔验证曲线

4.1 从CST导出电场文件的正确姿势

仿真跑完,在结果树里找到对应的E场监视器,右键导出文本数据。CST导出的ASCII文件通常每个点一行,列顺序大致是x、y、z、Re(Ex)、Im(Ex)、Re(Ey)、Im(Ey)、Re(Ez)、Im(Ez),注释行以#开头,坐标单位跟项目单位一致(通常是mm)。

这里有个经验之谈:导出之前先确认监视器平面的坐标范围和采样点密度。如果模型用了对称面,导出数据可能只有四分之一或一半口径,拿这种数据直接跟理论J0对比会错得离谱,必须做对称延拓或干脆关掉对称面重新导一次。

4.2 Python读取与相位展开

拿到ASCII文件后,用下面的脚本解析,注意列索引要以实际文件为准:

import numpy as np import matplotlib.pyplot as plt def load_cst_e(fname, unit_scale=1e-3): """读取CST导出的电场文件,默认坐标单位为mm。""" data = np.loadtxt(fname, comments="#") x = data[:, 0] * unit_scale y = data[:, 1] * unit_scale # 若实际文件列顺序不同,调整索引 Ex = data[:, 3] + 1j * data[:, 4] Ey = data[:, 5] + 1j * data[:, 6] Ez = data[:, 7] + 1j * data[:, 8] return x, y, Ex, Ey, Ez # 读取某个横向截面的数据,例如 z=100 mm 处 x, y, Ex, Ey, Ez = load_cst_e("Efield_z100.txt") amp = np.abs(Ex) phase = np.angle(Ex) # 相位在 [-pi, pi)

相位直接取angle会得到锯齿状的包裹相位。要验证锥面相位,需要沿某条半径方向做unwrap:

r = np.sqrt(x**2 + y**2) idx = np.argsort(r) r_sorted = r[idx] phase_sel = phase[idx] # 选一条过轴线的线数据 phase_unwrap = np.unwrap(phase_sel) # 在非奇点区域拟合相位斜率,理论值是 -kr mask = (r_sorted > 0.5e-3) & (r_sorted < 40e-3) slope = np.polyfit(r_sorted[mask], phase_unwrap[mask], 1)[0] print("拟合径向相位斜率: {:.2f} rad/m, 理论 -kr: {:.2f} rad/m".format( slope, -kr))

相位里会包含e^(-jk_z z)的常数相位因子,所以拟合斜率才是关键,绝对相位不用跟理论完全一致。

4.3 三条验证曲线与“像不像贝塞尔”的量化标准

仿真结果不能只靠眼睛看云图说“像”,要用三条曲线量化。

第一条是轴向强度曲线。把xz平面数据里y≈0的线提出来,画dB幅值对z的曲线。理论上在0到z_max范围内强度应保持平稳,波动最好在3 dB以内;过了z_max才开始明显跌落。

第二条是径向剖面。取无衍射区中段的某个横向截面(比如z=100 mm),画|Ex|随r的变化,叠加理论J0(k_r·r)。用第一零点的位置做快速判断:

from scipy.special import j0 # 取 r_sorted 和对应的幅值 amp_line(已沿半径排序) idx_zero = np.argmax(r_sorted > (2.4048 / kr)) r_zero_num = r_sorted[idx_zero] print("第一零点理论: {:.2f} mm, 仿真: {:.2f} mm".format( 2.4048/kr*1000, r_zero_num*1000))

第三条是复场相关系数。这个指标比肉眼对比云图严谨得多:

z_plane = 0.1 # 假设当前截面 z=100 mm E_th = j0(kr * r) * np.exp(-1j * (2*np.pi/lam * np.cos(theta)) * z_plane) rho = np.abs(np.sum(Ex * np.conj(E_th))) / ( np.sqrt(np.sum(np.abs(Ex)**2) * np.sum(np.abs(E_th)**2))) print("复场相关系数 rho = {:.3f}".format(rho))

相关系数大于0.9可以认为仿真波束与理想贝塞尔高度一致;低于0.8就老老实实回去查网格和边界设置。

5. FDTD复现的关键控制点:网格、边界与数值色散

5.1 在CST时域求解器里复现的检查清单

如果直接用CST时域求解器做FDTD复现,我建议按下面这个清单逐项确认,能少走很多弯路:

  1. 网格一致性:频域和时域尽量用同一套六面体网格参数,或者至少保证中心轴线区域每波长网格数相同。网格不一致时,两个求解器的径向相速度有差异,波束形态会微妙变化。
  2. 激励一致性:使用场源导入时,确认复振幅的相位列与之前相位文件一致,符号别在导入时翻转。
  3. 边界一致性:时域和频域都用 open (add space) 边界。如果时域结果出现低频振荡尾巴,多半是PML层数不足,把PML空间尺寸加大一档再跑。
  4. 收敛判据:让时域求解器的能量曲线衰减到-40 dB以下再停。我自己习惯再多跑一段,等-50 dB,虽然耗时间,但轴向强度曲线后半段的纹波会小很多。
  5. 结果对比:输出同一监视器平面的幅度和相位,跟频域结果做差。幅度差0.5 dB以内、相位差常数偏移,就算复现成功。

5.2 自制FDTD的维度陷阱:贝塞尔必须轴对称模型

如果你打算不依赖CST,自己写一段FDTD来复现,最大的坑是维度。很多人看到“二维截面能省内存”,就拿普通的x-z平面二维FDTD跑,结果发现横向剖面根本不是J0,而是一条余弦型的横向分布。原因很简单:普通二维FDTD假设结构沿y方向无限长、场沿y不变,等效成一个“平板波束”,而不是绕z轴旋转对称的零阶贝塞尔。

要在自编FDTD里复现贝塞尔,必须用轴对称模型,也就是(r, z)柱坐标,并且只保留m=0模。这样虽然是二维计算量,但场的横向分布仍然是J0,物理上才对应零阶贝塞尔。

5.3 轴对称TM模更新式与最小复现流程

轴对称TM模的场分量为E_r、E_z、H_φ,控制方程如下,这是自编FDTD的核心更新式:

# 轴对称TM模 (m=0) 更新式骨架 # ε ∂Er/∂t = -∂Hφ/∂z # ε ∂Ez/∂t = (1/r) ∂(r Hφ)/∂r # μ ∂Hφ/∂t = ∂Ez/∂r - ∂Er/∂z

自编完整求解器需要做Yee交错网格、Cuthack稳定条件、PML吸收边界、激励源注入和单频DFT提取,工程量不小。最小复现流程可以这样安排:

  1. 在z=0平面上设置口径源,场分布为 E_z = pulse(t)·cos(ωt - k_r·r),限定r<R,作为软源注入。
  2. 网格取dr=dz=λ/20,时间步按Courant条件取 dt ≤ 1/(c·sqrt(1/dr² + 1/dz²)) 的0.9倍。
  3. 在r_max和z_max处设置PML或简单吸收层,z方向计算域覆盖到z_max再加10个波长。
  4. 每个输出截面记录E_z的时间序列,用DFT提取0.3 THz的复振幅。
  5. 对比径向剖面与J0函数、轴向强度与理论z_max。

自编代码的数值色散比商用软件明显,所以网格密度至少要λ/20起步,并且把dr和dz取成一样,能减少各向异性色散对圆对称性的破坏。

6. 实测排查经验:相位、坐标与边界三大类问题

6.1 相位源最常见的翻车点

症状:轴线不在中心,或者波束沿z提前发散。最常见的根源有三个:相位符号反了、相位文件没有按CST实际坐标重采样、阵列馈电的阵元间距太粗。

排查方法是先只画相位剖面。把导入CST前的(x, y, phase)文件画成相位云图或者过轴线的相位曲线,确认斜率是-k_r而不是+k_r。符号一旦反了,波束会往相反方向倾斜,云图上一眼就能看出来。阵元间距太粗时,径向剖面会出现明显的栅瓣,中心亮斑周围多了不该有的旁瓣,这时候按λ/2间距重新布置阵元即可。

6.2 坐标单位与网格带来的测量偏差

症状:第一零点位置对不上理论值,往往是理论值的1.5倍甚至更大。排查两个地方:一是坐标单位。CST项目若用mm建模,导出文件坐标就是mm,后处理脚本必须乘1e-3再和米制单位下的k_r运算;忘掉这个换算,零点自然偏出去。二是网格密度。中心亮斑半径只有2.2 mm,波长又只有1 mm,如果中心区网格只有5 cells/λ,数值耗散会把尖峰抹平,第一零点看起来就变宽了。把中心区加密到20 cells/λ,零点位置通常会立刻回到理论值附近。

6.3 边界反射与计算时间不足的伪纹波

症状:轴向强度曲线在无衍射区中段出现周期性起伏,纹波幅度超过3 dB。这通常不是物理现象,而是边界反射。时域求解器里,若PML吸收不充分或者计算时间没等能量衰减完,反射波会叠加到主波束上形成驻波状纹波。

处理办法:把open边界的附加空间加大,比如+z方向额外加5到15个波长;PML层数按软件默认上限加一层;时域停止条件从-40 dB改成-50 dB。改完其中一个参数就重跑一次轴向曲线,看纹波是否下降,这样可以快速定位到底是谁引起的。

现象可能原因处理方向
波束轴线倾斜相位符号反了检查相位文件斜率,取反重导
出现额外栅瓣阵元间距太粗间距降到λ/2
第一零点位置偏大单位换算错/网格太粗核对mm-m换算,中心区加密至20 cells/λ
轴向纹波>3dBPML反射/计算时间不足增加PML空间,能量衰减到-50dB再停
频域时域对不齐网格不一致/源相位偏移统一网格与源文件,允许常数相位差

结尾

这些坑我基本都踩过一轮。现在做贝塞尔波束仿真的固定流程是:先用Python把相位文件生成出来,立刻画图检查斜率;导入CST后先用频域求解器跑一遍,导出径向和轴向两条曲线;确认没问题再切时域求解器做FDTD复现;最后所有数据统一进同一个后处理脚本出图。整套流程里最值得多花时间的其实是相位文件本身的检查——它是源头,源头错一步,后面所有验证都是在给错误数据打掩护。另一个小技巧是保存一个“后处理标准脚本”,每次只改文件名和参数基准,这样不同频段、不同锥角之间的对比会非常快,也能避免每次重新写读取代码时把列索引搞错。希望这套流程能帮你把从相位到电场的链路一次走通。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询