harmonic_fit.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #! /usr/bin/env python
  2. import sys
  3. import csv
  4. import numpy as np
  5. import matplotlib.pyplot as plt
  6. #from mpl_toolkits.mplot3d import axes3d
  7. from scipy.interpolate import interp1d, CubicSpline
  8. import math
  9. plt.rcParams['font.family'] = 'sans-serif'
  10. plt.rcParams['font.family'] = 'Times New Roman'
  11. plt.rcParams['axes.edgecolor']='#333F4B'
  12. plt.rcParams['axes.linewidth']=0.8
  13. plt.rcParams['xtick.color']='#333F4B'
  14. plt.rcParams['ytick.color']='#333F4B'
  15. plt.rcParams["axes.prop_cycle"]
  16. # Read CSV
  17. csvFileName = sys.argv[1]
  18. scan_var = csvFileName.split('.')[0]
  19. pltFileName = scan_var + '.png'
  20. csvData = []
  21. with open(csvFileName, 'r') as csvFile:
  22. csvReader = csv.reader(csvFile, delimiter = ' ')
  23. for csvRow in csvReader:
  24. csvData.append(csvRow)
  25. # Get X, Y and store in np array
  26. csvData = np.array(csvData)
  27. csvData = csvData.astype(np.float)
  28. X, Y = csvData[:,0], csvData[:,1]
  29. au_to_kJpmol = 2625.5
  30. Y = np.array([y/2625.5 for y in Y])
  31. # numerical second derivative of interpolant at equilibrium
  32. def comp_k_numeric(X,Y):
  33. """
  34. Compute numerical double derivative at equilibrium given X and V[X]
  35. """
  36. #x_new = np.linspace(X.min(), X.max(), 65)
  37. f = interp1d(X, Y, kind='cubic', fill_value="extrapolate")
  38. xe = 0
  39. h = 0.1*10**(-8)
  40. k_numeric = (1/(2.0*h)) * ((f(xe + 2.0*h) - f(xe))/(2.0*h) - (f(xe) - f(xe - 2.0*h))/(2.0*h))
  41. return (k_numeric)
  42. def comp_k_numeric_prec(X,Y, n):
  43. """
  44. Compute numerical double derivative at equilibrium given X and V[X]
  45. """
  46. x_new = np.linspace(X.min(), X.max(), 65)
  47. f = interp1d(X, Y, kind='cubic')
  48. xe = 0
  49. h = 0.1*10**(-n)
  50. k_numeric = (1/(2.0*h)) * ((f(xe + 2.0*h) - f(xe))/(2.0*h) - (f(xe) - f(xe - 2.0*h))/(2.0*h))
  51. return (k_numeric)
  52. # analytic derivative of interpolant at equilibrium
  53. def comp_k_analytic(X,Y):
  54. """
  55. Compute the analytic force constant given X, and V(X)
  56. """
  57. N = X.size
  58. mid = int((N + 1)/2)
  59. f2 = CubicSpline(X,Y)
  60. k_analytic = f2(X, 2)[mid]
  61. return k_analytic, f2
  62. # convert to cm-1
  63. def convert_k_to_cminv(k):
  64. """
  65. Import force constant in Hartree/Ang^2
  66. convert it to cm-1
  67. """
  68. mu = 918.553523379183232925595706294
  69. #ang_to_bohr = 1/(0.529)
  70. nu = 1/(2*np.pi)*math.sqrt(k/mu)*(1/(137*10**-8))
  71. return (nu)
  72. def convert_k_to_cminv_rotor(k):
  73. """
  74. Convert force constant in Hartree/Radian^2 to cm-1
  75. this is for h2
  76. """
  77. I = 1948.37443393238771437461228584
  78. nu = 1/(2*np.pi)*math.sqrt(k/I)*(1/(137*5.29*10**-9))
  79. return nu
  80. k_numeric = comp_k_numeric(X, Y)
  81. nu_numeric = convert_k_to_cminv(k_numeric)
  82. zpve_numeric = nu_numeric/2
  83. k_analytic, f2 = comp_k_analytic(X, Y)
  84. nu_analytic = convert_k_to_cminv(k_analytic)
  85. zpve_analytic = nu_analytic/2
  86. print (scan_var, "Analytic ", k_analytic, nu_analytic, zpve_analytic)
  87. print (scan_var, "Numeric ", k_numeric, nu_numeric, zpve_numeric)
  88. plt.plot(X, Y, 'bo')
  89. plt.plot(X, f2(X), 'b-')
  90. plt.plot(X, f2(X, 1), 'rx--')
  91. plt.plot(X, f2(X, 2), 'co--')
  92. plt.legend(['Points', 'Cubic Spline', r'dV/dq', r"d$^2$V/dq$^2$"], fontsize = 12)
  93. plt.xlabel(scan_var, fontsize = 16)
  94. plt.ylabel("E(a.u) and higher derivs", fontsize = 16)
  95. plt.savefig(pltFileName)