Цель занятия: опираясь на уравнение построить электронную плотность в одно-электронном атоме и сравнить с известными программами.
Импортируем необходимые модули, функцию Андрея Демкива npy2cube прогоним через 2to3. Работает!
python D:\pymol\anaconda\Tools\scripts\2to3.py --output-dir=C:\Users\днс\npy3cube -W -n C:\Users\днс\npy2cube
from pymol import cmd, stored
import numpy
import scipy.special
import scipy.misc
from math import factorial
import matplotlib.pyplot as plt
from IPython.display import display,Image
from npy3cube import npy2cube
Задаем волновую функцию:
def w(n,l,m,d): #n, l и m - квантовые числа, d - шаг
x,y,z = numpy.mgrid[-d:d:30j,-d:d:30j,-d:d:30j] #координаты в декартовой системе (30х30х30)
#переход от декартовых координат в сферические
r = lambda x,y,z: numpy.sqrt(x**2+y**2+z**2) #радиус-вектор
theta = lambda x,y,z: numpy.arccos(z/r(x,y,z)) #зенитный угол
phi = lambda x,y,z: numpy.arctan(y/x) #азимутальный угол
#a0 - Боровский радиус, радиус ближайшей к ядру орбиты электрона атома водорода в модели атома, предложенной Нильсом Бором
a0 = 1
#R - Радиальная часть волновой функции
R = lambda r,n,l: (2*r/n/a0)**l * numpy.exp(-r/n/a0) * scipy.special.genlaguerre(n-l-1,2*l+1)(2*r/n/a0)
#Волновая функция - произведение coef*R*угловая функция (сферическая гармоника)
WF = lambda r,theta,phi,n,l,m: R(r,n,l) * scipy.special.sph_harm(m,l,phi,theta)
#absWF = lambda r,theta,phi,n,l,m: numpy.absolute(WF(r,theta,phi,n,l,m))**2
#плотность вероятности нахождения электрона в данной точке в данный момент времени
return WF(r(x,y,z),theta(x,y,z),phi(x,y,z),n,l,m)
Cube-файлы со значениями волновых функций для первыx трёх уровней:
step = 1
#перебор квантовых чисел 0,1,2,3
for n in range(0,4):
d = 10*n
for l in range(0,n):
for m in range(0,l+1,1):
grid = w(n,l,m,d)
name ='%s-%s-%s' % (n,l,m)
npy2cube(grid,(-d,-d,-d),(step,step,step), name+'.cube')
C:\Users\днс\npy3cube.py:39: ComplexWarning: Casting complex values to real discards the imaginary part cube_file.write("%f " %(float(grid[x, y, z]))) C:\Users\днс\npy3cube.py:42: ComplexWarning: Casting complex values to real discards the imaginary part cube_file.write("%f\n" %(float(grid[x, y, z])))
Визуализируем орбитали в pymol:
orbit = open ('orbit.pml', 'w')
orbit.write('cmd.volume_ramp_new(\'ramp007\', [\
-0.015, 1.00, 0.00, 0.00, 0.00, \
-0.01, 1.00, 1.00, 0.00, 0.20, \
-0.005, 0.00, 0.00, 1.00, 0.00, \
0.005, 0.00, 0.00, 1.00, 0.00, \
0.01, 0.00, 1.00, 1.00, 0.20, \
0.015, 0.00, 0.00, 1.00, 0.00, \
])\n')
#схема окрашивания
for n in range(0,4):
for l in range(0,n):
for m in range(0,l+1,1):
name='%s-%s-%s' % (n,l,m)
print(name)
lname = name+'.cube'
volname = name+'_vol'
orbit.write('load %s, %s\n' % (lname, name))
orbit.write('volume %s, %s\n' % (volname, name))
orbit.write('volume_color %s, ramp007\n' % (volname))
orbit.close()
#записываем в файл инструкции по открыванию cube'ов и окрашиванию
1-0-0 2-0-0 2-1-0 2-1-1 3-0-0 3-1-0 3-1-1 3-2-0 3-2-1 3-2-2
import __main__
__main__.pymol_argv = [ 'pymol', '-x' ]
import pymol
pymol.finish_launching()
from pymol import cmd, stored
cmd.load("orbit.pml")
PyMOL>cmd.volume_ramp_new('ramp007', [ -0.015, 1.00, 0.00, 0.00, 0.00, -0.01, 1.00, 1.00, 0.00, 0.20, -0.005, 0.00, 0.00, 1.00, 0.00, 0.005, 0.00, 0.00, 1.00, 0.00, 0.01, 0.00, 1.00, 1.00, 0.20, 0.015, 0.00, 0.00, 1.00, 0.00, ]) PyMOL>load 1-0-0.cube, 1-0-0 PyMOL>volume 1-0-0_vol, 1-0-0 PyMOL>volume_color 1-0-0_vol, ramp007 PyMOL>load 2-0-0.cube, 2-0-0 PyMOL>volume 2-0-0_vol, 2-0-0 PyMOL>volume_color 2-0-0_vol, ramp007 PyMOL>load 2-1-0.cube, 2-1-0 PyMOL>volume 2-1-0_vol, 2-1-0 PyMOL>volume_color 2-1-0_vol, ramp007 PyMOL>load 2-1-1.cube, 2-1-1 PyMOL>volume 2-1-1_vol, 2-1-1 PyMOL>volume_color 2-1-1_vol, ramp007 PyMOL>load 3-0-0.cube, 3-0-0 PyMOL>volume 3-0-0_vol, 3-0-0 PyMOL>volume_color 3-0-0_vol, ramp007 PyMOL>load 3-1-0.cube, 3-1-0 PyMOL>volume 3-1-0_vol, 3-1-0 PyMOL>volume_color 3-1-0_vol, ramp007 PyMOL>load 3-1-1.cube, 3-1-1 PyMOL>volume 3-1-1_vol, 3-1-1 PyMOL>volume_color 3-1-1_vol, ramp007 PyMOL>load 3-2-0.cube, 3-2-0 PyMOL>volume 3-2-0_vol, 3-2-0 PyMOL>volume_color 3-2-0_vol, ramp007 PyMOL>load 3-2-1.cube, 3-2-1 PyMOL>volume 3-2-1_vol, 3-2-1 PyMOL>volume_color 3-2-1_vol, ramp007 PyMOL>load 3-2-2.cube, 3-2-2 PyMOL>volume 3-2-2_vol, 3-2-2 PyMOL>volume_color 3-2-2_vol, ramp007
#делаю скриншоты
orbitales = {0: 's', 1: 'p', 2: 'd'}
_, axarr = plt.subplots(5, 2, figsize=(10, 21.33))
row, col = 0, 0
for n in range(0,4):
for l in range(0,n):
for m in range(0,l+1,1):
name='%s-%s-%s' % (n,l,m)
f = plt.imread(name + '.png')
axarr[row, col].axis('off')
axarr[row, col].imshow(f)
axarr[row, col].set_title(str(n)+orbitales[l], {'fontsize': 35}, pad=10)
col += 1
if col == 2:
row += 1
col = 0
plt.tight_layout()
Вроде похоже, сравним с расчётами, сделанными с помощью psi4.
import psi4
g = '''
H
'''
m = psi4.geometry(g)
psi4.set_options({"maxiter": 200, "fail_on_maxiter" : True, 'reference':'uhf'})
#https://en.wikipedia.org/wiki/Unrestricted_Hartree%E2%80%93Fock
energy, wave=psi4.energy('scf/cc-pvtz', return_wfn = True, molecule = m )
psi4.cubeprop(wave)
energy
-0.49980981130184243
import __main__
__main__.pymol_argv = [ 'pymol', '-x' ]
import pymol
pymol.finish_launching()
from pymol import cmd, stored
cmd.load("volume.pml")
У меня возникли проблемы с volume, то от орбиталей остаются куски, то окрашивается куб.. Выглядит эпично:
from IPython.display import display, Image
display(Image('epic.jpg'))
В итоге, всё выданное программой в порядке выдачи (названия у файлов вышли весьма замысловатые):
display(Image('all_together.jpg'))
Весьма похоже!