当麦克斯韦方程组遇上Python代码,抽象的电磁学公式便跃然屏上。这不是传统物理教材的复述,而是一场用代码解构场论的视觉盛宴。我们将从点电荷的电场出发,逐步构建出载流导线的磁场模型,最终实现可交互的动态场图——所有这一切,只需NumPy的矩阵运算和Matplotlib的绘图魔法。
库仑定律的数学之美在代码中表现得淋漓尽致。我们先构建一个二维平面网格,用NumPy的meshgrid生成坐标点:
python复制import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
接下来定义点电荷电场计算函数。注意我们使用矢量化运算避免循环:
python复制def point_charge_field(q, x0, y0, X, Y):
r = np.sqrt((X-x0)**2 + (Y-y0)**2)
Ex = q * (X-x0) / r**3
Ey = q * (Y-y0) / r**3
return Ex, Ey
提示:在实际物理场景中,当r接近0时会遇到奇点问题,可以添加一个小量epsilon防止除零错误
绘制电场线时,Matplotlib的streamplot函数能自动计算场线密度:
python复制Ex, Ey = point_charge_field(1, 0, 0, X, Y)
plt.streamplot(X, Y, Ex, Ey, density=1.5, color='b')
plt.scatter([0], [0], c='r', s=100)
plt.title('点电荷电场线分布')
plt.show()
电磁场的线性叠加特性让复杂场的计算变得简单。假设我们有两个等量异号电荷:
python复制# 正电荷在(-1,0),负电荷在(1,0)
Ex1, Ey1 = point_charge_field(1, -1, 0, X, Y)
Ex2, Ey2 = point_charge_field(-1, 1, 0, X, Y)
Ex_total = Ex1 + Ex2
Ey_total = Ey1 + Ey2
绘制结果时,可以同时显示电场线和等势面:
python复制plt.figure(figsize=(12,5))
plt.subplot(121)
plt.streamplot(X, Y, Ex_total, Ey_total, color='b')
plt.scatter([-1,1], [0,0], c=['r','b'], s=100)
# 计算电势并绘制等势线
potential = -np.log(np.sqrt((X+1)**2 + Y**2)) + np.log(np.sqrt((X-1)**2 + Y**2))
plt.subplot(122)
plt.contour(X, Y, potential, levels=20, cmap='RdYlBu')
plt.colorbar()
plt.title('电偶极子等势线')
plt.show()
根据毕奥-萨伐尔定律,无限长直导线产生的磁场强度与距离成反比:
python复制def infinite_wire_field(I, X, Y):
"""计算无限长直导线在XY平面产生的磁场"""
r = np.sqrt(X**2 + Y**2)
Bx = -I * Y / r**2
By = I * X / r**2
return Bx, By
绘制磁感线时,可以添加箭头表示方向:
python复制Bx, By = infinite_wire_field(1, X, Y)
plt.streamplot(X, Y, Bx, By, color='g', density=2)
plt.title('无限长直导线磁感线')
plt.show()
圆形电流环轴线上的磁场分布是电磁学经典问题。我们首先定义电流微元产生的磁场:
python复制def circular_loop_field(I, a, X, Y, Z, n_segments=100):
"""计算圆形电流环在空间产生的磁场"""
phi = np.linspace(0, 2*np.pi, n_segments)
dl = a * 2*np.pi/n_segments # 电流微元长度
# 计算每个微元产生的磁场并叠加
Bx, By, Bz = np.zeros_like(X), np.zeros_like(Y), np.zeros_like(Z)
for angle in phi:
x0, y0 = a*np.cos(angle), a*np.sin(angle)
r_vec = np.array([X-x0, Y-y0, Z])
r = np.linalg.norm(r_vec, axis=0)
dl_vec = dl * np.array([-np.sin(angle), np.cos(angle), 0])
# 毕奥-萨伐尔定律
dB = I * np.cross(dl_vec[:,None,None], r_vec) / r**3
Bx += dB[0]
By += dB[1]
Bz += dB[2]
return Bx, By, Bz
注意:这个计算量较大,实际应用时可考虑使用Numba加速或简化模型
使用Matplotlib的FuncAnimation可以创建动态场图。以下示例展示振荡电偶极子的辐射场:
python复制from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots(figsize=(8,6))
q0 = 1 # 初始电荷量
omega = 0.5 # 振荡频率
def update(frame):
ax.clear()
t = frame * 0.1
q = q0 * np.cos(omega * t)
Ex, Ey = point_charge_field(q, -1, 0, X, Y)
Ex += point_charge_field(-q, 1, 0, X, Y)[0]
Ey += point_charge_field(-q, 1, 0, X, Y)[1]
ax.streamplot(X, Y, Ex, Ey, color='b', density=1.5)
ax.scatter([-1,1], [0,0], c=['r','b'], s=100)
ax.set_title(f'振荡电偶极子 t={t:.1f}s')
ani = FuncAnimation(fig, update, frames=100, interval=50)
plt.close()
结合ipywidgets创建可交互界面:
python复制from ipywidgets import interact
@interact
def plot_field(q1=(-2,2,0.1), q2=(-2,2,0.1), x1=(-3,3,0.5), x2=(-3,3,0.5)):
Ex, Ey = point_charge_field(q1, x1, 0, X, Y)
Ex += point_charge_field(q2, x2, 0, X, Y)[0]
Ey += point_charge_field(q2, x2, 0, X, Y)[1]
plt.figure(figsize=(8,6))
plt.streamplot(X, Y, Ex, Ey, color='b', density=1.5)
plt.scatter([x1,x2], [0,0], c=['r' if q1>0 else 'b', 'r' if q2>0 else 'b'], s=100)
plt.title('双电荷系统电场线')
plt.show()
实际电容器边缘的电场分布往往被简化处理。我们可以用数值方法精确模拟:
python复制def parallel_plate_field(V, d, L, X, Y):
"""计算平行板电容器的电场分布"""
# 上板电势V/2,下板-V/2
top_plate = (np.abs(Y - d/2) < 0.1) & (np.abs(X) < L/2)
bottom_plate = (np.abs(Y + d/2) < 0.1) & (np.abs(X) < L/2)
# 使用松弛法求解泊松方程
phi = np.zeros_like(X)
phi[top_plate] = V/2
phi[bottom_plate] = -V/2
for _ in range(1000): # 迭代次数
phi_new = phi.copy()
phi_new[1:-1,1:-1] = 0.25*(phi[2:,1:-1] + phi[:-2,1:-1] +
phi[1:-1,2:] + phi[1:-1,:-2])
phi = phi_new
# 计算电场强度
Ey, Ex = np.gradient(-phi)
return Ex, Ey
对于复杂三维场分布,可以导出数据用ParaView等工具可视化:
python复制def save_vtk(filename, X, Y, Z, Bx, By, Bz):
"""将磁场数据保存为VTK格式"""
from pyevtk.hl import gridToVTK
gridToVTK(filename, X[:,:,0], Y[0,:,:], Z[:,0,:],
pointData={'B': (Bx, By, Bz)})
在Jupyter notebook中,还可以使用plotly实现交互式3D可视化:
python复制import plotly.graph_objects as go
fig = go.Figure(data=go.Cone(
x=X.flatten(), y=Y.flatten(), z=np.zeros_like(X).flatten(),
u=Bx.flatten(), v=By.flatten(), w=np.zeros_like(Bx).flatten(),
colorscale='Blues', sizemode="absolute", sizeref=0.1))
fig.update_layout(scene=dict(aspectratio=dict(x=1, y=1, z=0.5)))
fig.show()
电磁场的可视化不仅是理论验证的工具,更是理解复杂物理现象的关键。当看到代码生成的场线与教科书图示完美吻合时,那种"顿悟"的喜悦正是计算物理的魅力所在。