Ejemplo n.º 1
0
    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]
Ejemplo n.º 2
0
 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
Ejemplo n.º 3
0
    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]
Ejemplo n.º 4
0
    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()
Ejemplo n.º 5
0
    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
Ejemplo n.º 6
0
    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