Вычисление параметров для молекулярной механики

Энергия молекулы в GAFF описывается суммой:

title

Найдем с помощью минимизации энергии из квантовых расчетов (orca) параметры r_eq, q_eq, n

In [3]:
length_start = 1.52986
HCC_start = 111.200
CC_start = 0

inp_template = '''!HF RHF 6-31G
* int 0 1
C 0 0 0 0 0 0 
C 1 0 0 {0} 0 0 
H 1 2 0 1.08439 {1} 0
H 1 2 3 1.08439 {1} 120
H 1 2 3 1.08439 {1} -120
H 2 1 3 1.08439 {1} {2} 
H 2 1 6 1.08439 {1} 120
H 2 1 6 1.08439 {1} -120
*
'''
# координаты атомов 7 и 8 заданы относительно 6, 
# поэтому если его поворачивать, то 7 и 8 будут поворачиваться согласованно

def get_inp(length, HCC, CC):
    return inp_template.format(length, HCC, CC)#, CC+120, CC-120, -CC+120, -CC-120)#CC+120, CC-120, CC+180, CC+120, CC-120)
In [4]:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize 
import subprocess

def run_orca(inp):
    with open('orca.inp', 'w') as outfile: 
        outfile.write(inp)
    p = subprocess.Popen("/srv/databases/orca/orca orca.inp", 
                          shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out=p.communicate()[0]
    outlines = out.splitlines()

    # extract energy: FINAL SINGLE POINT ENERGY'
    # and return it as float
    for l in outlines:
        #print(l)
        if 'FINAL SINGLE' in str(l):
            return float(l.split()[-1])
In [4]:
run_orca(inp.format(length_start, HCC_start, CC_start))
Out[4]:
-79.081531425851

Длина связи

Вычислим энергию для значений длины C-C связи от 1.3 до 1.7 ангстрем с шагом 0.02

In [8]:
x_o = np.arange(1.3, 1.7, 0.02)
x_o
Out[8]:
array([1.3 , 1.32, 1.34, 1.36, 1.38, 1.4 , 1.42, 1.44, 1.46, 1.48, 1.5 ,
       1.52, 1.54, 1.56, 1.58, 1.6 , 1.62, 1.64, 1.66, 1.68])
In [9]:
y_o = np.array([run_orca(get_inp(i, HCC_start, CC_start)) for i in x_o])
In [27]:
y_o
Out[27]:
array([-79.03218253, -79.04174446, -79.04998776, -79.05703088,
       -79.06298212, -79.06794047, -79.07199644, -79.07523272,
       -79.0777249 , -79.07954205, -79.08074728, -79.08139822,
       -79.08154754, -79.0812433 , -79.08052939, -79.07944588,
       -79.07802931, -79.07631301, -79.07432738, -79.07210013])
In [50]:
x_o[np.argmin(y_o)]
Out[50]:
1.5400000000000003

Проведем квадратичную функцию через полученные пары длина связи - значение энергии.

In [46]:
fitfunc = lambda p, x: p[0] * (p[1] - x) ** 2 + p[2] # Target function
errfunc = lambda p, x, y: fitfunc(p, x) - y # Error function

p0 = [1,1, -79] # Initial guess for the parameters
res = optimize.least_squares(errfunc, p0[:], args=(x_o, y_o), verbose=2, method='lm')
p1 = res.x
print("Optimized params:", p1)

#Plot it
plt.plot(x_o, y_o, "ro", x_o,fitfunc(p1,x_o),"r-",c='blue',alpha=0.5)
plt.xlim(1,2)
plt.show()
`ftol` termination condition is satisfied.
Function evaluations 17, initial cost 2.0422e+00, final cost 2.3159e-05, first-order optimality 1.80e-09.
Optimized params: [  0.78811337   1.55416077 -79.19468556]

Точка минимума энергии связи, приближенной кривой, равна параметру p[1]: ее значение равно 1.554. Видно, что парабола не очень хорошо приближает полученную функцию: истинный минимум энергии достигается при длине связи 1.54 ангстрема.

Валентный угол

Вычислим энергию для значений валентного угла H-C-C от 109.2 до 113.2 с шагом 0.2 и аналогично предыдущему пункту приблизим функцию квадратичной.

In [4]:
x_o1 = np.arange(109.2, 113.2, 0.2)
x_o1
Out[4]:
array([109.2, 109.4, 109.6, 109.8, 110. , 110.2, 110.4, 110.6, 110.8,
       111. , 111.2, 111.4, 111.6, 111.8, 112. , 112.2, 112.4, 112.6,
       112.8, 113. ])
In [6]:
y_o1 = np.array([run_orca(get_inp(length_start, i, CC_start)) for i in x_o1])
In [48]:
fitfunc = lambda p, x: p[0] * (p[1] - x) ** 2 + p[2] # Target function
errfunc = lambda p, x, y: fitfunc(p, x) - y # Error function

p0 = [1,1, 0] # Initial guess for the parameters
res = optimize.least_squares(errfunc, p0[:], args=(x_o1, y_o1), verbose=2, method='lm')
p1 = res.x
print("Optimized params:", p1)

#Plot it
plt.plot(x_o1, y_o1, "ro", x_o1,fitfunc(p1,x_o1),"r-",c='blue',alpha=0.5)
plt.xlim(109,114)
plt.show()
`xtol` termination condition is satisfied.
Function evaluations 25, initial cost 1.4897e+09, final cost 5.4501e-12, first-order optimality 2.11e-09.
Optimized params: [ 3.50062748e-04  1.11774883e+02 -7.91931033e+01]

Получена точка минимума 111.7. В силовом поле GAFF2 значение этого угла считается равным 109.8 (C-sp3 : C-sp3: H связанный с алифатическим C без стягивающих электроны групп):

c3-c3-hc    46.8      109.80      SOURCE3_SOURCE5       179054    0.7972

Это значение ближе к углу тетраэдрического атома (около 109.5). Вероятно, отклонение от этого значения в наших данных вызвано сильной асимметрией молекулы (один из заместителей, C, крупнее, и от него отталкиваются атомы водорода).

Двугранный угол

Вычислим энергию для значений двугранного угла от -180 до 180 с шагом 6, и приблизим ее косинусом (параметры: амплитуда, частота, сдвиг фазы и постоянная энергия, не зависящая от угла).

In [31]:
x_o2 = np.arange(-180, 181, 6)
x_o2
Out[31]:
array([-180, -174, -168, -162, -156, -150, -144, -138, -132, -126, -120,
       -114, -108, -102,  -96,  -90,  -84,  -78,  -72,  -66,  -60,  -54,
        -48,  -42,  -36,  -30,  -24,  -18,  -12,   -6,    0,    6,   12,
         18,   24,   30,   36,   42,   48,   54,   60,   66,   72,   78,
         84,   90,   96,  102,  108,  114,  120,  126,  132,  138,  144,
        150,  156,  162,  168,  174,  180])
In [32]:
y_o2 = np.array([run_orca(get_inp(length_start, HCC_start, i)) for i in x_o2])
In [34]:
y_o2
Out[34]:
array([-79.1975724 , -79.19746107, -79.19713771, -79.19663333,
       -79.19599652, -79.19528897, -79.19457972, -79.19393845,
       -79.19342857, -79.19310075, -79.19298771, -79.19310075,
       -79.19342856, -79.19393845, -79.19457972, -79.19528897,
       -79.19599652, -79.19663333, -79.19713771, -79.19746106,
       -79.1975724 , -79.19746107, -79.19713771, -79.19663333,
       -79.19599652, -79.19528897, -79.19457972, -79.19393845,
       -79.19342857, -79.19310075, -79.19298771, -79.19310075,
       -79.19342856, -79.19393845, -79.19457972, -79.19528897,
       -79.19599652, -79.19663333, -79.19713771, -79.19746106,
       -79.1975724 , -79.19746107, -79.19713771, -79.19663333,
       -79.19599652, -79.19528897, -79.19457972, -79.19393845,
       -79.19342857, -79.19310075, -79.19298771, -79.19310075,
       -79.19342856, -79.19393845, -79.19457972, -79.19528897,
       -79.19599652, -79.19663333, -79.19713771, -79.19746106,
       -79.1975724 ])
In [52]:
fitfunc = lambda p, x: p[0] * np.cos(x * p[1] * (np.pi) / 180 - p[2]) - p[3] # Target function
errfunc = lambda p, x, y: fitfunc(p, x) - y # Error function

p0 = [1, 2.5, 0, 0] # Initial guess for the parameters
res = optimize.least_squares(errfunc, p0[:], args=(x_o2, y_o2), verbose=2, xtol=1e-15, method='lm')
p1 = res.x
print("Optimized params:", p1)

#Plot it
plt.plot(x_o2, y_o2, "ro", x_o2,fitfunc(p1,x_o2),"r-",c='blue',alpha=0.5)
plt.xlim(-180, 180)
plt.show()
`xtol` termination condition is satisfied.
Function evaluations 59, initial cost 1.9191e+05, final cost 3.0165e-10, first-order optimality 9.41e-08.
Optimized params: [2.29217146e-03 3.00015667e+00 1.22515722e-09 7.91952843e+01]

У функции 3 максимума (n=3), соответствующих трем заслоненным конформациям этана.