量子力学入门:从波函数到薛定谔方程的5个关键概念(附Python可视化)
量子力学入门从波函数到薛定谔方程的5个关键概念附Python可视化量子力学常常被描绘为一门深奥、反直觉的学科充满了抽象的数学和哲学思辨。对于许多编程爱好者和理工科背景的学习者来说这种印象往往让人望而却步。然而如果我们换一个视角将量子力学视为一套描述微观世界行为的“编程语言”或“计算框架”其核心逻辑便会清晰许多。本文正是为这样的你准备的——我们不会陷入冗长的历史背景或哲学讨论而是直接切入核心的数学对象和方程并借助Python这一强大工具将抽象概念转化为可视化的、可交互的代码。通过亲手编写代码来模拟一维无限深势阱中的粒子绘制其波函数和概率密度你将直观地理解“量子化”、“叠加态”和“概率诠释”这些听起来玄乎的概念。我们的目标是在完成本文的阅读和实践后你不仅能说出薛定谔方程是什么更能用代码“解出”它并亲眼看到量子世界的独特规则是如何在屏幕上展现的。1. 核心基石理解波函数及其概率诠释在经典物理中描述一个粒子我们通常需要它的位置和速度。但在量子世界里这个描述方式彻底失效了。取而代之的是一个更基本的数学对象波函数通常用希腊字母ψ读作“普赛”表示。对于一维空间中的一个粒子其波函数写作 ψ(x, t)它是空间坐标 x 和时间 t 的复函数。注意波函数本身并非物理上可观测的量。它是一个概率幅包含了系统所有可能状态的量子信息。波函数的物理意义由马克斯·玻恩提出的概率诠释给出波函数模的平方 |ψ(x, t)|²代表了在时间 t于位置 x 附近单位体积内找到该粒子的概率密度。这是连接抽象的数学形式与可观测物理现实的桥梁。归一化条件由于粒子必须在空间中的某个地方被找到所以全空间找到它的总概率必须为1。这要求波函数满足归一化条件 ∫_{-∞}^{∞} |ψ(x, t)|² dx 1合格波函数的条件一个物理上可接受的波函数必须是单值、连续、有限的在某些势场边界处其一阶导数也需连续。为了直观感受让我们用Python生成一个最简单的高斯波包并观察其概率密度分布。高斯波包常被用来近似描述一个位置相对确定的自由粒子。import numpy as np import matplotlib.pyplot as plt # 设置参数 x np.linspace(-5, 5, 1000) # 空间坐标范围 x0 0.0 # 波包中心位置 sigma 1.0 # 波包宽度参数 # 定义一个高斯型波函数未归一化 psi np.exp(-(x - x0)**2 / (2 * sigma**2)) # 手动归一化 norm np.sqrt(np.trapz(np.abs(psi)**2, x)) # 计算归一化因子 psi_normalized psi / norm # 计算概率密度 probability_density np.abs(psi_normalized)**2 # 可视化 fig, (ax1, ax2) plt.subplots(1, 2, figsize(12, 4)) # 绘制波函数的实部和虚部此处为实函数 ax1.plot(x, psi_normalized.real, b-, labelRe(ψ)) ax1.plot(x, psi_normalized.imag, r--, labelIm(ψ)) # 本例中虚部为0 ax1.set_xlabel(位置 x) ax1.set_ylabel(波函数 ψ(x)) ax1.set_title(高斯波包归一化后) ax1.legend() ax1.grid(True, alpha0.3) # 绘制概率密度 ax2.plot(x, probability_density, g-, linewidth2) ax2.fill_between(x, probability_density, alpha0.3, colorgreen) ax2.set_xlabel(位置 x) ax2.set_ylabel(概率密度 |ψ(x)|²) ax2.set_title(粒子位置的概率密度分布) ax2.grid(True, alpha0.3) plt.tight_layout() plt.show() # 验证归一化 total_probability np.trapz(probability_density, x) print(f总概率应接近1: {total_probability:.6f})运行这段代码你会看到左侧是光滑的钟形波函数本例中为实函数右侧是相应的概率密度分布。阴影区域形象地展示了粒子最可能出现在波包中心附近。改变sigma参数观察波包宽度如何影响位置的不确定性——这是海森堡不确定性原理的一个直观体现。2. 算符与可观测量量子力学中的“测量指令”在经典力学中一个物理量如位置、动量、能量直接对应一个数值。在量子力学中物理量由算符来表示。算符是一种对波函数进行操作的数学指令。当我们对一个量子系统进行测量时过程可以概括为系统处于某个由波函数 ψ 描述的态。对某个物理量 A对应算符 Â进行测量。测量结果只能是该算符的本征值之一记为 a_n。测量后系统的波函数会坍缩到与该本征值 a_n 对应的本征态ψ_n 上。最关键的一类算符是厄米算符它们的本征值是实数这保证了测量结果总是实数。两个最基础的算符是物理量算符坐标表象作用方式位置 (x)x̂乘以坐标 x x̂ ψ(x) x · ψ(x)动量 (p)p̂对坐标求导 p̂ ψ(x) -iħ (∂/∂x) ψ(x)其中ħh-bar是约化普朗克常数一个非常小的数是量子效应的尺度标志。动量算符包含虚数单位 i 和导数这直接导致了量子力学的许多奇特性质比如波函数的振荡行为。让我们用代码直观感受一下算符的作用。我们将定义一个简单的波函数然后让位置和动量算符“作用”在它上面。import numpy as np import matplotlib.pyplot as plt # 定义常数 (使用原子单位简化设 ħ 1) hbar 1.0 # 定义空间网格 x np.linspace(-2*np.pi, 2*np.pi, 500) dx x[1] - x[0] # 定义一个简单的波函数平面波与高斯包络的乘积使其在边界处趋于0 k0 3.0 # 初始波矢与动量相关 psi np.exp(-x**2 / 4) * np.exp(1j * k0 * x) # 复波函数 psi psi / np.sqrt(np.trapz(np.abs(psi)**2, x)) # 归一化 # 1. 位置算符的作用x̂ ψ(x) x * ψ(x) position_operated x * psi # 2. 动量算符的作用p̂ ψ(x) -iħ * dψ/dx # 使用中心差分法数值求导 dpsi_dx np.gradient(psi, dx, edge_order2) momentum_operated -1j * hbar * dpsi_dx # 可视化 fig, axes plt.subplots(2, 2, figsize(12, 8)) # 原始波函数的实部和虚部 axes[0, 0].plot(x, psi.real, b-, labelRe(ψ)) axes[0, 0].plot(x, psi.imag, r--, labelIm(ψ)) axes[0, 0].set_xlabel(x) axes[0, 0].set_ylabel(ψ(x)) axes[0, 0].set_title(原始波函数) axes[0, 0].legend() axes[0, 0].grid(True, alpha0.3) # 原始波函数的概率密度 axes[0, 1].plot(x, np.abs(psi)**2, g-) axes[0, 1].fill_between(x, np.abs(psi)**2, alpha0.3, colorgreen) axes[0, 1].set_xlabel(x) axes[0, 1].set_ylabel(|ψ(x)|²) axes[0, 1].set_title(原始概率密度) axes[0, 1].grid(True, alpha0.3) # 位置算符作用后的结果 axes[1, 0].plot(x, position_operated.real, labelRe(x̂ψ)) axes[1, 0].plot(x, position_operated.imag, --, labelIm(x̂ψ)) axes[1, 0].set_xlabel(x) axes[1, 0].set_ylabel(x̂ ψ(x)) axes[1, 0].set_title(位置算符作用后的波函数) axes[1, 0].legend() axes[1, 0].grid(True, alpha0.3) # 动量算符作用后的结果 axes[1, 1].plot(x, momentum_operated.real, labelRe(p̂ψ)) axes[1, 1].plot(x, momentum_operated.imag, --, labelIm(p̂ψ)) axes[1, 1].set_xlabel(x) axes[1, 1].set_ylabel(p̂ ψ(x)) axes[1, 1].set_title(动量算符作用后的波函数) axes[1, 1].legend() axes[1, 1].grid(True, alpha0.3) plt.tight_layout() plt.show()观察图像你会发现位置算符的作用只是将波函数乘以 x因此波包形状被扭曲中心被“拉伸”或“压缩”。而动量算符的作用求导则显著改变了波函数的形态特别是其振荡频率和相位这反映了动量与波函数空间变化率之间的深刻联系。3. 势能与哈密顿算符定义量子游戏的“场地规则”在经典力学中势能 V(x)如重力势能、弹簧势能决定了粒子所受的力。在量子力学中势能同样至关重要它通过哈密顿算符Ĥ进入核心方程。哈密顿算符代表了系统的总能量它是动能算符T̂和势能算符V̂之和Ĥ T̂ V̂ (p̂² / 2m) V(x)在一维坐标表象下代入动量算符 p̂ -iħ ∂/∂x我们得到哈密顿算符的具体形式Ĥ - (ħ² / 2m) (∂²/∂x²) V(x)这个算符是量子力学的“引擎”。系统的所有动力学性质——能量如何、状态如何随时间演化——都封装在这个算符中。不同的势能函数 V(x) 定义了不同的量子系统就像不同的游戏规则自由粒子V(x) 0粒子不受力。无限深方势阱V(x) 0 (在阱内), ∞ (在阱外)。这是最简单的束缚态模型能完美展示量子化。谐振子势V(x) (1/2) m ω² x²在物理和化学中无处不在。势垒/势阶用于研究量子隧穿效应。下面我们将重点实现一维无限深势阱的模型。在这个模型中粒子被限制在 [0, L] 的区间内完全自由运动但在边界处势能为无穷大因此波函数在边界处必须为零。import numpy as np import matplotlib.pyplot as plt from scipy import sparse from scipy.sparse.linalg import eigs # 系统参数 L 1.0 # 势阱宽度 N 500 # 空间离散点数 x np.linspace(0, L, N) dx x[1] - x[0] # 构建离散化的哈密顿算符矩阵使用原子单位 ħ m 1 # 动能部分二阶导数的中心差分近似 (-1/2 * d^2/dx^2) # 使用稀疏矩阵以提高效率 diag np.ones(N) * (1.0 / dx**2) off_diag np.ones(N-1) * (-0.5 / dx**2) # 动能算符 T -0.5 * ∇^2 的矩阵表示 T sparse.diags([diag, off_diag, off_diag], [0, -1, 1], formatcsr) T -0.5 * T # 乘以 -ħ²/(2m)此处ħm1 # 势能部分无限深势阱阱内为0阱外为无穷大。 # 在矩阵方法中我们只需在阱内求解边界条件通过波函数为0来体现。 # 因此我们只处理区间内的点势能矩阵 V 是对角矩阵此处全为0。 V sparse.diags(np.zeros(N), 0, formatcsr) # 总哈密顿量 H T V # 由于是无限深势阱我们直接使用解析解进行验证和可视化 def infinite_well_wavefunction(n, x, L): 返回一维无限深势阱第n个本征态的波函数 return np.sqrt(2/L) * np.sin(n * np.pi * x / L) def infinite_well_energy(n, L, m1.0, hbar1.0): 返回一维无限深势阱第n个能级的能量 return (n**2 * np.pi**2 * hbar**2) / (2 * m * L**2) # 计算前5个能级和波函数 n_levels 5 energies_analytic [] wavefunctions_analytic [] for n in range(1, n_levels1): energies_analytic.append(infinite_well_energy(n, L)) wavefunctions_analytic.append(infinite_well_wavefunction(n, x, L)) # 数值求解哈密顿矩阵的本征值和本征态前5个 # 注意scipy的eigs求解的是绝对值最大的几个特征值我们需要最小的几个。 # 对于这个正定矩阵最小的特征值对应基态。 num_eigenvalues 5 vals, vecs eigs(H, knum_eigenvalues, whichSM) # SM Smallest Magnitude vals np.real(vals) vecs np.real(vecs) # 取实部本征函数应为实函数 idx vals.argsort() # 按能量排序 vals vals[idx] vecs vecs[:, idx] # 可视化对比 fig, axes plt.subplots(n_levels, 2, figsize(10, 2.5*n_levels)) for i in range(n_levels): n i 1 # 左侧解析解波函数与概率密度 psi_analytic wavefunctions_analytic[i] axes[i, 0].plot(x, psi_analytic, b-, labelfψ_{n}(x) 解析) axes[i, 0].plot(x, psi_analytic**2, r--, labelf|ψ_{n}(x)|² 解析) axes[i, 0].axhline(y0, colork, linestyle-, linewidth0.5) axes[i, 0].set_ylabel(fn{n}) if i n_levels-1: axes[i, 0].set_xlabel(位置 x) axes[i, 0].legend(locupper right, fontsizesmall) axes[i, 0].set_title(f能级 {n}: E {energies_analytic[i]:.3f}) axes[i, 0].grid(True, alpha0.3) # 右侧数值解波函数需归一化并调整相位与解析解匹配 psi_numeric vecs[:, i] # 数值解可能整体差一个负号通过点积判断相位 if np.dot(psi_numeric, psi_analytic) 0: psi_numeric -psi_numeric axes[i, 1].plot(x, psi_numeric, g-, labelfψ_{n}(x) 数值) axes[i, 1].plot(x, psi_numeric**2, m:, labelf|ψ_{n}(x)|² 数值) axes[i, 1].axhline(y0, colork, linestyle-, linewidth0.5) if i n_levels-1: axes[i, 1].set_xlabel(位置 x) axes[i, 1].legend(locupper right, fontsizesmall) axes[i, 1].set_title(f数值解能量: {vals[i]:.3f}) axes[i, 1].grid(True, alpha0.3) plt.suptitle(一维无限深势阱解析解 vs 数值解, fontsize16) plt.tight_layout() plt.show()运行这段代码你会看到前五个能级对应的波函数实线和概率密度虚线。注意观察量子化能量只能取离散值 E_n ∝ n²。节点第 n 个能级的波函数有 (n-1) 个节点与x轴的交点。宇称波函数关于势阱中心具有交替的奇偶性。概率密度在阱内并非均匀分布基态 (n1) 粒子最可能出现在中心而激发态则在不同位置有多个峰值。4. 定态薛定谔方程求解能量的“本征值问题”当势能 V(x) 不显含时间时我们可以分离变量得到与时间无关的定态薛定谔方程Ĥ ψ_n(x) E_n ψ_n(x)这是一个本征值方程。求解它意味着我们要找到那些特殊的波函数 ψ_n(x)称为能量本征态或定态当哈密顿算符作用其上时效果仅仅是乘以一个常数 E_n称为本征值即系统的可能能量。这些定态具有极其重要的性质确定的能量处于定态 ψ_n 的系统测量其能量必定得到 E_n。稳定的概率分布概率密度 |ψ_n(x)|² 不随时间变化。时间演化简单如果系统初始处于某个定态其随时间的演化只是乘以一个相位因子 e^{-iE_n t/ħ}不影响可观测的概率分布。上一节的无限深势阱例子我们实际上已经求解了其定态薛定谔方程Ĥ T̂因为 V0。现在让我们尝试一个更复杂的势能有限深势阱。粒子有可能尽管概率很小出现在经典不允许的区域阱外这就是量子隧穿的雏形。import numpy as np import matplotlib.pyplot as plt from scipy import sparse from scipy.sparse.linalg import eigsh # 系统参数 L 4.0 # 计算区域总宽度 N 1000 # 离散点数 x np.linspace(-L/2, L/2, N) dx x[1] - x[0] # 定义有限深方势阱 V(x) V0 20.0 # 势阱深度 width 1.0 # 势阱宽度 V np.zeros_like(x) V[np.abs(x) width/2] V0 # 阱外势能为V0 # 构建哈密顿矩阵 (ħ m 1) # 动能部分使用二阶中心差分 diag np.ones(N) * (1.0 / dx**2) off_diag np.ones(N-1) * (-0.5 / dx**2) T sparse.diags([diag, off_diag, off_diag], [0, -1, 1], formatcsr) T -0.5 * T # 势能部分对角矩阵 V_matrix sparse.diags(V, 0, formatcsr) H T V_matrix # 求解最小的几个本征值和本征向量束缚态 num_bound_states 4 # 使用eigsh求解实对称矩阵的特征值问题 whichSA 表示Smallest Algebraic eigenvalues, eigenvectors eigsh(H, knum_bound_states, whichSA) idx eigenvalues.argsort() eigenvalues eigenvalues[idx] eigenvectors eigenvectors[:, idx] # 可视化势阱和波函数 fig, ax1 plt.subplots(figsize(10, 6)) # 绘制势能曲线 ax1.plot(x, V, k-, linewidth2, label势能 V(x)) ax1.fill_between(x, V, 0, alpha0.2, colorgray) ax1.set_xlabel(位置 x, fontsize12) ax1.set_ylabel(能量 / 势能, colork, fontsize12) ax1.tick_params(axisy, labelcolork) ax1.grid(True, alpha0.3) # 为每个束缚态绘制波函数并偏移其能量位置以便观察 colors [b, r, g, m] for i in range(num_bound_states): E eigenvalues[i] psi eigenvectors[:, i] # 归一化波函数 psi psi / np.sqrt(np.trapz(np.abs(psi)**2, x)) # 将波函数按比例缩放并平移到其能量本征值位置 scale 0.2 * L / np.max(np.abs(psi)) # 缩放因子 y_offset E # 能量偏移 ax1.plot(x, psi * scale y_offset, colorcolors[i], linewidth1.5, labelfψ_{i1}, E{E:.3f}) # 填充概率密度区域 ax1.fill_between(x, y_offset, psi * scale y_offset, colorcolors[i], alpha0.1) # 绘制能级线 for i, E in enumerate(eigenvalues): ax1.axhline(yE, colorcolors[i], linestyle:, linewidth1, alpha0.7) ax1.legend(locupper right, fontsize10) ax1.set_title(有限深方势阱中的束缚态波函数与能级, fontsize14) ax1.set_ylim(bottommin(V)-2, topmax(eigenvalues)5) plt.tight_layout() plt.show() print(有限深势阱束缚态能量:) for i, E in enumerate(eigenvalues): print(f 能级 {i1}: {E:.4f})观察结果你会发现能级数量有限与无限深势阱的无穷多能级不同有限深势阱只有有限个束缚态能量 E V0。波函数在阱外指数衰减在经典禁区|x| width/2波函数并不为零而是呈指数衰减。这意味着粒子有非零的概率出现在势阱之外这是纯粹的量子效应。能级间距能级间距并不像无限深势阱那样严格按 n² 增长而是逐渐变化。5. 含时薛定谔方程量子态的演化与叠加最后我们来到量子动力学的心脏——含时薛定谔方程iħ (∂/∂t) Ψ(x, t) Ĥ Ψ(x, t)这个方程决定了波函数如何随时间演化。如果系统初始时刻处于某个状态 Ψ(x, 0)那么通过求解这个方程我们就能预测未来任何时刻 t 的状态 Ψ(x, t)。对于定态时间演化很简单Ψ_n(x, t) ψ_n(x) e^{-iE_n t/ħ}。但对于一般状态它是多个定态的叠加Ψ(x, 0) Σ_n c_n ψ_n(x)其中系数 c_n 由初始条件决定。随后每个定态分量按照自己的相位因子独立演化Ψ(x, t) Σ_n c_n ψ_n(x) e^{-iE_n t/ħ}这种叠加导致了有趣的干涉现象波包可以移动、扩散甚至发生“量子反弹”。让我们通过模拟一个波包在无限深势阱中的运动来直观感受这一点。我们将创建一个由前几个能量本征态叠加而成的初始波包然后观察其时间演化。import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation from IPython.display import HTML # 参数设置 L 1.0 # 势阱宽度 N_x 200 # 空间网格点数 N_t 300 # 时间步数 t_max 4.0 # 总演化时间 x np.linspace(0, L, N_x) dx x[1] - x[0] t np.linspace(0, t_max, N_t) dt t[1] - t[0] # 无限深势阱的解析本征函数和本征值 (ħ m 1) def eigenstate(n, x, L): return np.sqrt(2/L) * np.sin(n * np.pi * x / L) def energy(n, L): return (n**2 * np.pi**2) / (2 * L**2) # 构造初始波包高斯波包但限制在阱内并投影到能量本征基上 x0 L/3 # 初始波包中心 sigma 0.05 # 初始波包宽度 # 一个在阱内的高斯型初始波函数未归一化边界已为0 psi_init np.exp(-(x - x0)**2 / (2 * sigma**2)) * np.sin(np.pi * x / L) # 乘以sin项确保边界为0 psi_init psi_init / np.sqrt(np.trapz(np.abs(psi_init)**2, x)) # 归一化 # 将初始波函数展开为能量本征态的叠加 max_n 20 # 叠加所取的最大本征态数 coeffs np.zeros(max_n, dtypecomplex) # 展开系数 c_n for n in range(1, max_n1): phi_n eigenstate(n, x, L) # 计算内积 phi_n | psi_init 作为系数 coeffs[n-1] np.trapz(np.conj(phi_n) * psi_init, x) # 验证展开的精度 psi_reconstructed np.zeros(N_x, dtypecomplex) for n in range(1, max_n1): psi_reconstructed coeffs[n-1] * eigenstate(n, x, L) overlap np.trapz(np.conj(psi_reconstructed) * psi_init, x) print(f初始波函数与重构波函数的重叠积分应接近1: {overlap:.6f}) # 计算随时间演化的波函数 psi_time np.zeros((N_t, N_x), dtypecomplex) for i, ti in enumerate(t): psi np.zeros(N_x, dtypecomplex) for n in range(1, max_n1): En energy(n, L) # 每个本征态乘以其时间演化相位因子 psi coeffs[n-1] * eigenstate(n, x, L) * np.exp(-1j * En * ti) psi_time[i, :] psi # 计算概率密度随时间的变化 prob_density_time np.abs(psi_time)**2 # 创建动画 fig, (ax1, ax2) plt.subplots(2, 1, figsize(10, 8)) # 上部波函数的实部和虚部 line_real, ax1.plot(x, psi_time[0, :].real, b-, labelRe[Ψ(x,t)], linewidth1.5) line_imag, ax1.plot(x, psi_time[0, :].imag, r--, labelIm[Ψ(x,t)], linewidth1.5) ax1.set_xlim(0, L) ax1.set_ylim(-3, 3) ax1.set_xlabel(位置 x) ax1.set_ylabel(波函数) ax1.set_title(波函数在无限深势阱中的时间演化) ax1.legend(locupper right) ax1.grid(True, alpha0.3) # 下部概率密度 line_prob, ax2.plot(x, prob_density_time[0, :], g-, linewidth2, label|Ψ(x,t)|²) ax2.fill_between(x, prob_density_time[0, :], alpha0.3, colorgreen) ax2.set_xlim(0, L) ax2.set_ylim(0, np.max(prob_density_time)*1.1) ax2.set_xlabel(位置 x) ax2.set_ylabel(概率密度) ax2.legend(locupper right) ax2.grid(True, alpha0.3) time_text ax2.text(0.02, 0.95, , transformax2.transAxes, fontsize12, verticalalignmenttop, bboxdict(boxstyleround, facecolorwheat, alpha0.8)) def animate(frame): 更新动画帧 line_real.set_ydata(psi_time[frame, :].real) line_imag.set_ydata(psi_time[frame, :].imag) line_prob.set_ydata(prob_density_time[frame, :]) ax2.collections.clear() # 清除之前的填充 ax2.fill_between(x, prob_density_time[frame, :], alpha0.3, colorgreen) time_text.set_text(f时间 t {t[frame]:.2f}) return line_real, line_imag, line_prob, time_text ani FuncAnimation(fig, animate, framesN_t, interval50, blitTrue) plt.close(fig) # 防止重复显示静态图 # 在Jupyter Notebook中显示动画 HTML(ani.to_jshtml())这段代码会生成一个动画。观察动画你会发现波包扩散与反弹初始局域的波包会随着时间扩散碰到势阱边界后反射回来与自身发生干涉形成复杂的图案。复振荡波函数的实部和虚部快速振荡反映了不同能量分量的相对相位在变化。概率密度演化概率密度 |Ψ|² 的演化相对平滑它展示了找到粒子的概率如何随时间在阱内重新分布。在某些时刻波包可能会近乎恢复原状量子复苏但通常它会变得更加弥散。通过这个模拟你直观地看到了量子态如何作为多个定态的叠加而演化以及这种叠加如何导致非平凡的动力学行为。这超越了定态的静态图像进入了量子力学真正动态和有趣的部分。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2412744.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!