Pr 6. Вычисление параметров для молекулярной механики
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from scipy import optimize
ORCA_PATH = "./orca/orca" # На kodomo не грузится numpy (???) + мало памяти.
import subprocess
from IPython.display import Image, display
напишем функцию для запуска orca:
def run_orca(inp):
with open('orca.inp', 'w') as outfile:
outfile.write(inp)
with subprocess.Popen(f"{ORCA_PATH} orca.inp", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as p:
out=p.communicate()[0].decode()
for line in out.splitlines():
if 'FINAL SINGLE POINT' in line:
return float(line.strip().split()[4])
return np.nan
проверяем
input_orca = '''!HF RHF 6-31G
* int 0 1
C 0 0 0 0 0 0
C 1 0 0 1.52986 0 0
H 1 2 0 1.08439 111.200 0
H 1 2 3 1.08439 111.200 120
H 1 2 3 1.08439 111.200 -120
H 2 1 3 1.08439 111.200 180
H 2 1 5 1.08439 111.200 120
H 2 1 5 1.08439 111.200 -120
*
'''
run_orca(input_orca)
Это успех!
Сделаем шаблоны файлов
bond = '''!HF RHF 6-31G
* int 0 1
C 0 0 0 0 0 0
C 1 0 0 {:.5f} 0 0
H 1 2 0 1.08439 111.200 0
H 1 2 3 1.08439 111.200 120
H 1 2 3 1.08439 111.200 -120
H 2 1 3 1.08439 111.200 180
H 2 1 5 1.08439 111.200 120
H 2 1 5 1.08439 111.200 -120
*
'''
angle = '''!MP2 6-31G*
* int 0 1
C 0 0 0 0 0 0
C 1 0 0 1.52986 0 0
H 1 2 0 1.08439 {:.3f} 0
H 1 2 3 1.08439 111.200 120
H 1 2 3 1.08439 111.200 -120
H 2 1 3 1.08439 111.200 180
H 2 1 6 1.08439 111.200 120
H 2 1 6 1.08439 111.200 -120
*'''
tors = '''!MP2 6-311G**
* int 0 1
C 0 0 0 0 0 0
C 1 0 0 1.52986 0 0
H 1 2 0 1.08439 111.200 0
H 1 2 3 1.08439 111.200 120
H 1 2 3 1.08439 111.200 -120
H 2 1 3 1.08439 111.200 {:d}
H 2 1 6 1.08439 111.200 120
H 2 1 6 1.08439 111.200 -120
*'''
bonds = np.linspace(1.30986, 1.72986, 22)
bonds
run_orca_bonds = np.vectorize(lambda x: run_orca(bond.format(x)), otypes=[np.float])
bonds_e = run_orca_bonds(bonds)
bonds_e
Отрисуем результаты и зафитим функцию по ним.
#function is f(x)=k(b-x)^2 + a
fitfunc = lambda p, x: p[0] * pow(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
p1, success = optimize.leastsq(errfunc, p0[:], args=(bonds, bonds_e))
print("Optimized params:", p1)
#Plot it
plt.plot(bonds, bonds_e, "x", c='green', alpha=0.5)
plt.plot(bonds, fitfunc(p1, bonds), "r-", c='blue')
#plt.xlim(1,2)
plt.show()
angles = np.linspace(109.2, 113.2, 21)
angles
run_orca_angles = np.vectorize(lambda x: run_orca(angle.format(x)), otypes=[np.float])
angles_e = run_orca_angles(angles)
angles_e
def angle_potential(x, k, f0, a):
return k / 2 * (x - f0) ** 2 + a
#function is f(x)=k(b-x)^2 + a
fitfunc = lambda p, x: p[0] * pow(p[1] - x, 2) + p[2] # Target function
errfunc = lambda p, x, y: fitfunc(p, x) - y # Error function
p0 = [1, 1, -8] # Initial guess for the parameters
p1, success = optimize.leastsq(errfunc, p0[:], args=(angles, angles_e))
print("Optimized params:", p1)
#Plot it
plt.plot(angles, angles_e, "x", c='green', alpha=0.5)
plt.plot(angles, fitfunc(p1, angles), "r-", c='blue')
#plt.xlim(1,2)
plt.show()
Данных в сатье нет. Фитинг вполне хорош.
torss = np.linspace(-180, 180, 31).astype(int)
torss
torss_e = run_orca_torss(torss)
torss_e
fitfunc = lambda p, x: p[0] * (1 + np.cos(p[1] * np.pi * np.radians(x) - p[2])) + p[3] # Target function
errfunc = lambda p, x, y: fitfunc(p, x) - y # Error function
p0 = [0, 1, -1, -1] # Initial guess for the parameters
p1, success = optimize.leastsq(errfunc, p0[:], args=(torss, torss_e))
print("Optimized params:", p1)
#Plot it
plt.plot(torss, torss_e, "x", c='darkred', alpha=0.5)
good_torss = np.linspace(-180, 180, 361)
plt.plot(good_torss, fitfunc(p1, good_torss), "r-", c='red')
#plt.xlim(1,2)
plt.show()
Получается, что значения минимумов соответствуют -180, -60, 60, 180 - т.е. анти (заторможенным)-конформациям этана. Максимумы - заслонённая, наименее выгодная конформация.