Загрузка данных
import numpy as np
import matplotlib.pyplot as plt
# задание отрезка [A, B] (края ямы)
L = 2.0
A = -L
B = +L
# кол-во узлов сетки на [A, B]
n = 501
# шаг сетки
h = (B - A) / (n - 1)
# константа для использования в методе Нумерова
c = h**2 / 12.0
# минимальное значение потенциальной функции
U0 = -1.0
# максимальное значение потенциальной функции на графике
W = 4.0
# потенциальная функция
def U(x):
return float(U0 if abs(x) < L else W)
# функция формулы 13
def q(e, x):
return 2.0 * (e - U(x))
# численное вычисление производной, формула 19
def deriv(Y, h, m):
return (Y[m-2] - Y[m+2] + 8.0 * (Y[m+1] - Y[m-1])) / (12.0 * h)
# вычисление разности производных в узле сшивки, формула 18
def f_fun(e, r, n):
F = np.array([c * q(e, X[i]) for i in np.arange(n)])
Psi[0] = 0.0
Fi[n-1] = 0.0
Psi[1] = d1
Fi[n-2] = d2
# решение задачи Коши "вперед" методом Нумерова
for i in np.arange(1, n-1, 1):
p1 = 2.0 * (1.0 - 5.0 * F[i]) * Psi[i]
p2 = (1.0 + F[i-1]) * Psi[i-1]
Psi[i+1] = (p1 - p2) / (1.0 + F[i+1])
# решение задачи Коши "назад" методом Нумерова
for i in np.arange(n-2, 0, -1):
f1 = 2.0 * (1.0 - 5.0 * F[i]) * Fi[i]
f2 = (1.0 + F[i+1]) * Fi[i+1]
Fi[i-1] = (f1 - f2) / (1.0 + F[i-1])
# поиск максимального по величине элемента Psi
p1 = np.abs(Psi).max()
p2 = np.abs(Psi).min()
big = p1 if p1 > p2 else p2
# масштабирование Psi
Psi[:] = Psi[:] / big
# математическая нормировка Fi
# для достижения равенства F[r] = Psi[r]
coef = Psi[r] / Fi[r]
Fi[:] = coef * Fi[:]
# вычисление f(E) для узла сшивки, формула 18
f = deriv(Psi, h, r) - deriv(Fi, h, r)
return f
# ==========================================================
# УТОЧНЕНИЕ СОБСТВЕННОГО ЗНАЧЕНИЯ МЕТОДОМ ДЕЛЕНИЯ
# ОТРЕЗКА ПОПОЛАМ
# ==========================================================
def bisection(e1, e2, r, n, eps=1.e-10, max_iter=100):
f1 = f_fun(e1, r, n)
f2 = f_fun(e2, r, n)
print("Начальный интервал:")
print("E1 =", e1, "f(E1) =", f1)
print("E2 =", e2, "f(E2) =", f2)
# Проверка условия существования корня
if f1 * f2 > 0:
raise ValueError(
"На концах заданного интервала f(E) имеет одинаковый знак. "
"Задайте другой интервал."
)
for k in range(max_iter):
# середина отрезка
e_mid = (e1 + e2) / 2.0
# значение функции в середине
f_mid = f_fun(e_mid, r, n)
print(
"Итерация:", k + 1,
" E =", e_mid,
" f(E) =", f_mid
)
# условие окончания
if abs(f_mid) < eps or abs(e2 - e1) < eps:
return e_mid
# выбираем половину отрезка,
# на которой сохраняется смена знака
if f1 * f_mid < 0:
e2 = e_mid
f2 = f_mid
else:
e1 = e_mid
f1 = f_mid
return (e1 + e2) / 2.0
# ==========================================================
# ОСНОВНАЯ ЧАСТЬ ПРОГРАММЫ
# ==========================================================
Psi = np.zeros(n)
Fi = np.zeros(n)
F = np.zeros(n)
Psi2 = np.zeros(n)
X = np.linspace(A, B, n)
# номер узла сшивки
r = (n - 1) // 2 + 15
d1 = 1.e-9
d2 = d1
# ----------------------------------------------------------
# Начальный отрезок поиска собственного значения
# ----------------------------------------------------------
e1 = -0.9
e2 = -0.5
# точность поиска
eps = 1.e-10
# уточнение собственного значения методом бисекции
e = bisection(e1, e2, r, n, eps)
# значение функции в найденной точке
f = f_fun(e, r, n)
print()
print("========================================")
print("Собственное значение энергии:")
print("e =", e)
print("f(E) =", f)
print("========================================")
# ==========================================================
# ПОСТРОЕНИЕ ГРАФИКА
# ==========================================================
Upot = np.array([U(X[i]) for i in np.arange(n)])
# построение графика
plt.axis([A, B, U0, W])
Zero = np.zeros(n, dtype=float)
plt.plot(X, Zero, 'k-', linewidth=1.0)
plt.plot(
X,
Upot,
'g-',
linewidth=6.0,
label="U(x)"
)
plt.plot(
X[1:n-1],
Psi[1:n-1],
'r-',
linewidth=2.0,
label="Psi(x)"
)
plt.plot(
X[1:n-1],
Fi[1:n-1],
'b-',
linewidth=2.0,
label="Phi(x)"
)
plt.xlabel("X", fontsize=20, color="k")
plt.ylabel("Psi(x), Phi(x), U(x)", fontsize=20, color="k")
plt.grid(True)
plt.legend(
fontsize=16,
shadow=True,
fancybox=True
)
# точка сшивки
plt.plot(
[X[r]],
[Psi[r]],
color='red',
marker='o',
markersize=10
)
string1 = "E = " + str(e)
string2 = "f(E) = " + str(f)
plt.text(
-1.5,
2.1,
string1,
fontsize=16,
color='black'
)
plt.text(
-1.5,
1.7,
string2,
fontsize=16,
color="black"
)
# сохранение графика в файл
# plt.savefig('Schrodinger_bisection.pdf', dpi=300)
# вывод графика в окно
plt.show()