def make_result(self, coords, energy): from pele.optimize import Result res = Result() res.coords = coords res.energy = energy res.eigenval = 1. res.eigenvec = coords.copy() return res
def get_result(self): res = Result() res.energy = self.energy res.gradient = self.gradient res.coords = self.coords res.nsteps = self.iter_number res.rms = np.linalg.norm(res.gradient) / np.sqrt(len(res.gradient)) res.nfev = self.transverse_potential.nfev res.eigenval = self.eigenval res.eigenvec = self.get_eigenvector() res.success = self.stop_criterion_satisfied() return res
def _get_lowest_eigenvector_diagonalization(self, coords, **kwargs): """compute the lowest eigenvector by diagonalizing the Hessian This scales as N**3, so can be very slow for large systems. """ if self.verbosity > 3: print "computing the lowest eigenvector by diagonalizing the Hessian" hess = self.pot.getHessian(coords) eigenval, evec = get_smallest_eig(hess) res = Result() res.eigenval = eigenval res.eigenvec = evec res.nfev = 1 res.success = True res.rms = 0. return res
def _get_lowest_eigenvector_diagonalization(self, coords, **kwargs): """compute the lowest eigenvector by diagonalizing the Hessian This scales as N**3, so can be very slow for large systems. """ if self.verbosity > 3: print("computing the lowest eigenvector by diagonalizing the Hessian") hess = self.pot.getHessian(coords) eigenval, evec = get_smallest_eig(hess) res = Result() res.eigenval = eigenval res.eigenvec = evec res.nfev = 1 res.success = True res.rms = 0. return res
def get_result(self): """return a results object""" trans_res = self.translator.get_result() rot_result = self.rotator.get_result() res = Result() res.eigenval = rot_result.eigenval res.eigenvec = rot_result.eigenvec res.coords = trans_res.coords res.energy, res.grad = self.get_true_energy_gradient(res.coords) res.rms = trans_res.rms res.nfev = rot_result.nfev + trans_res.nfev res.nsteps = self.iter_number res.success = self.stop_criterion_satisfied() if res.eigenval > 0: res.success = False return res
def run(self): """The main loop of the algorithm""" coords = np.copy(self.coords) res = Result() # return object res.message = [] self._compute_gradients(coords) iend = 0 for i in xrange(self.nsteps): iend = i # get the lowest eigenvalue and eigenvector self.overlap = self._getLowestEigenVector(coords, i) overlap = self.overlap if self.eigenval < 0: self.negatives_before_check -= 1 # determine whether everything looks OK. all_ok = self.eigenval < 0 or not self.check_negative if not all_ok: if i == 0: # we need to accept because we haven't saved the state yet # Also, demand_initial_negative_vec will stop later if needed all_ok = True if not all_ok: if self.negatives_before_check > 0 and not self.demand_initial_negative_vec: print " positive before check. setting all ok" all_ok = True # if everything is OK, then continue, else revert the step if all_ok: self._saveState(coords) self.reduce_step = 0 else: self.npositive += 1 if self.npositive > self.npositive_max: logger.warning( "positive eigenvalue found too many times. ending %s", self.npositive) res.message.append( "positive eigenvalue found too many times %d" % self.npositive) break if self.verbosity > 2: logger.info( "the eigenvalue turned positive. %s %s", self.eigenval, "Resetting last good values and taking smaller steps") coords = self._resetState() self.reduce_step += 1 # step uphill along the direction of the lowest eigenvector coords = self._stepUphill(coords) # minimize the coordinates in the space perpendicular to the lowest eigenvector tangent_ret = self._minimizeTangentSpace( coords, energy=self.get_energy(), gradient=self.get_gradient()) coords = tangent_ret.coords tangentrms = tangent_ret.rms # check if we are done and print some stuff # self._compute_gradients(coords) # this is unnecessary E = self.get_energy() grad = self.get_gradient() rms = np.linalg.norm(grad) * self.rmsnorm gradpar = np.dot(grad, self.eigenvec) / np.linalg.norm( self.eigenvec) if self.iprint > 0: if (i + 1) % self.iprint == 0: ostring = "findTS: %3d E %9g rms %8g eigenvalue %9g rms perp %8g grad par %9g overlap %g" % ( i, E, rms, self.eigenval, tangentrms, gradpar, overlap) extra = " Evec search: %d rms %g" % ( self.leig_result.nfev, self.leig_result.rms) extra += " Tverse search: %d step %g" % ( self.tangent_result.nfev, self.tangent_move_step) extra += " Uphill step:%g" % (self.uphill_step_size, ) logger.info("%s %s", ostring, extra) if callable(self.event): self.event(energy=E, coords=coords, rms=rms, eigenval=self.eigenval, stepnum=i) if rms < self.tol: break if self.nfail >= self.nfail_max: logger.warning( "stopping findTransitionState. too many failures in eigenvector search %s", self.nfail) res.message.append( "too many failures in eigenvector search %d" % self.nfail) break if i == 0 and self.eigenval > 0.: if self.verbosity > 1: logger.warning( "initial eigenvalue is positive - increase NEB spring constant?" ) if self.demand_initial_negative_vec: logger.warning( " aborting transition state search") res.message.append("initial eigenvalue is positive %f" % self.eigenval) break # done. do one last eigenvector search because coords may have changed self._getLowestEigenVector(coords, iend) # print some data if self.verbosity > 0 or self.iprint > 0: logger.info("findTransitionState done: %s %s %s %s %s", iend, E, rms, "eigenvalue", self.eigenval) success = True # check if results make sense if self.eigenval >= 0.: if self.verbosity > 2: logger.info( "warning: transition state is ending with positive eigenvalue %s", self.eigenval) success = False if rms > self.tol: if self.verbosity > 2: logger.info( "warning: transition state search appears to have failed: rms %s", rms) success = False if iend >= self.nsteps: res.message.append("maximum iterations reached %d" % iend) # update nfev with the number of calls from the transverse walker if self._transverse_walker is not None: twres = self._transverse_walker.get_result() self.nfev += twres.nfev res.coords = coords res.energy = E res.eigenval = self.eigenval res.eigenvec = self.eigenvec res.grad = grad res.rms = rms res.nsteps = iend res.success = success res.nfev = self.nfev return res
def run(self): """The main loop of the algorithm""" coords = np.copy(self.coords) res = Result() # return object res.message = [] # if starting with positive curvature, disable negative eigenvalue check # this will be reenabled as soon as the eigenvector becomes negative negative_before_check = 10 self._compute_gradients(coords) for i in xrange(self.nsteps): # get the lowest eigenvalue and eigenvector self.overlap = self._getLowestEigenVector(coords, i) overlap = self.overlap #print self.eigenval if self.eigenval < 0: negative_before_check -= 1 # check to make sure the eigenvector is ok if (i == 0 or self.eigenval <= 0 or not self.check_negative or (negative_before_check > 0 and not self.demand_initial_negative_vec)): self._saveState(coords) self.reduce_step = 0 else: self.npositive += 1 if self.npositive > self.npositive_max: logger.warning( "positive eigenvalue found too many times. ending %s", self.npositive) res.message.append( "positive eigenvalue found too many times %d" % self.npositive ) break if self.verbosity > 2: logger.info("the eigenvalue turned positive. %s %s", self.eigenval, "Resetting last good values and taking smaller steps") coords = self._resetState() self.reduce_step += 1 # step uphill along the direction of the lowest eigenvector coords = self._stepUphill(coords) # minimize the coordinates in the space perpendicular to the lowest eigenvector tangent_ret = self._minimizeTangentSpace(coords, energy=self.get_energy(), gradient=self.get_gradient()) coords = tangent_ret.coords tangentrms = tangent_ret.rms # check if we are done and print some stuff # self._compute_gradients(coords) # this is unnecessary E = self.get_energy() grad = self.get_gradient() rms = np.linalg.norm(grad) * self.rmsnorm gradpar = np.dot(grad, self.eigenvec) / np.linalg.norm(self.eigenvec) if self.iprint > 0: if (i+1) % self.iprint == 0: ostring = "findTS: %3d E %9g rms %8g eigenvalue %9g rms perp %8g grad par %9g overlap %g" % ( i, E, rms, self.eigenval, tangentrms, gradpar, overlap) extra = " Evec search: %d rms %g" % (self.leig_result.nfev, self.leig_result.rms) extra += " Tverse search: %d step %g" % (self.tangent_result.nfev, self.tangent_move_step) extra += " Uphill step:%g" % (self.uphill_step_size,) logger.info("%s %s", ostring, extra) if callable(self.event): self.event(energy=E, coords=coords, rms=rms, eigenval=self.eigenval, stepnum=i) if rms < self.tol: break if self.nfail >= self.nfail_max: logger.warning("stopping findTransitionState. too many failures in eigenvector search %s", self.nfail) res.message.append( "too many failures in eigenvector search %d" % self.nfail ) break if i == 0 and self.eigenval > 0.: if self.verbosity > 1: logger.warning("initial eigenvalue is positive - increase NEB spring constant?") if self.demand_initial_negative_vec: logger.warning(" aborting transition state search") res.message.append( "initial eigenvalue is positive %f" % self.eigenval ) break # done. do one last eigenvector search because coords may have changed self._getLowestEigenVector(coords, i) # print some data if self.verbosity > 0 or self.iprint > 0: logger.info("findTransitionState done: %s %s %s %s %s", i, E, rms, "eigenvalue", self.eigenval) success = True # check if results make sense if self.eigenval >= 0.: if self.verbosity > 2: logger.info( "warning: transition state is ending with positive eigenvalue %s", self.eigenval) success = False if rms > self.tol: if self.verbosity > 2: logger.info("warning: transition state search appears to have failed: rms %s", rms) success = False if i >= self.nsteps: res.message.append( "maximum iterations reached %d" % i ) # update nfev with the number of calls from the transverse walker if self._transverse_walker is not None: twres = self._transverse_walker.get_result() self.nfev += twres.nfev #return results res.coords = coords res.energy = E res.eigenval = self.eigenval res.eigenvec = self.eigenvec res.grad = grad res.rms = rms res.nsteps = i res.success = success res.nfev = self.nfev return res