def __init__(self, coords, pot, eigenvec0=None, orthogZeroEigs=0, dx=1e-6, first_order=True, gradient=None, **minimizer_kwargs): self.minimizer_kwargs = minimizer_kwargs if eigenvec0 is None: # this random vector should be distributed uniformly on a hypersphere. eigenvec0 = rotations.vec_random_ndim(coords.shape) eigenvec0 = eigenvec0 / np.linalg.norm(eigenvec0) # change some default in the minimizer unless manually set if "nsteps" not in minimizer_kwargs: minimizer_kwargs["nsteps"] = 500 if "logger" not in minimizer_kwargs: minimizer_kwargs["logger"] = logging.getLogger( "pele.connect.findTS.leig_quench") self.eigpot = LowestEigPot(coords, pot, orthogZeroEigs=orthogZeroEigs, dx=dx, gradient=gradient, first_order=first_order) self.minimizer = MYLBFGS(eigenvec0, self.eigpot, rel_energy=True, **self.minimizer_kwargs)
def setUp(self): natoms = 18 self.system = LJCluster(natoms) self.pot = self.system.get_potential() self.evec = vec_random_ndim(3*natoms) self.evec /= np.linalg.norm(self.evec) self.x = self.system.get_random_configuration()
def makeplot(): # pragma: no cover atom1 = np.zeros(3) rcut = 2.5 potAA = BLJCut(2, 0, rcut=rcut) potAB = BLJCut(2, 1, rcut=rcut) potBB = BLJCut(2, 2, rcut=rcut) eAA = [] eAB = [] eBB = [] v = vec_random_ndim(3) v /= np.linalg.norm(v) rlist = np.arange(.85, 3, .01) for r in rlist: atom2 = atom1 + r * v x = np.array(list(atom1) + list(atom2)) eAA.append(potAA.getEnergy(x)) eAB.append(potAB.getEnergy(x)) eBB.append(potBB.getEnergy(x)) import matplotlib.pyplot as plt plt.plot(rlist, eAA) plt.plot(rlist, eAB) plt.plot(rlist, eBB) plt.show()
def setUp(self): np.random.seed(1) self.rcut = 2.5 self.atom1 = np.random.uniform(-1, 1, [3]) v = vec_random_ndim(3) v /= np.linalg.norm(v) self.v = v
def __init__(self, coords, potential, eigenvec0=None, rotational_steps=20, translational_steps=10, maxiter=500, leig_kwargs=None, translator_kwargs=None, dimer=True, ): coords = coords.copy() self.rotational_steps = rotational_steps self.translational_steps = translational_steps self.maxiter = maxiter self.iter_number = 0 # check the keyword dictionaries if translator_kwargs is None: translator_kwargs = {} if leig_kwargs is None: leig_kwargs = {} # set up the initial guess for the eigenvector if eigenvec0 is None: eigenvec0 = rotations.vec_random_ndim(coords.shape) eigenvec0 /= np.linalg.norm(eigenvec0) assert coords.shape == eigenvec0.shape # set up the object that will maintain the rotation of the dimer self.rotator = FindLowestEigenVector(coords, potential, eigenvec0=eigenvec0, **leig_kwargs) # set up the object that will translate the dimer if dimer: self.translator = _DimerTranslator(coords, potential, eigenvec0, **translator_kwargs) else: self.translator = _HybridEigenvectorWalker(coords, potential, eigenvec0, **translator_kwargs)
def minima_from_ts(pot, xt, n=None, quench=None, stepmin=0.01, **kwargs): """ step off either side of a transition state and quench to find the minima Parameters ---------- pot : potential object xt : array transition state coords n : array direction to step off quench : callable routine to use to do the quenching kwargs : dict parameters to pass to determine_pushoff """ if n is None: # if no direction is given, choose random direction n = vec_random_ndim(xt.size) if quench: quenchRoutine = lambda coords: quench(coords, pot=pot, **kwargs) else: quenchRoutine = lambda coords: mylbfgs(coords, pot=pot, **kwargs) x1 = determine_pushoff(pot, xt, n, stepmin=stepmin, **kwargs) x2 = determine_pushoff(pot, xt, -n, stepmin=stepmin, **kwargs) minimum1 = quench(x1) minimum2 = quench(x2) return minimum1, minimum2
def setUp(self): natoms = 18 self.system = LJCluster(natoms) self.pot = self.system.get_potential() self.evec = vec_random_ndim(3 * natoms) self.evec /= np.linalg.norm(self.evec) self.x = self.system.get_random_configuration()
def minima_from_ts(pot, xt, n=None, quench=None, stepmin=0.01, **kwargs): """ step off either side of a transition state and quench to find the minima Parameters ---------- pot : potential object xt : array transition state coords n : array direction to step off quench : callable routine to use to do the quenching kwargs : dict parameters to pass to determine_pushoff """ if n is None: # if no direction is given, choose random direction n = vec_random_ndim(xt.size) if quench is None: quench = lambda coords: mylbfgs(coords, pot) x1 = determine_pushoff(pot, xt, n, stepmin=stepmin, **kwargs) x2 = determine_pushoff(pot, xt, -n, stepmin=stepmin, **kwargs) minimum1 = quench(x1) minimum2 = quench(x2) return minimum1, minimum2
def __init__( self, coords, pot, eigenvec0=None, orthogZeroEigs=0, dx=1e-6, first_order=True, gradient=None, **minimizer_kwargs ): self.minimizer_kwargs = minimizer_kwargs if eigenvec0 is None: # this random vector should be distributed uniformly on a hypersphere. eigenvec0 = rotations.vec_random_ndim(coords.shape) eigenvec0 = eigenvec0 / np.linalg.norm(eigenvec0) # change some default in the minimizer unless manually set if "nsteps" not in minimizer_kwargs: minimizer_kwargs["nsteps"] = 500 if "logger" not in minimizer_kwargs: minimizer_kwargs["logger"] = logging.getLogger("pele.connect.findTS.leig_quench") self.eigpot = LowestEigPot( coords, pot, orthogZeroEigs=orthogZeroEigs, dx=dx, gradient=gradient, first_order=first_order ) self.minimizer = MYLBFGS(eigenvec0, self.eigpot, rel_energy=True, **self.minimizer_kwargs)
def test(self): x = self.system.get_random_configuration() evec = vec_random_ndim(x.size) evec /= np.linalg.norm(evec) opt = _TransverseWalker(x, self.pot, evec) ret = opt.run(10) self.assertEqual(ret.nfev, self.pot.nfev) self.assertGreater(ret.nfev, 0)
def sample_coords_from_basin(self, m, Emax): """Returns a configuration with energy less than Emax sampled uniformly from the basin of a minimum this assumes the harmonic approximation and is exact in the harmonic approximation Parameters ---------- m : Minimum object normal mode frequencies and associated eigenvectors Emax : float energy upper bound k : integer number of degrees of freedom Notes ----- in real system, even ones that fit quite well to the harmonic approximation this very often generates configurations with energy greater than Emax. """ nm = m.normal_modes evals = nm.freqs vectors = nm.vectors k = self.k nzero = len(evals) - k # get uniform random k dimensional unit vector f = vec_random_ndim(k) # the target increase in energy is sampled from a power law distribution dE_target = np.random.power(k - 1) * (Emax - m.energy) # scale f according to dE_target f *= np.sqrt(2.0 * dE_target) # TODO check prefactor # create the random displacement vector dx = np.zeros(m.coords.shape) for i in range(k): if evals[i + nzero] > 1e-4: dx += f[i] * vectors[:, i + nzero] / np.sqrt(evals[i + nzero]) return m.coords + dx
def sample_coords_from_basin(self, m, Emax): """Returns a configuration with energy less than Emax sampled uniformly from the basin of a minimum this assumes the harmonic approximation and is exact in the harmonic approximation Parameters ---------- m : Minimum object normal mode frequencies and associated eigenvectors Emax : float energy upper bound k : integer number of degrees of freedom Notes ----- in real system, even ones that fit quite well to the harmonic approximation this very often generates configurations with energy greater than Emax. """ nm = m.normal_modes evals = nm.freqs vectors = nm.vectors k = self.k nzero = len(evals) - k # get uniform random k dimensional unit vector f = vec_random_ndim(k) # the target increase in energy is sampled from a power law distribution dE_target = np.random.power(k - 1) * (Emax - m.energy) # scale f according to dE_target f *= np.sqrt(2. * dE_target) #TODO check prefactor # create the random displacement vector dx = np.zeros(m.coords.shape) for i in range(k): if evals[i + nzero] > 1e-4: dx += f[i] * vectors[:, i + nzero] / np.sqrt(evals[i + nzero]) return m.coords + dx