1. 课程导入与仿真环境搭建

电磁波传播是无线通信、雷达探测、天线设计、电磁兼容等工程领域的共同物理基础。解析方法(如均匀平面波解、菲涅尔反射系数、射线追踪)能给出清晰的物理图像,但一旦遇到分层介质、复杂边界、色散材料或任意激励波形,闭式解往往难以获得。数值仿真正是在这一环节发挥作用:它把麦克斯韦方程组(或由其导出的波动方程、传输线方程)离散为计算机可迭代求解的代数问题,使我们能够"看到"场随空间和时间的演化。

本课程面向的典型工程场景包括:自由空间与分层介质中的平面波传播、地面反射与多径效应、波导与传输线中的模式传播、时域有限差分(FDTD)中的脉冲传播与色散观察、以及简单散射体的近场分布。这些场景的共同点是:物理模型明确、边界条件可描述、结果可用解析解或已知规律交叉验证。课程的学习路径遵循"物理方程 → 离散格式 → 代码实现 → 可视化 → 验证与误差分析"的闭环,每一节都要求读者亲手跑通一段可复现的脚本,而不是停留在公式推导。

本课程约定:空间坐标取右手系,电磁波沿 +z 方向传播时,电场写在 x 分量、磁场写在 y 分量,时间因子取 ejωt。后续所有图示与代码均遵循这一约定,切换约定时会明确说明。

为什么先做"一维可视化"

在进入二维/三维网格之前,先用一维行波把"参数—波形—传播"的对应关系建立起来,是性价比最高的入门方式。一个沿 +z 传播的单频均匀平面波可写为 Ex(z,t)=E0cos(ωt−kz+φ0),其中 k=2π/λ,λ=c/f。只要在代码中改变 f、E0、φ0,就能直观看到波长伸缩、幅度缩放与相位平移。下图给出本节脚本的核心数据流:从物理参数出发,经采样与相位计算,生成时空场矩阵,再分别以"空间快照"和"时空瀑布图"两种视图呈现,最后用解析波长做一致性校验。

一维平面波可视化脚本的数据流与校验 物理参数输入 f = 1.0 GHz E₀ = 1.0 V/m φ₀ = 0 rad c = 3×10⁸ m/s λ = c/f = 0.3 m 空间/时间采样 z ∈ [0, 1.2] m Nz = 601 点 t ∈ [0, 3] ns Nt = 121 帧 Δz ≈ 2 mm ≪ λ 场矩阵计算 k = 2π/λ ω = 2πf E[z,t] = E₀·cos(ωt−kz) NumPy 广播生成 形状 (Nt, Nz) 双视图输出 ① 空间快照  E–z 曲线 ② 时空瀑布图  z–t 伪彩色 Matplotlib 绘制 一致性校验:从图中反读物理量 相邻同相点间距 = λ 快照中相邻波峰间距应等于 0.3 m;瀑布图斜率 Δz/Δt 应等于 c 若间距偏离,优先检查 Δz 是否过粗、k 是否用错单位(GHz→Hz) 校验通过 → 参数与离散设置可信,可进入下一节分层介质

环境安装与最小可运行脚本

推荐使用 Python 3.10 及以上版本,通过虚拟环境隔离依赖。以下命令在 Windows、macOS、Linux 上通用(Windows 下把 python3 换成 python 即可):

python3 -m venv emsim
source emsim/bin/activate        # Windows: emsim\Scripts\activate
pip install numpy scipy matplotlib
python -c "import numpy, scipy, matplotlib; print(numpy.__version__, scipy.__version__, matplotlib.__version__)"

版本检查通过后,编写第一个脚本 wave1d.py。关键点有三:一是用 numpy.linspace 生成空间与时间轴,保证 Δz 远小于 λ(本例 2 mm 对 300 mm,约 150 点/波长,足够平滑);二是用广播机制一次性生成二维场矩阵,避免双重循环;三是同时输出快照与瀑布图,便于从两个角度判断传播方向与速度。

import numpy as np
import matplotlib.pyplot as plt

c = 3e8
f = 1e9
E0, phi0 = 1.0, 0.0
lam = c / f
k = 2 * np.pi / lam
omega = 2 * np.pi * f

z = np.linspace(0, 1.2, 601)          # 空间轴,单位 m
t = np.linspace(0, 3e-9, 121)         # 时间轴,单位 s
E = E0 * np.cos(omega * t[:, None] - k * z[None, :] + phi0)

fig, ax = plt.subplots(1, 2, figsize=(11, 4))
ax[0].plot(z, E[0], color="#2c7fb8")
ax[0].set_xlabel("z / m"); ax[0].set_ylabel("Ex / (V/m)")
ax[0].set_title("t = 0 时刻空间快照")
ax[1].imshow(E, aspect="auto", origin="lower",
             extent=[z[0], z[-1], t[0]*1e9, t[-1]*1e9], cmap="RdBu_r")
ax[1].set_xlabel("z / m"); ax[1].set_ylabel("t / ns")
ax[1].set_title("时空瀑布图")
plt.tight_layout(); plt.show()

运行后应看到:左图是一条周期为 0.3 m 的余弦曲线;右图是红蓝相间的斜条纹,条纹斜率对应光速。若把 f 改为 2 GHz,左图波长减半、右图条纹变密,这正是"频率升高、波长缩短"的直接体现。若把 phi0 改为 π/2,曲线整体左移四分之一波长,可用来验证相位项符号:本课程约定 ejωt,故相位为 ωt−kz,z 增大时相位减小,波形向 +z 推进。

常见错误:把 f 写成 1(误以为单位是 GHz),会导致 λ=3×10⁸ m,图中几乎看不到变化;或把 t[:, None] 写成 t,广播失败报维度错误。遇到异常先打印 E.shape,应为 (121, 601)。

本节应达到的能力

完成本节后,读者应能独立完成三件事:第一,说清数值仿真相对于解析解的价值边界——它扩展了可处理问题的范围,但不能替代解析解做校验;第二,搭好可复用的 Python 环境,并理解 NumPy 广播在批量生成场数据中的作用;第三,用快照与瀑布图两种视图读出波长、传播方向与相速,并知道用解析 λ 做交叉验证。这套"参数—矩阵—双视图—校验"的工作方式将贯穿后续所有章节,是后续分层介质反射、FDTD 脉冲传播等内容的共同起点。