用Python和NumPy可视化理解波函数:从概率密度到薛定谔方程的可视化教程
用Python和NumPy可视化理解波函数:从概率密度到薛定谔方程的可视化教程
量子力学的抽象数学描述常常让初学者望而生畏。当教科书上写满Ψ(x,t)和积分符号时,我们很容易迷失在公式的森林中而忘记物理图像的本质。本文将通过Python代码和可视化手段,带你用程序员熟悉的工具重新认识波函数——不是通过复杂的推导,而是通过直观的图形和动画。
1. 环境准备与基础概念
在开始绘制波函数前,我们需要配置Python科学计算环境。推荐使用Anaconda发行版,它已经集成了我们所需的关键库:
conda create -n quantum python=3.9 conda activate quantum conda install numpy matplotlib scipy jupyter波函数的核心物理意义体现在玻恩规则中:|Ψ(x,t)|²表示概率密度。让我们用代码实现这个概念的转换:
import numpy as np import matplotlib.pyplot as plt # 创建一个简单的波函数示例 x = np.linspace(-5, 5, 1000) psi = np.exp(-x**2) * np.exp(1j * 2 * x) # 高斯波包乘以相位因子 plt.figure(figsize=(12, 4)) plt.subplot(121) plt.plot(x, np.real(psi), label="实部") plt.plot(x, np.imag(psi), label="虚部") plt.title("波函数Ψ(x)") plt.legend() plt.subplot(122) plt.plot(x, np.abs(psi)**2, 'r', label="|Ψ(x)|²") plt.title("概率密度") plt.legend() plt.show()这段代码揭示了波函数的几个关键特性:
- 波函数通常是复数,包含实部和虚部
- 相位因子(e^iφ)不影响概率密度分布
- 概率密度始终是实数和非负的
2. 一维无限深势阱的量子态
无限深势阱是最简单的量子系统之一,其解析解为: ψₙ(x) = √(2/L) sin(nπx/L), 其中n=1,2,3,...
让我们用NumPy实现这个系统:
def infinite_well(n, L=1, points=1000): x = np.linspace(0, L, points) psi = np.sqrt(2/L) * np.sin(n * np.pi * x / L) return x, psi # 绘制前三个能级 plt.figure(figsize=(10, 6)) for n in range(1, 4): x, psi = infinite_well(n) plt.plot(x, psi + n, label=f"n={n}") plt.fill_between(x, n, psi + n, alpha=0.2) plt.xlabel("位置 x") plt.ylabel("能级 + 波函数") plt.title("无限深势阱中的前三个定态") plt.legend() plt.grid(True)观察这些波函数,我们可以发现:
- 节点数随能级增加(n-1个节点)
- 基态(n=1)在势阱中心概率最大
- 随着n增大,粒子趋向于经典均匀分布
3. 量子谐振子的可视化
谐振子势V(x) = ½mω²x²是另一个重要模型,其解为厄米多项式:
from scipy.special import hermite def harmonic_oscillator(n, x): # 归一化常数 norm = 1 / np.sqrt(2**n * np.math.factorial(n)) * (1/np.pi)**0.25 Hn = hermite(n) return norm * Hn(x) * np.exp(-x**2 / 2) x = np.linspace(-4, 4, 1000) plt.figure(figsize=(10, 6)) for n in range(0, 4): psi = harmonic_oscillator(n, x) plt.plot(x, psi + n, label=f"n={n}") plt.fill_between(x, n, psi + n, alpha=0.2) plt.title("量子谐振子的前四个能级") plt.xlabel("位置 x") plt.ylabel("能级 + 波函数") plt.legend() plt.grid(True)谐振子展示的量子效应更加明显:
- 存在非零的基态能量(零点能)
- 波函数在经典禁区(|x| > √(2E/mω²))仍有非零概率
- 能级等间距分布
4. 时间演化的动态可视化
静态波函数只展示了量子态的一部分,时间演化才是量子动力学的核心。让我们实现薛定谔方程的时间演化:
from matplotlib.animation import FuncAnimation # 无限深势阱中的叠加态 L = 1 x = np.linspace(0, L, 500) psi1 = np.sqrt(2/L) * np.sin(np.pi * x / L) psi2 = np.sqrt(2/L) * np.sin(2 * np.pi * x / L) psi_initial = (psi1 + psi2) / np.sqrt(2) # 归一化叠加态 # 时间演化函数 def time_evolve(psi, E, t): return psi * np.exp(-1j * E * t) # 创建动画 fig, ax = plt.subplots(figsize=(10, 5)) line, = ax.plot(x, np.abs(psi_initial)**2) ax.set_ylim(0, 3) ax.set_xlabel("位置 x") ax.set_ylabel("概率密度 |Ψ|²") def update(t): E1 = (np.pi**2) / (2 * L**2) # n=1能量 E2 = (2 * np.pi)**2 / (2 * L**2) # n=2能量 psi_t = (time_evolve(psi1, E1, t) + time_evolve(psi2, E2, t)) / np.sqrt(2) line.set_ydata(np.abs(psi_t)**2) return line, ani = FuncAnimation(fig, update, frames=np.linspace(0, 10, 200), blit=True) plt.title("叠加态的时间演化") plt.close()这段代码展示了量子力学最神奇的现象之一——相位干涉。虽然我们无法在此展示动画,但运行代码你将看到:
- 概率密度随时间周期性变化
- 波包在势阱中来回"滑动"
- 量子相干性的直观表现
5. 量子测量与期望值计算
量子力学中的测量对应着算符的期望值计算。让我们实现位置和动量的期望值计算:
def expectation_value(x, psi, operator): """计算算符的期望值""" prob = np.abs(psi)**2 prob /= np.sum(prob) # 数值归一化 if operator == "x": return np.sum(x * prob) elif operator == "x^2": return np.sum(x**2 * prob) elif operator == "p": # 数值导数计算动量 dx = x[1] - x[0] dpsi = np.gradient(psi, dx) return -1j * np.sum(psi.conj() * dpsi) * dx # 测试基态谐振子 x = np.linspace(-5, 5, 10000) psi_ground = harmonic_oscillator(0, x) print(f"位置期望值: {expectation_value(x, psi_ground, 'x'):.3f}") print(f"位置平方期望: {expectation_value(x, psi_ground, 'x^2'):.3f}") print(f"动量期望值: {expectation_value(x, psi_ground, 'p'):.3f}")输出结果验证了量子谐振子的基本性质:
- 位置期望值为零(对称分布)
- 动量期望值为零(实波函数)
- 位置方差不为零(不确定性原理)
6. 从数值解理解薛定谔方程
对于没有解析解的势场,我们可以用数值方法求解定态薛定谔方程。以下使用有限差分法:
def solve_schrodinger(V, x): N = len(x) dx = x[1] - x[0] # 构造哈密顿矩阵 kinetic = np.zeros((N, N)) np.fill_diagonal(kinetic, -2) np.fill_diagonal(kinetic[1:], 1) np.fill_diagonal(kinetic[:, 1:], 1) kinetic = -kinetic / (2 * dx**2) potential = np.diag(V(x)) H = kinetic + potential # 求解本征值问题 energies, states = np.linalg.eigh(H) return energies, states.T # 转置使每行是一个本征态 # 有限深势阱示例 x = np.linspace(-5, 5, 1000) V = lambda x: 0.5 * x**2 * (np.abs(x) < 3) + 10 * (np.abs(x) >= 3) energies, states = solve_schrodinger(V, x) # 绘制前三个能级 plt.figure(figsize=(10, 6)) for i in range(3): plt.plot(x, states[i] + energies[i], label=f"E={energies[i]:.2f}") plt.plot(x, V(x), 'k--', label="势能V(x)") plt.legend() plt.title("有限深势阱的数值解") plt.xlabel("位置 x") plt.ylabel("能量 + 波函数")这种方法可以处理任意形状的势场,是研究复杂量子系统的有力工具。
