Ниже задана функция расчёта орбиталей на основе подхода Рутана Холла
S - матрица перекрывания; p. 412 eq. (A.9)
F - матрица Фока;
X - диагонализированная матрица S;
H - гамильтониан; p. 141 eq. (3.153)
C - матрица коэффициентов.
from hfscf import *
import numpy as np
from IPython.display import display,Image
def SCF (r = 1.4632, Z=[1,1], b1 = GTO["H"], b2 = GTO["H"], b = 3, vbs=False):
R = [0, r]
#r -- электронные степени свободы, R -- ядерные степени свободы
if vbs: print("*) Generating overlap matrix S") #Генерируем матрицу перекрывания S
s_scf = S(R, b1, b2, b)
if vbs: print("\n*) Generating Hamiltonian H.") #Генерируем гамильтониан H
h_scf = H(R, Z, b1, b2, b)
# Диагонализировать матрицу S и найти матрицу X
if vbs: print("\n*) Diagonalizing matrix S and finding diagonal matrix X.")#Диагонализируем матрицу S и ищем матрицу X
X = diagon(m=s_scf)
Xa = X.getH()
# Cоздать матрицу электронной плотности P
if vbs: print("\n*) Creating density matrix P.")#Cоздаем матрицу электронной плотности P
p_scf = np.matrix([[0,0],[0,0]], dtype=np.float64) # Referencia (7) p. 148
# Запуск итеративных процессов
if vbs: print("\n*) Starting with the SCF.") #Начинаем считать SCF.
for iteracion in range(50):
# Строим матрицу Фока F
# F = H + G
if vbs: print("\n**) Generating the Fock matrix: calculating \
integral of two electrons.") #Генерируем матрицу Фока: рассчитываем интегралы двух электронов.
g_scf = G(r, p_scf, b1, b2, b)
f_scf = h_scf + g_scf # Referencia (7) p. 141 eq. (3.154)
# Строим матрицу F'
# F' = X_adj * F * X
if vbs: print("**) Changing the base of F.") # Меняем базис F
f_tra = Xa * f_scf * X
# диагонализировать матрицу F и построить C'
if vbs: print("**) Diagonalizing F' and generating C'.") #диагонализируем F' и генерируем C'
c_tra = diagon2(m=f_tra)
# Строим матрицу C
# C = X * C'
if vbs: print("**) Constructing coefficient matrix C.") #Строим матрицу коэффициентов C
c_scf = X * c_tra
# Строим матрицу P на основе матрицы C
if vbs: print("**) Recalculating density matrix P.") #Перерасчет матрицы плотности P
p_temp = P(C=c_scf)
# Calculating orbital, electronic and total energy.
orbital_energy = hfscf.ener_orbs(X, f_scf)
electronic_energy = hfscf.ener_elec(p_temp, h_scf, f_scf)
total_energy = hfscf.ener_tot(r, Z, 0)
# Plot orbitals.
#hfscf.orbital(c_tra, r, b1, b2, b)
#hfscf.orbital2D(c_scf, X, f_scf, r, b1, b2, b, 0.02)
#Очень хотелось каждый раз показывать картиночки с орбиталями, но они выводились в отдельное окно и скрипт дальше не работал
print("\n Завершена " + str(iteracion + 1) + ". итерация.\n")
# Проверяем сходимость (насколько поменялась Р с предыдущей итерации)
if np.linalg.norm(p_temp - p_scf) < 1E-4: # Referencia (7) p. 148
print("\n\n-->Самосогласованное поле сходится")
return {"S":s_scf,"H":h_scf,"X": X,"F":f_scf,"C":c_scf,"P":p_temp,"OE":orbital_energy,"EE":electronic_energy, "TE":total_energy}
else:
p_scf = p_temp
print("\n\n-->Самосогласованное поле НЕ сходится!\n Перепроверить предположения.")
return {"S":s_scf,"H":h_scf,"X": X,"F":f_scf,"C":c_scf,"P":p_temp,"OE":orbital_energy,"EE":electronic_energy, "TE":total_energy}
result = SCF()
Считаем электронную и полную энергию молекулы
print("Электронная энергия молекулы " + str(result.get("EE")))
print("Общая энергия молекулы " + str(result.get("TE")))
#1D плот орбиталей, хз как нормально вставить картинку в notebook -- она выводится в отдельное окно :|
#orbital(result["C"])
Image("figure_1.png")
#2D плот орбиталей
#orbital2D(result["C"],result["X"],result["F"])
Image("figure_2Dorb.png")