如何使用射击法从薛定谔方程中评估更准确的能量特征值?

计算科学 Python 边界条件 特征值 量子力学
2021-11-29 20:39:59

我正在尝试使用“射击方法”来求解薛定谔方程,以获得一维中合理的任意势。但是,与分析结果相比,在没有硬边界的势能的情况下如此评估的特征值并不准确。

我认为可以通过使空间网格更精细来解决问题,但是更改空间网格实际上对特征值没有任何影响。我并没有使能量网格更精细,因为精细到正确特征值的工作是通过 SciPy 的二分法来解决的,而波函数是通过odeint从 SciPy 求解相关的 IVP 来评估的,这些函数足够准确。

最后,改变第二个边界使波函数在经典禁区的更深部分消失也没有带来特征值的实际改进(仅在小数点后第 9 位或第 10 位发现变化,但使低能态的波函数在端点处发散使事情变得更糟)。

我找不到要修改的内容以获得更准确的特征值。边界条件还是步长?我的实现是否出错了,还是由于舍入错误或其他“Python 事物”?

示例:莫尔斯电位

import numpy as np
from scipy.integrate import odeint
from scipy.optimize import bisect


def V(x, xe=1.0, lam=6.0):
    """Morse potential definition"""
    return lam**2*(np.exp(-2*(x- xe)) - 2*np.exp(-(x - xe))) 


def func(y, x):
    """
    Utility function for returning RHS of the differential equation.
    """
    psi, phi = y # psi=eigenfunction, phi=spatial derivative of psi
    return np.array([phi, -(E - V(x))*psi])


def ivp(f, initial1, initial2, X):
    """Solve an ivp with odeint"""
    y0 = np.array([initial1, initial2])
    return odeint(f, y0, X)[:, 0]


def psiboundval(E1): 
    """
    Find out value of eigenfunction at bound2 for energy E1
    by solving ivp.
    """
    global E;
    E = E1
    S = ivp(func, bval1, E1, X)
    return S[(len(S)) - 1] - bval2


def shoot(Erange): 
    """
    Find out accurate eigenvalues from approximate ones in
    Erange by bisect.
    """
    global E
    Y = np.array([psiboundval(E) for E in Erange])
    eigval = np.array([bisect(psiboundval, Erange[i], Erange[i + 1])
                       for i in np.where(np.diff(np.signbit(Y)))[0]])
    return eigval


#%% Solution
xe, lam = 1.0, 6.0 # parameters for potential
# Bval, Bval2 = wavefunction values at x = bound1, bound2
bound1, bound2, bval1, bval2 = 0, xe + 15, 0, 0 
X = np.linspace(bound1, bound2, 1000) # region of integration
Erange = np.geomspace(-lam**2, -0.0001, 100) # region of Energy level searching
print("Numerical results:", np.round(shoot(Erange), 4))
print("Analytical results:",
      [-(lam - n - 0.5)**2 for n in range(0, int(np.floor(lam - 0.5) + 1))])

输出

Numerical results: [-30.2483 -20.2432 -12.2361  -6.2318  -2.2343  -0.2438]
Analytical results: [-30.25, -20.25, -12.25, -6.25, -2.25, -0.25]

对于更高的能量状态,精度会降低。对于所有状态,精度至少要达到小数点后 4 位(如果不是更多的话)是可取的。

1个回答

您的问题是集成的下限。它应该是而不是 0,因为是势能的平衡点,而不是最小距离。xexe

更正后,您会得到以下信息

#%% Solution
xe, lam = 1.0, 6.0 # parameters for potential
xmax = 10
# Bval, Bval2 = wavefunction values at x = bound1, bound2
bound1, bound2, bval1, bval2 = -xe, xmax, 0, 0 
X = np.linspace(bound1, bound2, xmax) # region of integration
Erange = np.geomspace(-lam**2, -0.01, 100) # region of Energy level searching
print("Numerical results:", np.round(shoot(Erange)[:6], 6))
print("Analytical results:",
      [-(lam - n - 0.5)**2 for n in range(6)])

结果

Numerical results: [-30.25     -20.25     -12.25      -6.25      -2.25      -0.240849]
Analytical results: [-30.25, -20.25, -12.25, -6.25, -2.25, -0.25]

我还尝试了简单谐振子的方法并返回了预期的特征值。

如前所述,我不认为这种方法是完成任务的最佳方法。您应该尝试域离散化方法,例如有限元法或有限差分法或变分法。后者通常用于具有高斯基的量子化学代码中。

我看到这种方法的两个主要缺点是你应该有一个(足够精细离散的)特征值范围,这可能事先不知道。另外,我看不到如何将该方法推广到更高维的问题。

我认为它可能有用的一个场景是在进行扰动分析时。在这种情况下,一组(近似的)特征值是可用的,特征函数也是如此。