def get_forces(self): F0 = self.minmodesearch(minoriso = 'min') Fparallel = np.vdot(F0, self.N) * self.N Fperp = F0 - Fparallel beta1 = self.beta if self.curvature > 0: self.Ftrans = -Fparallel print "drag up directly" else: if vmag(F0) < self.releaseF: gamma1 = 1; gamma2 = 1; else: self.minmodesearch(minoriso = 'iso') print "exact isocurve:", self.isocurv if abs(self.isocurv) > 20: self.isocurv = 20 * np.sign(self.isocurv) gamma1 = 2.0 / (np.exp((self.isocurv - 0.0) * beta1) + 1.0) - 1.0 gamma2 = -1.0 / (np.exp((self.isocurv - 0.0) * beta1) + 1.0) + 1.0 self.Ftrans = gamma2 * Fperp - gamma1 * Fparallel #####xph: needs further improvement to insure k-dimer won't be trapped at isocurve=0.0 and Fperp=0.0 #if vmag(F0) > 0.03 and vmag(self.Ftrans) < 0.005: #self.Ftrans = Fperp - Fparallel #self.Ftrans *= 10 if self.ss: return self.Ftrans else: return self.Ftrans[:-3]
def getMaxAtomForce(self): if self.Ftrans is None: return 1000 maxForce = -1 for i in range(len(self.Ftrans)): maxForce = max(maxForce, vmag(self.Ftrans[i])) #maxForce = vmag(self.Ftrans) return maxForce
def get_forces(self): F0 = self.minmodesearch() self.F0 = F0 Fparallel = np.vdot(F0, self.N) * self.N Fperp = F0 - Fparallel alpha = vmag(Fperp) / vmag(F0) print "alpha=vmag(Fperp)/vmag(F0): ", alpha print "curvature:", self.get_curvature() gamma = 1.0 if self.curvature > 0: self.Ftrans = -1 * Fparallel print "drag up directly" else: self.Ftrans = Fperp - gamma * Fparallel if self.ss: return self.Ftrans else: return self.Ftrans[:-3]
def step(self): if self.steps == 0: if self.ss: self.V = np.zeros((self.natom + 3, 3)) else: self.V = np.zeros((self.natom, 3)) self.steps += 1 Ftrans = self.get_forces() print "Ftrans", vmag(Ftrans) dV = Ftrans * self.dT if np.vdot(self.V, Ftrans) > 0: self.V = dV * (1.0 + np.vdot(dV, self.V) / np.vdot(dV, dV)) else: self.V = dV step = self.V * self.dT if vmag(step) > self.maxStep: step = self.maxStep * vunit(step) self.set_positions(self.get_positions() + step) self.E = self.get_potential_energy()
def minmodesearch(self): F0 = self.update_general_forces(self.R0) F1 = self.rotation_update() dphi = 100 ## only for atom degree of freedoms #u = self.N[:-3].flatten() ## include cell too u = self.N.flatten() beta = vmag(u) size = (self.natom + 3) * 3 #size = self.natom * 3 T = np.zeros((size, size)) Q = np.zeros((size, size)) #while dphi > self.phi_tol and iteration < self.rotationMax: for i in range(size): Q[:, i] = u / beta Hv = -(F1 - F0) / self.dR #u = Hv[:-3].flatten() u = Hv.flatten() if i > 0: u = u - beta * Q[:, i - 1] alpha = np.vdot(Q[:, i], u) u = u - alpha * Q[:, i] # re-orthogonalize u = u - np.dot(Q, np.dot(Q.T, u)) T[i, i] = alpha if i > 0: T[i - 1, i] = beta T[i, i - 1] = beta beta = vmag(u) newN = np.reshape(u / beta, (-1, 3)) #self.N[:-3] = newN self.N = newN F1 = self.rotation_update() ##Check Eigenvalues if i > 0: eigenValues, eigenVectors = np.linalg.eig(T[:i + 1, :i + 1]) idx = eigenValues.argsort() ew = eigenValues[idx][0] evT = eigenVectors[:, idx][:, 0] ##Convert eigenvector of T matrix to eigenvector of full Hessian evEst = Q[:, :i + 1].dot(evT) evEst = vunit(evEst) evAtom_old = copy.copy(evAtom) evAtom = np.reshape(evEst, (-1, 3)) c0 = ew ## check with pi/2 dotp = np.vdot(evAtom, evAtom_old) if dotp > 1: dotp = 1 elif dotp < -1: dotp = -1 dphi = np.arccos(dotp) if dphi > np.pi / 2.0: dphi = np.pi - dphi else: #evAtom = self.N[:-3] #c0 = np.vdot(Hv[:-3], evAtom) evAtom = self.N c0 = np.vdot(Hv, evAtom) #print "i, Curvature, dphi:", i, c0, dphi if dphi < self.phi_tol or i == size - 1 or i >= self.rotationMax: #self.N[:-3] = evAtom self.N = evAtom break self.curvature = c0 return F0
def minmodesearch(self, minoriso): # rotate dimer to the minimum mode direction # self.N, the dimer direction; # self.T, the rotation direction, spans the rotation plane with self.N. ## self.N or self.Contour if minoriso == "min": self.F0 = self.update_general_forces(self.R0) mode = self.N.copy() else: F0unit = vunit(self.F0) mode = self.Contour.copy() mode = mode - np.vdot(mode, F0unit) * F0unit # project out any rigid translation and rotation if not self.ss: mode = self.project_translt_rott(mode, self.R0) F0 = self.F0 F1 = self.rotation_update(mode) phi_min = 1.5 Fperp = F1 * 0.0 # avoid Fperp_old asignment error iteration = 0 while iteration < self.rotationMax: ## self.N or self.Contour if minoriso == "min": if phi_min <= self.phi_tol: break F0perp = F0 - np.vdot(F0, mode) * mode F1perp = F1 - np.vdot(F1, mode) * mode else: if phi_min <= self.phi_iso: break mode = mode - np.vdot(mode, F0unit) * F0unit F0perp = F0 * 0.0 F1iso = F1 - np.vdot(F1, F0unit) * F0unit F1perp = F1iso - np.vdot(F1iso, mode) * mode Fperp_old = Fperp Fperp = 2.0 * (F1perp - F0perp) if iteration == 0: Fperp_old = Fperp self.T = mode * 0.0 self.Tnorm= 0.0 # update self.T self.rotation_plane(Fperp, Fperp_old, mode) if minoriso == "iso": self.T = self.T - np.vdot(self.T, F0unit) * F0unit self.T = vunit(self.T) # project out any rigid translation and rotation if not self.ss: self.T = self.project_translt_rott(self.T, self.R0) # curvature and its derivative c0 = np.vdot(F0-F1, mode) / self.dR c0d = np.vdot(F0-F1, self.T) / self.dR * 2.0 phi_1 = -0.5 * atan(c0d / (2.0 * abs(c0))) if abs(phi_1) <= self.phi_tol: break # calculate F_prime: force after rotating the dimer by phi_prime N1_prime = vunit(mode * cos(phi_1) + self.T * sin(phi_1)) self.iset_endpoint_pos(N1_prime, self.R0, self.R1_prime) F1_prime = self.update_general_forces(self.R1_prime) c0_prime = np.vdot(F0-F1_prime, N1_prime) / self.dR # calculate phi_min b1 = 0.5 * c0d a1 = (c0 - c0_prime + b1 * sin(2 * phi_1)) / (1 - cos(2 * phi_1)) a0 = 2 * (c0 - a1) phi_min = 0.5 * atan(b1 / a1) c0_min = 0.5 * a0 + a1 * cos(2.0 * phi_min) + b1 * sin(2 * phi_min) # check whether it is minimum or maximum if c0_min > c0 : phi_min += pi * 0.5 c0_min = 0.5 * a0 + a1 * cos(2.0 * phi_min) + b1 * sin(2 * phi_min) # update self.N mode = vunit(mode * cos(phi_min) + self.T * sin(phi_min)) c0 = c0_min # update F1 by linear extropolation F1 = F1 * (sin(phi_1 - phi_min) / sin(phi_1)) + F1_prime * (sin(phi_min) / sin(phi_1)) \ + F0 * (1.0 - cos(phi_min) - sin(phi_min) * tan(phi_1 * 0.5)) #print "phi_min:", phi_min, "toque:", vmag(Fperp) iteration += 1 if minoriso == "min": self.curvature = c0 self.N = mode.copy() ''' ## estimate the curvature of the isophote (isoenergy curve) Fg = vunit(F0) cosalpha = abs(np.vdot(Fg, self.N)) print "cosalpha", cosalpha if cosalpha > 0.01 and cosalpha < 0.999: N1_prime = vunit(self.N - np.vdot(Fg, self.N)*Fg) self.iset_endpoint_pos(N1_prime, self.R0, self.R1_prime) F1_prime = self.update_general_forces(self.R1_prime) c0_prime = np.vdot(F0-F1_prime, N1_prime) / self.dR self.kappa = -c0_prime/vmag(F0) else: self.kappa = -0.25 ''' else: self.isocurv = -c0/vmag(F0) self.Contour = mode.copy() print "isocurv iteration:", iteration return F0