def get_surface(lepsgui): """Get Vmat (potential) for a given set of parameters""" lepsgui.get_params() #Check if params have changed. If not, no need to recalculate if lepsgui.old_params == lepsgui.params and not lepsgui._firstrun: return resl = 0.02 #Resolution lepsgui._firstrun = False #Get grid lepsgui.Grid_X = np.arange(lepsgui.params.mina, lepsgui.params.maxa, resl) lepsgui.Grid_Y = np.arange(lepsgui.params.minb, lepsgui.params.maxb, resl) lepsgui.Vmat = np.zeros((len(lepsgui.Grid_Y), len(lepsgui.Grid_X))) #Calculate potential for each gridpoint for drabcount, drab in enumerate(lepsgui.Grid_X): lepsgui.Current_Separations[0] = drab for drbccount, drbc in enumerate(lepsgui.Grid_Y): lepsgui.Current_Separations[1] = drbc V = lepspoint(np.deg2rad(lepsgui.theta), lepsgui.params.Dissociation_energies, lepsgui.params.Reqs, lepsgui.params.Morse_Parameters, lepsgui.params.surface_param, lepsgui.Current_Separations, lepsgui.Current_First_derivative, lepsgui.Current_Hessian, derivative=0) lepsgui.Vmat[drbccount, drabcount] = V lepsgui.old_params = lepsgui.params
def get_surface(self): """Get Vmat (potential) for a given set of parameters""" self.get_params() #Check if params have changed. If not, no need to recalculate new_params = [self.a, self.b, self.c, self.theta] if self.old_params == new_params and not self._firstrun: return resl = 0.02 #Resolution grad = 0 #Gradient calc type (0 = energy) self._firstrun = False #Get grid self.x = np.arange(self.mina, self.maxa, resl) self.y = np.arange(self.minb, self.maxb, resl) self.Vmat = np.zeros((len(self.y), len(self.x))) #Calculate potential for each gridpoint for drabcount, drab in enumerate(self.x): for drbccount, drbc in enumerate(self.y): V = lepspoint(drab, drbc, np.deg2rad(self.theta), self.Drab, self.Drbc, self.Drac, self.Brab, self.Brbc, self.Brac, self.lrab, self.lrbc, self.lrac, self.H, grad) self.Vmat[drbccount, drabcount] = V self.old_params = new_params
def get_first(lepsgui): """1 step of trajectory to get geometry properties""" lepsgui._read_entries() lepsgui.get_params() lepsgui.current_potential_energy = lepspoint( np.deg2rad(lepsgui.theta), lepsgui.params.Dissociation_energies, lepsgui.params.Reqs, lepsgui.params.Morse_Parameters, lepsgui.params.surface_param, lepsgui.Current_Separations, lepsgui.Current_First_derivative, lepsgui.Current_Hessian, 2) lepsgui.theta, lepsgui.current_kinetic_energy = lepnorm( np.deg2rad(lepsgui.theta), lepsgui.Current_Separations, lepsgui.Current_First_derivative, lepsgui.Current_Hessian, lepsgui.Current_Velocities, lepsgui.Current_Accelerations, lepsgui.params.Masses, lepsgui.params.Reduced_masses, lepsgui.dt, False)
def get_first(self): """1 step of trajectory to get geometry properties""" self._read_entries() self.get_params() dt = self.dt ma = self.ma mb = self.mb mc = self.mc mab = self.mab mbc = self.mbc Drab = self.Drab Drbc = self.Drbc Drac = self.Drac lrab = self.lrab lrbc = self.lrbc lrac = self.lrac Brab = self.Brab Brbc = self.Brbc Brac = self.Brac xrabi = self.xrabi xrbci = self.xrbci prabi = self.prabi prbci = self.prbci thetai = np.deg2rad(self.theta) vrabi = prabi / mab vrbci = prbci / mbc vraci = 0 grad = 2 ti = 0 Vrinti,Frabi,Frbci,Fraci,hr1r1i,hr1r2i,hr1r3i,hr2r2i,hr2r3i,hr3r3i = lepspoint(xrabi,xrbci,thetai,Drab,Drbc,Drac,Brab,Brbc,Brac,lrab,lrbc,lrac,self.H,grad) xrabf,xrbcf,xracf,thetaf,vrabf,vrbcf,vracf,tf,arabi,arbci,araci,Ktoti = lepnorm(xrabi,xrbci,thetai,Frabi,Frbci,Fraci,vrabi,vrbci,vraci,hr1r1i,hr1r2i,hr1r3i,hr2r2i,hr2r3i,hr3r3i,ma,mb,mc,ti,dt,False) return Vrinti,Frabi,Frbci,Fraci,hr1r1i,hr1r2i,hr1r3i,hr2r2i,hr2r3i,hr3r3i,xrabf,xrbcf,xracf,thetaf,vrabf,vrbcf,vracf,tf,arabi,arbci,araci,Ktoti
def get_trajectory(lepsgui): """Get dynamics, MEP or optimisation""" dt = lepsgui.dt #Time step lepsgui.current_time = 0 thetai = np.deg2rad(lepsgui.theta) #Collision Angle grad = 2 #Calculating gradients and Hessian lepsgui.get_arrays() lepsgui.Animation_Positions = [] lepsgui.append_animation_position() #Initial Velocity lepsgui.Current_Velocities = lepsgui.Current_Momenta / lepsgui.params.Reduced_masses lepsgui.Trajectory_Velocities = [] #Initialise outputs lepsgui.Trajectory_times = [] lepsgui.Trajectory_Separations = [] lepsgui.Trajectory_Velocities = [] lepsgui.Trajectory_Momenta = [] lepsgui.Trajectory_Accelerations = [] lepsgui.Trajectory_First_derivatives = [] lepsgui.Trajectory_Hessians = [] lepsgui.Potential_Energies = [] lepsgui.Kinetic_Energies = [] lepsgui.Potential_Energies = [] lepsgui.Total_Energies = [] #Initial conditions lepsgui.current_potential_energy = lepspoint( thetai, lepsgui.params.Dissociation_energies, lepsgui.params.Reqs, lepsgui.params.Morse_Parameters, lepsgui.params.surface_param, lepsgui.Current_Separations, lepsgui.Current_First_derivative, lepsgui.Current_Hessian, grad) lepsgui.add_trajectory_step() #Flag to stop appending to output in case of a crash terminate = False for itcounter in range(lepsgui.steps): if lepsgui.calc_type != "Dynamics": lepsgui.Current_Velocities = np.zeros((3)) #Get current potential, forces, and Hessian lepsgui.current_potential_energy = lepspoint( thetai, lepsgui.params.Dissociation_energies, lepsgui.params.Reqs, lepsgui.params.Morse_Parameters, lepsgui.params.surface_param, lepsgui.Current_Separations, lepsgui.Current_First_derivative, lepsgui.Current_Hessian, grad) if lepsgui.calc_type in ["Opt Min", "Opt TS"]: #Optimisation calculations #Diagonalise Hessian eigenvalues, eigenvectors = np.linalg.eig(lepsgui.Current_Hessian) #Eigenvalue test neg_eig_i = [i for i, eig in enumerate(eigenvalues) if eig < -0.01] if len(neg_eig_i) == 0 and lepsgui.calc_type == "Opt TS": msgbox.showinfo("Eigenvalues Info", "No negative eigenvalues at this geometry") terminate = True elif len(neg_eig_i) == 1 and lepsgui.calc_type == "Opt Min": msgbox.showerror( "Eigenvalues Error", "Too many negative eigenvalues at this geometry") terminate = True elif len(neg_eig_i) > 1: msgbox.showerror( "Eigenvalues Error", "Too many negative eigenvalues at this geometry") terminate = True #Optimiser Displacements = np.array([0., 0., 0.]) for mode in range(len(eigenvalues)): e_val = eigenvalues[mode] e_vec = eigenvectors[mode] disp = np.dot( np.dot((e_vec.T), lepsgui.Current_First_derivative), e_vec) / e_val Displacements += disp lepsgui.Current_Separations += Displacements #xrabf = xrabi + disps[0] #xrbcf = xrbci + disps[1] #xracf = ((xrabf ** 2) + (xrbcf ** 2) - 2 * xrabf * xrbcf * np.cos(thetai)) ** 0.5 else: #Dynamics/MEP try: lepsgui.theta, lepsgui.current_kinetic_energy = lepnorm( lepsgui.theta, lepsgui.Current_Separations, lepsgui.Current_First_derivative, lepsgui.Current_Hessian, lepsgui.Current_Velocities, lepsgui.Current_Accelerations, lepsgui.params.Masses, lepsgui.params.Reduced_masses, lepsgui.dt, False) lepsgui.current_time += lepsgui.dt except LinAlgError: msgbox.showerror( "Surface Error", "Energy could not be evaulated at step {}. Steps truncated" .format(itcounter + 1)) terminate = True if lepsgui.Current_Separations[ 0] > lepsgui.lim or lepsgui.Current_Separations[ 1] > lepsgui.lim: #Stop calc if distance lim is exceeded msgbox.showerror( "Surface Error", "Surface Limits exceeded at step {}. Steps truncated".format( itcounter + 1)) terminate = True if lepsgui.calc_type != "Dynamics": lepsgui.Current_Velocities = np.zeros((3)) if itcounter != lepsgui.steps - 1 and not terminate: #As above lepsgui.append_animation_position() ### Maybe not necessary #Get A-C Velocity r0 = np.linalg.norm(lepsgui.Trajectory_Separations[-1][2] - lepsgui.Trajectory_Separations[-1][0]) r1 = np.linalg.norm(lepsgui.Current_Separations[2] - lepsgui.Current_Separations[0]) vrac = (r1 - r0) / dt lepsgui.add_trajectory_step() if terminate: break
def get_trajectory(self): """Get dynamics, MEP or optimisation""" itlimit = self.steps #Max number of steps dt = self.dt #Time step ti = 0 #Initial time variable tf = 0 #Final time variable ma = self.ma #Mass of A mb = self.mb #Mass of B mc = self.mc #Mass of C mab = self.mab #Reduced mass of AB mbc = self.mbc #Reduced mass of BC Drab = self.Drab Drbc = self.Drbc Drac = self.Drac lrab = self.lrab lrbc = self.lrbc lrac = self.lrac Brab = self.Brab Brbc = self.Brbc Brac = self.Brac thetai = np.deg2rad(self.theta) #Collision Angle grad = 2 #Calculating gradients and Hessian xrabi = self.xrabi #Initial AB separation xrbci = self.xrbci #Initial BC separation xraci = ( (xrabi**2) + (xrbci**2) - 2 * xrabi * xrbci * np.cos(thetai))**0.5 #Initial AC separation prabi = self.prabi #Initial AB momentum prbci = self.prbci #Initial BC momentum vrabi = prabi / mab #Initial AB Velocity vrbci = prbci / mbc #Initial BC Velocity #Positions of A, B and C relative to B a = np.array([-xrabi, 0.]) b = np.array([0., 0.]) c = np.array([-np.cos(thetai) * xrbci, np.sin(thetai) * xrbci]) #Get centre of mass com = (a * ma + b * mb + c * mc) / (ma + mb + mc) com = np.real(com) #Translate to centre of mass (for animation) a -= com b -= com c -= com self.ra = [a] self.rb = [b] self.rc = [c] #Initial AC Velocity va = (a - self.ra[-1]) / dt vc = (c - self.rc[-1]) / dt vraci = np.linalg.norm(va + vc) #Initialise outputs self.xrab = [xrabi] self.xrbc = [xrbci] self.xrac = [xraci] self.vrab = [vrabi] self.vrbc = [vrbci] self.vrac = [vraci] self.t = [ti] self.Vrint = Vrint = [] self.Ktot = Ktot = [] self.Frab = Frab = [] self.Frbc = Frbc = [] self.Frac = Frac = [] self.arab = arab = [] self.arbc = arbc = [] self.arac = arac = [] self.etot = etot = [] self.hr1r1 = hr1r1 = [] self.hr1r2 = hr1r2 = [] self.hr1r3 = hr1r3 = [] self.hr2r2 = hr2r2 = [] self.hr2r3 = hr2r3 = [] self.hr3r3 = hr3r3 = [] #Flag to stop appending to output in case of a crash terminate = False for itcounter in range(itlimit): if self.calc_type != "Dynamics": vrabi = 0 vrbci = 0 vraci = 0 #Get current potential, forces, and Hessian Vrinti, Frabi, Frbci, Fraci, hr1r1i, hr1r2i, hr1r3i, hr2r2i, hr2r3i, hr3r3i = lepspoint( xrabi, xrbci, thetai, Drab, Drbc, Drac, Brab, Brbc, Brac, lrab, lrbc, lrac, self.H, grad) Vrint.append(Vrinti) Frab.append(Frabi) Frbc.append(Frbci) Frac.append(Fraci) hr1r1.append(hr1r1i) hr1r2.append(hr1r2i) hr1r3.append(hr1r3i) hr2r2.append(hr2r2i) hr2r3.append(hr2r3i) hr3r3.append(hr3r3i) if self.calc_type in ["Opt Min", "Opt TS"]: #Optimisation calculations #Diagonalise Hessian hessian = np.array([[hr1r1i, hr1r2i, hr1r3i], [hr1r2i, hr2r2i, hr2r3i], [hr1r3i, hr2r3i, hr3r3i]]) eigenvalues, eigenvectors = np.linalg.eig(hessian) #Get forces for opt calculation forces = np.array([Frabi, Frbci, Fraci]) #Eigenvalue test neg_eig_i = [ i for i, eig in enumerate(eigenvalues) if eig < -0.01 ] if len(neg_eig_i) == 0 and self.calc_type == "Opt TS": msgbox.showinfo( "Eigenvalues Info", "No negative eigenvalues at this geometry") terminate = True elif len(neg_eig_i) == 1 and self.calc_type == "Opt Min": msgbox.showerror( "Eigenvalues Error", "Too many negative eigenvalues at this geometry") terminate = True elif len(neg_eig_i) > 1: msgbox.showerror( "Eigenvalues Error", "Too many negative eigenvalues at this geometry") terminate = True #Optimiser disps = np.array([0., 0., 0.]) for mode in range(len(eigenvalues)): e_val = eigenvalues[mode] e_vec = eigenvectors[mode] disp = np.dot(np.dot((e_vec.T), forces), e_vec) / e_val disps += disp xrabf = xrabi + disps[0] xrbcf = xrbci + disps[1] xracf = ((xrabf**2) + (xrbcf**2) - 2 * xrabf * xrbcf * np.cos(thetai))**0.5 arabi = 0 arbci = 0 araci = 0 thetaf = thetai vrabf = 0 vrbcf = 0 vracf = 0 Ktoti = 0 tf += dt else: #Dynamics/MEP try: xrabf, xrbcf, xracf, thetaf, vrabf, vrbcf, vracf, tf, arabi, arbci, araci, Ktoti = lepnorm( xrabi, xrbci, thetai, Frabi, Frbci, Fraci, vrabi, vrbci, vraci, hr1r1i, hr1r2i, hr1r3i, hr2r2i, hr2r3i, hr3r3i, ma, mb, mc, ti, dt, self.calc_type == "MEP") except LinAlgError: msgbox.showerror( "Surface Error", "Energy could not be evaulated at step {}. Steps truncated" .format(itcounter + 1)) terminate = True if xrabf > self.lim or xrbcf > self.lim: #Stop calc if distance lim is exceeded msgbox.showerror( "Surface Error", "Surface Limits exceeded at step {}. Steps truncated". format(itcounter + 1)) terminate = True arab.append(arabi) arbc.append(arbci) arac.append(araci) Ktot.append(Ktoti) #Total energy etot.append(Vrint[itcounter] + Ktot[itcounter]) if itcounter != itlimit - 1 and not terminate: #As above a = np.array([-xrabf, 0.]) b = np.array([0., 0.]) c = np.array([-np.cos(thetaf) * xrbcf, np.sin(thetaf) * xrbcf]) com = (a * ma + b * mb + c * mc) / (ma + mb + mc) com = np.real(com) a -= com b -= com c -= com #Get A-C Velocity r0 = np.linalg.norm(self.rc[-1] - self.ra[-1]) r1 = np.linalg.norm(c - a) vrac = (r1 - r0) / dt self.ra.append(a) #A Pos self.rb.append(b) #B Pos self.rc.append(c) #C Pos self.xrab.append(xrabf) #A-B Distance self.xrbc.append(xrbcf) #B-C Distance self.xrac.append(xracf) #A-C Distance if self.calc_type == "Dynamics": self.vrab.append(vrabf) #A-B Velocity self.vrbc.append(vrbcf) #B-C Velocity self.vrac.append(vrac) #A-C Velocity else: self.vrab.append(0.) #A-B Velocity self.vrbc.append(0.) #B-C Velocity self.vrac.append(0.) #A-C Velocity self.t.append(tf) #Time xrabi = xrabf xrbci = xrbcf xraci = xracf vrabi = vrabf vrbci = vrbcf vraci = vracf ti = tf if terminate: break