跳到正文
EN

4.4

数值求解薛定谔方程

把连续的 x 轴换成一排格点,薛定谔方程就变成三对角矩阵的本征值问题——十行代码解出任意势的束缚态。

建议先掌握

学完本节你应该能

  • 用泰勒展开推导二阶导数的三点差分公式,并说出误差的阶
  • 把哈密顿量写成三对角矩阵,说明每个矩阵元的来历
  • 用现成的本征值例程解谐振子并与精确解对比
  • 做网格收敛性检查,识别「格距」与「盒子大小」两个独立的误差来源

上一节末尾把话挑明了:真实的势是光滑的,分段常数的台阶逼近不是长久之计。而回望第 2 章,我们能精确解出的势屈指可数——无限阱、有限阱、谐振子、方垒,每个都靠一件专属的巧劲(驻波条件、超越方程、升降算符)。换一个稍微不规则的势,比如两个不等深的阱、或者加了电场的斜底阱,所有巧劲同时失灵。

第 3 章早就把出路写好了,只是当时听着像哲学:波函数是矢量的分量,算符是矩阵3.1 节3.4 节)。那里的「矩阵」是无穷维的,写不进计算机。这一节做一件不客气的事:把无穷维砍成有限维——xx 轴换成一排格点,ψ(x)\psi(x) 换成一列数,H^\hat H 就真的变成一个你能打印出来看的矩阵。能级?矩阵的本征值。波函数?本征矢量。剩下的交给线性代数库。

第一步:把函数变成数组

选一个足够大的区间 [L/2,L/2][-L/2,\,L/2](大到束缚态波函数在端点处早已衰减殆尽),撒 NN 个等距格点:

xn=L2+nh,h=LN+1,n=1,2,,N(4.4.1)x_n=-\frac{L}{2}+nh,\qquad h=\frac{L}{N+1},\qquad n=1,2,\dots,N\tag{4.4.1}

波函数从连续曲线降格为一列采样值 ψnψ(xn)\psi_n\equiv\psi(x_n)。势能同样变成一列数 VnV(xn)V_n\equiv V(x_n)——这就是为什么任何势都不再特殊:势再古怪,也不过是数组里换一列数字。

定态薛定谔方程里动能项含 ψ\psi''。麻烦来了:只剩一排离散的点,导数怎么办?

第二步:用邻居算二阶导

第三步:哈密顿量现出矩阵原形

把差分公式塞进定态方程 22mψ+Vψ=Eψ-\frac{\hbar^2}{2m}\psi''+V\psi=E\psi,第 nn 个格点上:

22mh2ψn+1+(2mh2+Vn)ψn22mh2ψn1=Eψn(4.4.6)-\frac{\hbar^2}{2mh^2}\psi_{n+1}+\left(\frac{\hbar^2}{mh^2}+V_n\right)\psi_n-\frac{\hbar^2}{2mh^2}\psi_{n-1}=E\,\psi_n\tag{4.4.6}

左边是对列向量 (ψ1,,ψN)(\psi_1,\dots,\psi_N) 的线性操作——它就是矩阵乘法 Hψ=EψH\boldsymbol\psi=E\boldsymbol\psi,其中

H=(2mh2+V122mh222mh22mh2+V222mh2)(4.4.7)H=\begin{pmatrix} \frac{\hbar^2}{mh^2}+V_1&-\frac{\hbar^2}{2mh^2}&&\\[2pt] -\frac{\hbar^2}{2mh^2}&\frac{\hbar^2}{mh^2}+V_2&-\frac{\hbar^2}{2mh^2}&\\[2pt] &\ddots&\ddots&\ddots \end{pmatrix}\tag{4.4.7}

一个三对角矩阵:对角线装着「动能基底 + 当地势能」,紧邻对角线装着格点间的耦合,其余全为零——因为三点公式只跟左右邻居说话。

两处细节交代清楚:

  • 边界条件n=1n=1 的方程里出现 ψ0\psi_0n=Nn=N 里出现 ψN+1\psi_{N+1},即区间端点的值。我们直接令 ψ0=ψN+1=0\psi_0=\psi_{N+1}=0——相当于把系统关进一个宽 LL 的无限深盒子。只要 LL 够大、束缚态在墙边早就指数衰减到零,这两堵假墙就无关痛痒(多大才「够大」,见下面的警告)。
  • 矩阵是实对称的——第 3 章厄米算符的离散化身。3.5 节的定理原样兑现:本征值全是实数,本征矢量相互正交。理论保证与数值验证在下面的代码里当场对账。

第四步:跑起来

用谐振子练手(取无量纲单位 =m=ω=1\hbar=m=\omega=1,能级应为 n+12n+\frac12)。三对角矩阵有专用的高效例程 eigh_tridiagonal,不必存储 N2N^2 个零:

import numpy as np
from scipy.linalg import eigh_tridiagonal

def solve(V, L, N):
    """解 -psi''/2 + V(x) psi = E psi,区间 [-L/2, L/2],N 个内部格点。"""
    x = np.linspace(-L/2, L/2, N + 2)[1:-1]     # 去掉两端的边界点
    h = x[1] - x[0]
    diag = 1.0 / h**2 + V(x)                    # 对角元:动能基底 + 势能
    off  = -0.5 / h**2 * np.ones(N - 1)         # 次对角元:邻居耦合
    E, psi = eigh_tridiagonal(diag, off, select='i', select_range=(0, 5))
    return x, E, psi / np.sqrt(h)               # 除以 √h:让 Σ|ψ|²h = 1

x, E, psi = solve(lambda x: 0.5 * x**2, L=16, N=1000)
print(E)        # [0.499992  1.499960  2.499896  3.499800  4.499673  5.499513]

六个能级与精确值 0.5,1.5,,5.50.5,1.5,\dots,5.5 的偏差都在小数点后第四、五位。顺手验证第 3 章的承诺:psi[:,0] @ psi[:,1] * h 输出 0.00.0——不同本征态严格正交,机器精度以内。

第五步:怀疑你的结果

数值计算最重要的纪律:结果必须证明自己收敛了。上面的数字有两个独立的误差来源,各配一个检查。

**误差一:格距 hh 有限。**加密网格,看结果怎么变:

NN50100200400800
E0E_0 的误差3.1×1033.1\times10^{-3}7.9×1047.9\times10^{-4}2.0×1042.0\times10^{-4}5.0×1055.0\times10^{-5}1.2×1051.2\times10^{-5}

NN 每翻倍(hh 减半),误差几乎精确地缩到 1/41/4——推导预言的 O(h2)O(h^2) 指纹清清楚楚。这条纪律的实操版本:NN 翻倍重算一遍,头几位数字不动了,才可以引用它们。

**误差二:盒子 LL 有限。**假墙离得太近会把波函数「夹疼」。检查方式相同:把 LL 加大重算,结果不变才算数。

接下来

方法齐了,代码也有了,但每次换势都要重新摆弄网格、单位、检查项,像每顿饭都从生火开始。下一节把这些打包成一个通用求解器:喂给它任意一条势能曲线,它吐出能级和波函数,并自带质量检查清单。然后用它做一件解析方法办不到的事——解双势阱,看着一对能级挤到只差百分之一,从中读出隧穿、氨分子微波激射器、以及化学键的雏形。

全站第 34 / 106 节 · 用 翻页