Advertisement
Guest User

Untitled

a guest
Jun 18th, 2019
254
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.23 KB | None | 0 0
  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from mpl_toolkits import mplot3d
  4. import math
  5. import time as time
  6.  
  7. # special points on the surface
  8.  
  9. # minima
  10. min3pos = -0.558224, 1.44173
  11. min1pos = 0.623499, 0.0280378
  12. min2pos = -0.0500108, 0.466694
  13. mainminpos = min1pos
  14.  
  15. # saddle points
  16. saddle_pos = np.array([0.212487,0.292988])
  17. saddle_pos2 = np.array([-0.822002, 0.624313])
  18. mainsaddlepos = saddle_pos
  19.  
  20.  
  21. #%%Initiatlization
  22.  
  23. time_begin = time.clock()
  24.  
  25. coefficients = np.array([[-200, -1, 0, -10, 1, 0],
  26. [-100, -1, 0, -10, 0, 0.5],
  27. [-170, -6.5, 11, -6.5, -0.5, 1.5],
  28. [15, 0.7, 0.6, 0.7, -1, 1]])
  29.  
  30. pointnum = 100 #how fine shoutld the grid of the contour plot be
  31. V = np.zeros((pointnum,pointnum))
  32.  
  33. x_min2 = -1.5 #max and min x and y values for plot
  34. x_max2 = 0.2
  35. y_min2 = 0.2
  36. y_max2 = 1.8
  37.  
  38. x_min = -0.5 #max and min x and y values for plot
  39. x_max = 1.2
  40. y_min = -0.3
  41. y_max = 0.8
  42.  
  43. buffer = 0.005 #time particle can penetrate into the other valley - to make sure it stays there
  44.  
  45. x = np.linspace(x_min,x_max,pointnum)
  46. y = np.linspace(y_min,y_max,pointnum)
  47. X, Y = np.meshgrid(x, y) #make X,Y grid
  48.  
  49. def energy(x,y):
  50. a = sum(coeff[0]*np.exp(coeff[1]*(x-coeff[4])**2 + coeff[2]*(x-coeff[4])*(y-coeff[5])
  51. + coeff[3]*(y-coeff[5])**2) for coeff in coefficients) #calculate Müller Brown PES
  52. return a
  53.  
  54. def force(x,y):
  55. Fx = -sum((coeff[0]*np.exp(coeff[1]*(x-coeff[4])**2 + coeff[2]*(x-coeff[4])*(y-coeff[5]) +
  56. coeff[3]*(y-coeff[5])**2))*(coeff[1]*(x-coeff[4])*2 + coeff[2]*(y-coeff[5])) for coeff in coefficients)
  57. Fy = -sum((coeff[0]*np.exp(coeff[1]*(x-coeff[4])**2 + coeff[2]*(x-coeff[4])*(y-coeff[5]) +
  58. coeff[3]*(y-coeff[5])**2))*(coeff[3]*(y-coeff[5])*2 + coeff[2]*(x-coeff[4])) for coeff in coefficients)
  59. return Fx, Fy
  60.  
  61. def Hessian(x,y,delta):
  62. Hess = np.array([[(force(x,y)[0]-force(x+delta,y)[0])/delta, (force(x,y)[1]-force(x+delta,y)[1])/delta],
  63. [(force(x,y)[0]-force(x,y+delta)[0])/delta, (force(x,y)[1]-force(x,y+delta)[1])/delta]])
  64. return Hess
  65.  
  66. def calcZ(mainminpos,min2pos,betha,deltaEmins):
  67. Hmin1 = Hessian(mainminpos[0],mainminpos[1],1e-7)
  68. Hmin2 = Hessian(min2pos[0],min2pos[1],1e-7)
  69. curvatures1, curvatures2 = np.linalg.eig(Hmin1)[0],np.linalg.eig(Hmin2)[0]
  70. Z = 2*np.pi/betha/(np.sqrt(curvatures1[0]*curvatures1[1])+np.sqrt(curvatures2[0]*curvatures2[1])*np.exp(-betha*deltaEmins))
  71. Z = Z*np.pi*2/betha/m
  72. return Z
  73.  
  74. def calZalternative(pointnum,V_backup,x_min,x_max,y_min,y_max):
  75. Zalt = np.sum(np.exp(-betha*(V_backup-energy(mainminpos[0],mainminpos[1]))))*(x_min-x_max)*(y_min-y_max)/(pointnum**2)
  76. Zalt = Zalt * np.pi*2/betha/m
  77. return Zalt
  78.  
  79. def calcZinResPhaseSpace(pointnum,V_backup,x_min,x_max,y_min,y_max):
  80. V_backup[V_backup<V_backup.min()+deltaE] = V_backup.min()+deltaE
  81. Z = np.sum(np.exp(-betha*(V_backup-energy(mainminpos[0],mainminpos[1]))))*(x_min-x_max)*(y_min-y_max)/(pointnum**2)
  82. Z = Z*np.pi*2/betha/m
  83. return Z
  84.  
  85. def computevec(mainminpos, mainsaddlepos):
  86. H = Hessian(mainsaddlepos[0],mainsaddlepos[1], 10e-7)
  87. Eigs = np.linalg.eig(H)
  88. whichvec = int(np.where(Eigs[0]<0)[0]) # which vector has negative eigenvalue
  89. vec = Eigs[1][:,whichvec]
  90. vec = vec*np.sign(np.dot(vec,mainminpos - mainsaddlepos)) # gets multiplied with -1 if it is looking away from the mainmin
  91. return vec
  92.  
  93. def calcP(deltaE,betha,Z,mainsaddlepos):
  94. H = Hessian(mainsaddlepos[0],mainsaddlepos[1], 10e-7)
  95. V = np.linalg.eig(H)[0]
  96. P = 2*np.pi*np.exp(-betha*deltaE)/(betha**2*m**(3/2)*np.sqrt(float(V[V>0])))/Z
  97. return P
  98.  
  99. def checkside(vec, xy_data,mainsaddlepos, buffer, delta_t):
  100. buffer_steps = int(buffer/delta_t)
  101. crossboarder = 0
  102. dist_sepplane = np.matmul(np.transpose(xy_data) - mainsaddlepos.reshape(1,2) , vec.reshape(2,1))
  103. dist_sepplane[dist_sepplane < 0] = -1
  104. dist_sepplane[dist_sepplane > 0] = 1
  105.  
  106. change = dist_sepplane - np.row_stack((dist_sepplane[0],dist_sepplane[0:np.size(dist_sepplane)-1]))
  107. if np.any(change != 0):
  108. if np.sum(dist_sepplane[np.where(change != 0)[0][0]:np.where(change != 0)[0][0] + buffer_steps]) == -buffer_steps:
  109. crossboarder = 1
  110. return crossboarder
  111.  
  112. def checkside_with_comeback(vec, xy_data):
  113. crossboarder = 0
  114. dist_sepplane = np.matmul(np.transpose(xy_data) - mainsaddlepos.reshape(1,2) , vec.reshape(2,1))
  115. dist_sepplane[dist_sepplane < 0] = 0 # towards sidemin
  116. dist_sepplane[dist_sepplane > 0] = 1 # towards mainmin
  117.  
  118. change = dist_sepplane - np.row_stack((dist_sepplane[0],dist_sepplane[0:np.size(dist_sepplane)-1]))
  119. changesum = np.sum(change[change != 0])
  120. if changesum != 0:
  121. if np.sum(dist_sepplane[np.where(change != 0)[0][0]:np.where(change != 0)[0][0] + 5]) == 0 or np.sum(dist_sepplane[np.where(change != 0)[0][0]:np.where(change != 0)[0][0] + 5]) == 5:
  122. crossboarder = 1
  123. return crossboarder
  124.  
  125.  
  126. def calcMat(betha,pointnum,xmin,xmax,ymin,ymax,deltaE):
  127. x = np.linspace(xmin,xmax,pointnum*3)
  128. y = np.linspace(ymin,ymax,pointnum*3)
  129. X, Y = np.meshgrid(x, y)
  130. Vacc = np.exp(-betha*energy(X,Y))
  131. Emin = energy(mainminpos[0],mainminpos[1])
  132.  
  133. Vacc[Vacc>np.exp(-betha*(Emin+deltaE))] = np.exp(-betha*(Emin + deltaE))
  134.  
  135. VaccCUM = np.cumsum(Vacc)
  136. VaccCUMSUM = VaccCUM.reshape(pointnum*3,pointnum*3)
  137. VaccCUMSUM_norm = VaccCUMSUM/VaccCUMSUM.max()
  138. return VaccCUMSUM_norm, VaccCUM
  139.  
  140.  
  141. def findStartv(betha,m):
  142. v_abs = np.sqrt(-2/(betha*m)*np.log(1-np.random.uniform(0,1)))
  143. rand = np.random.uniform(0,2*np.pi)
  144. randvec = np.array([np.cos(rand),np.sin(rand)])
  145. v_maxboltz = v_abs * randvec
  146. return v_maxboltz
  147.  
  148.  
  149. def findStartv_restricted_phase_space(betha,m,startE,deltaE):
  150. E_kinmin = float(np.array([deltaE-startE,0]).max())
  151. v1 = np.sqrt(2*(E_kinmin)/m)
  152. v_abs = np.sqrt(v1**2 - 2*np.log(1- np.random.uniform(0,1))/(betha*m))
  153. rand = np.random.uniform(0,2*np.pi)
  154. randvec = np.array([np.cos(rand),np.sin(rand)])
  155. v_maxboltz = v_abs * randvec
  156. return v_maxboltz
  157.  
  158.  
  159. def findStartPos(VaccCUMSUM_norm,xmin,xmax,ymin,ymax,pointnum):
  160. r = np.random.uniform(0,1)
  161. Vdiff_row = np.abs(VaccCUMSUM_norm[:,0] - r)
  162. nearV = Vdiff_row.min()
  163. ygrid = int(np.where(Vdiff_row < nearV + 1e-18)[0][0])
  164.  
  165. Vdiff_zeile = np.abs(VaccCUMSUM_norm[ygrid-1:ygrid+1,:] - r)
  166. nearestV = np.abs(Vdiff_zeile.min())
  167. xgrid = int(np.where(Vdiff_zeile < nearestV + 1e-20)[1][0])
  168. ygrid = ygrid - 1 + np.where(Vdiff_zeile < nearestV + 1e-15)[0][0]
  169. y = ymin + ygrid*(ymax-ymin)/(pointnum*3)
  170. x = xmin + xgrid*(xmax-xmin)/(pointnum*3)
  171. return x,y
  172.  
  173.  
  174. def findMinEnergyPath(m,mainsaddlepos):
  175. x = np.zeros(1000+1)
  176. y = np.zeros(1000+1)
  177. delta = 0.0001
  178. x[0],y[0] = mainsaddlepos + (mainminpos - mainsaddlepos)*delta
  179. for i in np.linspace(1,1000,1000):
  180. i = int(i)
  181. Fx = -sum((coeff[0]*np.exp(coeff[1]*(x[i-1]-coeff[4])**2 + coeff[2]*(x[i-1]-coeff[4])*(y[i-1]-coeff[5]) +
  182. coeff[3]*(y[i-1]-coeff[5])**2))*(coeff[1]*(x[i-1]-coeff[4])*2 + coeff[2]*(y[i-1]-coeff[5])) for coeff in coefficients)
  183. Fy = -sum((coeff[0]*np.exp(coeff[1]*(x[i-1]-coeff[4])**2 + coeff[2]*(x[i-1]-coeff[4])*(y[i-1]-coeff[5]) +
  184. coeff[3]*(y[i-1]-coeff[5])**2))*(coeff[3]*(y[i-1]-coeff[5])*2 + coeff[2]*(x[i-1]-coeff[4])) for coeff in coefficients)
  185. x[i], y[i] = x[i-1] + Fx*delta, y[i-1] + Fy*delta
  186.  
  187. if x[i] - x[i-1] < delta*1e-2 and y[i] - y[i-1] < delta*1e-2 and i>20:
  188. break
  189.  
  190. deltax, deltay = x[i] - x[i-1], y[i] - y[i-1]
  191. deltax, deltay = deltax/(np.sqrt(deltax**2+deltay**2)), deltay/(np.sqrt(deltax**2+deltay**2))
  192. deltaxy = np.array([deltax, deltay]).reshape(2,1)
  193. return deltaxy, x[i], y[i]
  194.  
  195.  
  196. def calcArrheniusTransRate(deltaxy, m, deltaE, x_last, y_last, betha):
  197. H = Hessian(x_last,y_last,1e-7)
  198. gradchange = np.matmul(H,deltaxy)
  199. curv = np.matmul(gradchange.reshape(1,2),deltaxy)
  200. w = np.sqrt(curv/m)
  201. k_arrhenius = w/(2*np.pi)*np.exp(-betha*deltaE)
  202. return k_arrhenius
  203.  
  204.  
  205. V_backup = energy(X,Y)
  206. V = np.array(V_backup) #calculate the PES by calling energy function on the X,Y grid
  207. V[V>200] = float('nan') #set very big values of PES to NaN for estetical reasons
  208.  
  209.  
  210. #%%FIGURE
  211.  
  212. fig = plt.figure()
  213. #ax = fig.add_subplot(111, projection='3d') #fig.projection = '3d' #uncomment if you want 3D plot
  214. CS = plt.contour(X, Y, V, pointnum, linewidths=0.5, colors='k') #contour plot with xx contour lines
  215. CS = plt.contourf(X, Y, V, pointnum) #adds colors to the contour lines
  216. plt.colorbar() #draw colorbar
  217.  
  218.  
  219.  
  220. #%%IMPLEMENT EQUATIONS OF MOTION
  221.  
  222. deltaE = -energy(mainminpos[0],mainminpos[1]) + energy(mainsaddlepos[0],mainsaddlepos[1]) #energy difference between saddle point and minimum (small two minimas and their saddle)
  223. deltaEmins = energy(min2pos[0],min2pos[1]) - energy(mainminpos[0],mainminpos[1]) #energy diff between the two minima
  224. betha = 1e-1*1.6
  225. m = 1
  226. delta_t = 0.001 #one increment of time
  227.  
  228. l = -1
  229. times = np.array([0.1]) + buffer #times one particle can propagate till thermal equilibration is reached --> then it gets new position and velocities
  230. predtrans = np.zeros(int(np.size(times)))
  231. actualtrans = np.zeros(int(np.size(times)))
  232.  
  233. VaccCUMSUM_norm = calcMat(betha,pointnum,x_min,x_max,y_min,y_max,deltaE)[0]
  234.  
  235.  
  236.  
  237. traj_num_max = 20000
  238.  
  239. E_diff = np.zeros(traj_num_max+1) # will be the difference of starting energy and final energy after all runs
  240. traj_num = -1
  241. pottrans_traj_num = 0
  242. trans_traj_num = np.zeros(np.size(times))
  243. count = 0
  244.  
  245. count_occurrances = np.zeros([pointnum,pointnum])
  246.  
  247. x,y = mainminpos[0],mainminpos[1]
  248. vx,vy = 5,8
  249. gamma = 30
  250. v = np.zeros(int((traj_num_max*((times[0] + buffer+0.001)/delta_t ))))
  251. sigma = np.sqrt(2*gamma/(betha*delta_t))
  252.  
  253. while traj_num<traj_num_max: #traj_num < number of trajectories we are gonna sample
  254. traj_num+=1
  255. t = 0
  256. j = -1
  257.  
  258. U = (energy(x,y)-V_backup.min())
  259.  
  260. T = m/2*(vx**2 +vy**2)
  261. #print(E)
  262. vx, vy = vx + force(x,y)[0]/m*delta_t/2, vy + force(x,y)[1]/m*delta_t #make a half step at beginning (leap frog)
  263.  
  264. E = U+T #calculate total Energy
  265. xy_data = np.zeros((2,int(times[0]/delta_t)+1)) #initialize xy_array
  266.  
  267.  
  268. while t<times[0]+delta_t:
  269. j+=1
  270. count+=1
  271. x,y = x+vx*delta_t, y+vy*delta_t
  272. #equations of motion
  273. Fx_cons, Fy_cons = force(x,y)
  274. Fx_fric, Fy_fric = -gamma*vx,-gamma*vy
  275. Fx_rand, Fy_rand = np.random.normal(0,sigma), np.random.normal(0,sigma)
  276. Fx_net,Fy_net = Fx_rand+Fx_cons+Fx_fric, Fy_rand+Fy_cons+Fy_fric
  277.  
  278. vx, vy = vx+Fx_net/m*delta_t, vy+Fy_net/m*delta_t
  279.  
  280. v[count] = vx
  281.  
  282. xy_data[:,j] = x,y
  283. t = t+delta_t
  284. if x<x_max and y<y_max:
  285. x_grid = int((x-x_min)*pointnum/(x_max-x_min))
  286. y_grid = int((y-y_min)*pointnum/(y_max-y_min))
  287. count_occurrances[x_grid,y_grid] = count_occurrances[x_grid,y_grid] + 1
  288.  
  289. U2 = (energy(x+vx*delta_t/2,y+vy*delta_t/2)-V_backup.min()) #calculate pot and kin energy after the sweep
  290. T2 = m/2*(vx**2 +vy**2)
  291. E2 = U2+T2
  292. E_diff[traj_num] = np.abs(E-E2) #calc numerical error in energy
  293.  
  294. if checkside(computevec(mainminpos,mainsaddlepos) , xy_data[:,0:int(times[0]/delta_t)],mainsaddlepos,buffer,delta_t) == 1:
  295. np.savetxt('x_data.dat',xy_data[0,:]) #save x and y Data for scatter plot of animation
  296. np.savetxt('y_data.dat',xy_data[1,:])
  297. print(1)
  298. trans_traj_num[0] = trans_traj_num[0]+1
  299. scat = plt.scatter(xy_data[0,:],xy_data[1,:],marker='o',c='r',s=5,zorder=10)
  300.  
  301. x = np.linspace(-10,10,500)
  302. fig = plt.figure
  303. fig, axs = plt.subplots(1, 2, sharey=True, tight_layout=True)
  304. axs[0].hist(v, bins=100)
  305. plt.plot(x,np.exp(-x**2*betha/2)*9200)
  306.  
  307.  
  308. Z = calZalternative(pointnum,V_backup,x_min,x_max,y_min,y_max)
  309. Z_res = calcZinResPhaseSpace(pointnum,V_backup,x_min,x_max,y_min,y_max)
  310. P = calcP(deltaE,betha,Z,mainsaddlepos)
  311. predtrans = P*traj_num_max*(times - buffer)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement