Beispiel #1
0
    def move(self, ro, bests):
        """Move atoms by a random step."""
        atoms = self.atoms
        velocity = copy.deepcopy(self.velocity)


        best_to_use = bests[-1]
        best_dist = 1e32
        for i in bests:
            d = i.get_bcm() - self.get_bcm()
            di = np.sqrt(np.vdot(d,d))
            if(di<best_dist):
                best_to_use = i
                best_dist = di

        print "using best: ", best_to_use.get_bcm()
        # PSO heuristic
        for i in range(len(ro)):
            for j in range(3):
                velocity[i][j] = self.inertia_weight*velocity[i][j] + random.uniform(0,2)*(self.rmin[i][j]-ro[i][j]) + random.uniform(0,2)*(best_to_use.positions[i][j]-ro[i][j])

        rn = ro + velocity
        rn = self.push_apart(rn)
        atoms.set_positions(rn)
        En = self.get_energy(rn)
        cm = atoms.get_center_of_mass()
        atoms.translate(self.cm - cm)

        rn = atoms.get_positions()
        world.broadcast(rn, 0)

        atoms.set_positions(rn)
        return En,atoms.get_positions(),velocity
    def _startup(self):
        """Initiates a run, and determines if running from previous data or
        a fresh run."""

        status = np.array(-1.)
        exists = self._read_minima()
        if world.rank == 0:
            if not exists:
                # Fresh run with new minima file.
                status = np.array(0.)
            elif not os.path.exists(self._logfile):
                # Fresh run with existing or shared minima file.
                status = np.array(1.)
            else:
                # Must be resuming from within a working directory.
                status = np.array(2.)
        world.barrier()
        world.broadcast(status, 0)

        if status == 2.:
            self._resume()
        else:
            self._counter = 0
            self._log('init')
            self._log('msg', 'Performing initial optimization.')
            if status == 1.:
                self._log(
                    'msg', 'Using existing minima file with %i prior '
                    'minima: %s' % (len(self._minima), self._minima_traj))
            self._optimize()
            self._check_results()
            self._counter += 1
Beispiel #3
0
    def _startup(self):
        """Initiates a run, and determines if running from previous data or
        a fresh run."""

        status = np.array(-1.)
        exists = self._read_minima()
        if rank == 0:
            if not exists:
                # Fresh run with new minima file.
                status = np.array(0.)
            elif not os.path.exists(self._logfile):
                # Fresh run with existing or shared minima file.
                status = np.array(1.)
            else:
                # Must be resuming from within a working directory.
                status = np.array(2.)
        world.barrier()
        world.broadcast(status, 0)

        if status == 2.:
            self._resume()
        else:
            self._counter = 0
            self._log('init')
            self._log('msg', 'Performing initial optimization.')
            if status == 1.:
                self._log('msg', 'Using existing minima file with %i prior '
                          'minima: %s' % (len(self._minima),
                                          self._minima_traj))
            self._optimize()
            self._check_results()
            self._counter += 1
Beispiel #4
0
    def move(self, step, ro, distribution):
        """Move atoms by a random step or MD"""
        # random move (BH move)
        if distribution != 'molecular_dynamics':

            if distribution == 'uniform':
                disp = np.random.uniform(-self.dr, self.dr,
                                         (len(self.atoms), 3))

            elif distribution == 'gaussian':
                disp = np.random.normal(0, self.dr, size=(len(self.atoms), 3))

            elif distribution == 'linear':
                distgeo = self.get_dist_geo_center()
                disp = np.zeros(np.shape(self.atoms.get_positions()))
                for i in range(len(disp)):
                    maxdist = self.dr * distgeo[i]
                    disp[i] = np.random.uniform(-maxdist, maxdist, 3)

            elif distribution == 'quadratic':
                distgeo = self.get_dist_geo_center()
                disp = np.zeros(np.shape(self.atoms.get_positions()))
                for i in range(len(disp)):
                    maxdist = self.dr * distgeo[i] * distgeo[i]
                    disp[i] = np.random.uniform(-maxdist, maxdist, 3)

            # there is a typo in distribution or jump distribution
            else:
                print 'distribution flag has typo'
                sys.exit()
                disp = np.random.uniform(-1 * self.dr, self.dr,
                                         (len(self.atoms), 3))

            # update atoms positions by the random move
            rn = ro + disp
            rn = self.push_apart(rn)
            self.atoms.set_positions(rn)

            # refix the center of mass after random move
            if self.cm is not None:
                cm = self.atoms.get_center_of_mass()
                self.atoms.translate(self.cm - cm)

        # MD move (MH move)
        else:
            N = None
            # use the dimer method to create an initial velocity vector for MD
            if self.dimer_method:
                dimer = ModifiedDimer()
                N = dimer(self.atoms, self.dimer_a, self.dimer_d,
                          self.dimer_steps)
            self._molecular_dynamics(step, N)

        rn = self.atoms.get_positions()
        world.broadcast(rn, 0)
        return rn
Beispiel #5
0
    def calculate_energies_and_forces(self, all=False):
        """Calculate and store the forces and energies for the band."""
        images = self.images

        if all:
            self.forces['real'][0] = images[0].get_forces()
            self.forces['real'][-1] = images[-1].get_forces()
            if not self.integrate_forces:
                self.energies[0] = images[0].get_potential_energy()
                self.energies[-1] = images[-1].get_potential_energy()

        if not self.parallel:
            # Do all images - one at a time:
            for i in range(1, self.nimages - 1):
                self.calculate_image_forces(i)

            for i in range(1, self.nimages - 1):
                self.calculate_image_energies(i)
        else:
            # Parallelize over images: first the forces ...
            i = rank * (self.nimages - 2) // size + 1
            try:
                self.calculate_image_forces(i)
            except:
                # Make sure other images also fail:
                error = world.sum(1.0)
                raise
            else:
                error = world.sum(0.0)
                if error:
                    raise RuntimeError('Parallel NEB failed')
            for i in range(1, self.nimages - 1):
                root = (i - 1) * size // (self.nimages - 2)
                world.broadcast(self.forces['real'][i], root)

            # ... and now the energies
            try:
                self.calculate_image_energies(i)
            except:
                # Make sure other images also fail:
                error = world.sum(1.0)
                raise
            else:
                error = world.sum(0.0)
                if error:
                    raise RuntimeError('Parallel NEB failed')
            for i in range(1, self.nimages - 1):
                root = (i - 1) * size // (self.nimages - 2)
                world.broadcast(self.energies[i : i + 1], root)

        if all and self.integrate_forces:
            # fill in the first and last energies by force integration
            self.energies[0] = 0.
            self.calculate_image_energies(len(self.images)-1)
Beispiel #6
0
    def move(self, ro):
        """Move atoms by a random step."""
        atoms = self.atoms
        disp = np.zeros(np.shape(atoms.get_positions()))
        while np.alltrue(disp == np.zeros(np.shape(atoms.get_positions()))):
            if self.distribution == 'uniform':
                disp = np.random.uniform(-self.dr, self.dr, (len(atoms), 3))
            elif self.distribution == 'gaussian':
                disp = np.random.normal(0, self.dr, size=(len(atoms), 3))
            elif self.distribution == 'linear':
                distgeo = self.get_dist_geo_center()
                disp = np.zeros(np.shape(atoms.get_positions()))
                for i in range(len(disp)):
                    maxdist = self.dr * distgeo[i]
                    #    disp[i] = np.random.normal(0,maxdist,3)
                    disp[i] = np.random.uniform(-maxdist, maxdist, 3)
            elif self.distribution == 'quadratic':
                distgeo = self.get_dist_geo_center()
                disp = np.zeros(np.shape(atoms.get_positions()))
                for i in range(len(disp)):
                    maxdist = self.dr * distgeo[i] * distgeo[i]
                    #    disp[i] = np.random.normal(0,maxdist,3)
                    disp[i] = np.random.uniform(-maxdist, maxdist, 3)
            else:
                disp = np.random.uniform(-1 * self.dr, self.dr,
                                         (len(atoms), 3))

            #Lei: set all other disp to zero except those selected to move
            #     the number of atoms that can be moved is defined by int(active_ratio * len(atoms))
            if self.active_ratio is not None:
                fix_space = len(atoms) - int(self.active_ratio * len(atoms))
                fix_atoms = random.sample(range(len(atoms)), fix_space)
                for i in range(len(fix_atoms)):
                    disp[fix_atoms[i]] = (0.0, 0.0, 0.0)

        #Lei: suppose to only update 'ro' with local minimum when accept == true

    #    if self.significant_structure == True:
    #        rn = self.local_min_pos + disp
    #    if self.significant_structure2 == True:
    #        ro,reng = self.get_minimum()
    #        rn = ro + disp
    #    else:
        rn = ro + disp
        rn = self.push_apart(rn)
        atoms.set_positions(rn)
        if self.cm is not None:
            cm = atoms.get_center_of_mass()
            atoms.translate(self.cm - cm)
        rn = atoms.get_positions()
        world.broadcast(rn, 0)
        atoms.set_positions(rn)
        return atoms.get_positions()
Beispiel #7
0
 def move(self, ro):
     """Move atoms by a random step."""
     atoms = self.atoms
     # displace coordinates
     disp = np.random.uniform(-1., 1., (len(atoms), 3))
     rn = ro + self.dr * disp
     atoms.set_positions(rn)
     if self.cm is not None:
         cm = atoms.get_center_of_mass()
         atoms.translate(self.cm - cm)
     rn = atoms.get_positions()
     world.broadcast(rn, 0)
     atoms.set_positions(rn)
     return atoms.get_positions()
Beispiel #8
0
 def move(self, ro):
     """Move atoms by a random step."""
     atoms = self.atoms
     # displace coordinates
     disp = np.random.uniform(-1., 1., (len(atoms), 3))
     rn = ro + self.dr * disp
     atoms.set_positions(rn)
     if self.cm is not None:
         cm = atoms.get_center_of_mass()
         atoms.translate(self.cm - cm)
     rn = atoms.get_positions()
     world.broadcast(rn, 0)
     atoms.set_positions(rn)
     return atoms.get_positions()
Beispiel #9
0
    def get_forces(self):
        images = self.images

        forces = np.empty(((self.nimages - 2), self.natoms, 3))

        energies = np.empty(self.nimages - 2)

        if not self.parallel:
            # Do all images - one at a time:
            for i in range(1, self.nimages - 1):
                energies[i - 1] = images[i].get_potential_energy()
                forces[i - 1] = images[i].get_forces()
        else:
            # Parallelize over images:
            i = rank * (self.nimages - 2) // size + 1
            energies[i - 1] = images[i].get_potential_energy()
            forces[i - 1] = images[i].get_forces()
            for i in range(1, self.nimages - 1):
                root = (i - 1) * size // (self.nimages - 2)
                world.broadcast(energies[i - 1:i], root)
                world.broadcast(forces[i - 1], root)

        imax = 1 + np.argsort(energies)[-1]
        self.emax = energies[imax - 1]
        
        tangent1 = images[1].get_positions() - images[0].get_positions()
        for i in range(1, self.nimages - 1):
            tangent2 = (images[i + 1].get_positions() -
                        images[i].get_positions())
            if i < imax:
                tangent = tangent2
            elif i > imax:
                tangent = tangent1
            else:
                tangent = tangent1 + tangent2
                
            tt = np.vdot(tangent, tangent)
            f = forces[i - 1]
            ft = np.vdot(f, tangent)
            if i == imax and self.climb:
                f -= 2 * ft / tt * tangent
            else:
                f -= ft / tt * tangent
                f -= (np.vdot(tangent1 - tangent2, tangent) *
                      self.k / tt * tangent)
                
            tangent1 = tangent2

        return forces.reshape((-1, 3))
Beispiel #10
0
    def move(self, ro):
        """Move atoms by a random step."""
        atoms = self.atoms
        if self.distribution == 'uniform':
            disp = np.random.uniform(-self.dr, self.dr, (len(atoms), 3))
        elif self.distribution == 'gaussian':
            disp = np.random.normal(0,self.dr,size=(len(atoms), 3))
        elif self.distribution == 'linear':
            distgeo = self.get_dist_geo_center()
            disp = np.zeros(np.shape(atoms.get_positions()))
            for i in range(len(disp)):
                maxdist = self.dr*distgeo[i]
            #    disp[i] = np.random.normal(0,maxdist,3)
                disp[i] = np.random.uniform(-maxdist,maxdist,3)
        elif self.distribution == 'quadratic':
            distgeo = self.get_dist_geo_center()
            disp = np.zeros(np.shape(atoms.get_positions()))
            for i in range(len(disp)):
                maxdist = self.dr*distgeo[i]*distgeo[i]
            #    disp[i] = np.random.normal(0,maxdist,3)
                disp[i] = np.random.uniform(-maxdist,maxdist,3)
### EDIT CODE FOR PROBLEM 5 HERE ###########################################
        elif self.distribution == 'your_move':
            ## an example of distribution to pick is as follows: a fixed size move
            arr = np.random.rand(len(atoms), 3)
            for y in range(len(atoms)):
                for x in range(3):
                    arr[y][x] = self.my_distribution(arr[y][x])
            disp = self.dr * arr
############################################################################
        else:
            disp = np.random.uniform(-1*self.dr, self.dr, (len(atoms), 3))
        if self.significant_structure == True:
            ro,reng = self.get_minimum()
            rn = ro +disp
        else:
            rn = ro + disp
        rn = self.push_apart(rn)
        atoms.set_positions(rn)
        if self.cm is not None:
            cm = atoms.get_center_of_mass()
            atoms.translate(self.cm - cm)
        rn = atoms.get_positions()
        world.broadcast(rn, 0)
        atoms.set_positions(rn)
        return atoms.get_positions()
Beispiel #11
0
    def move_del(self, ro, vectors):
        """Displace atoms by randomly selected delocalized 'normal mode' """
        atoms = self.atoms[self.adsorbate[0]:self.adsorbate[1]]
        atms = self.atoms
        numvec = len(vectors)
        numcomb = self.numdelmodes
        while True:
            disp = np.zeros((len(ro), 3))
            start = 0  #find way for start to be number of stretches
            if self.constr:
                mm = atoms.get_masses()
                x0 = atoms.get_positions().flatten()
                vv = VCG(atoms.get_chemical_symbols(), masses=mm)
                start = len(
                    icSystem(vv(x0), len(atoms), masses=mm,
                             xyz=x0).getStretchBendTorsOop()[0][0])
            if numcomb > len(range(start, numvec)):
                numcomb = len(range(start, numvec))
            w = np.random.choice(range(start, numvec),
                                 size=numcomb,
                                 replace=False)
            for i in w:
                disp[self.adsorbate[0]:(
                    self.adsorbate[1]), :3] += vectors[i] * np.random.uniform(
                        -1., 1.)  #this is important if there is an adsorbate.
            disp /= np.max(np.abs(disp))
            #from here on, everything is JUST COPIED from self.move(); should be sane
            rn = ro + self.dr * disp
            atms.set_positions(rn)

            if self.cm is not None:
                cm = atms.get_center_of_mass()
                atms.translate(self.cm - cm)
            rn = atms.get_positions()
            world.broadcast(rn, 0)
            atms.set_positions(rn)
            if self.check_distances(atoms):
                break
            else:
                print 'HIIIIGHWAY TO THE DANGERZONE!'
                atoms.write('Maverick.xyz')
        return atms.get_positions()
Beispiel #12
0
    def get_forces(self):
        """Evaluate and return the forces."""

        if self.parallel and self.images[1].minmode_init:
            propagate_initial_values = True
        else:
            propagate_initial_values = False

        # Update the clean forces and energies
        self.calculate_energies_and_forces()

        if self.parallel and propagate_initial_values:
            for i in range(1, self.nimages - 1):
                if self.images[i].eigenmodes is None:
                    self.images[i].eigenmodes = [np.zeros(self.images[i].get_positions().shape)]
                self.images[i].minmode_init = False
                self.images[i].rotation_required = True
                self.images[i].check_atoms = self.images[i].atoms.copy()

                root = (i - 1) * size // (self.nimages - 2)
                world.broadcast(self.images[i].eigenmodes[0], root)

        # Update the highest energy image
        self.imax = 1 + np.argsort(self.energies[1:-1])[-1]
        self.emax = self.energies[self.imax]
        # BUG: self.imax can be an endimage.

        # Calculate the tangents of all the images
        self.update_tangents()

        # IDEA: If f_c_perp is small force dimer rotation?

        # Calculate the modes
        self.calculate_eigenmodes()

        # Prjoect the forces for each image
        self.invert_eigenmode_forces()
        self.project_forces(sort = 'dimer')
        if self.plot_devplot:
            self.plot_pseudo_3d_pes()
        self.control.increment_counter('optcount')
        return self.forces['neb'][1:self.nimages-1].reshape((-1, 3))
Beispiel #13
0
 def move(self, ro):
     """Move atoms by a random step."""
     atoms = self.atoms
     # displace coordinates
     disp = np.random.uniform(-1., 1., (len(atoms), 3))
     rn = ro + self.dr * disp
     # exchange two atoms
     from numpy.random import randint
     ind = randint(0,12,  size=2)
     postemp = rn[ind[0]].copy()
     rn[ind[0]] = rn[ind[1]]
     rn[ind[1]] = postemp
     #
     atoms.set_positions(rn)
     if self.cm is not None:
         cm = atoms.get_center_of_mass()
         atoms.translate(self.cm - cm)
     rn = atoms.get_positions()
     world.broadcast(rn, 0)
     atoms.set_positions(rn)
     return atoms.get_positions()
Beispiel #14
0
    def move(self, ro, bests):
        """Move atoms by a random step."""
        atoms = self.atoms
        velocity = copy.deepcopy(self.velocity)

        # PSO heuristic
        for i in range(len(ro)):
            for j in range(3):
                velocity[i][j] = self.inertia_weight*velocity[i][j] + random.uniform(0,2)*(self.rmin[i][j]-ro[i][j]) + random.uniform(0,2)*(bests[-1].positions[i][j]-ro[i][j])

        rn = ro + velocity
        rn = self.push_apart(rn)
        atoms.set_positions(rn)
        En = self.get_energy(rn)
        cm = atoms.get_center_of_mass()
        atoms.translate(self.cm - cm)

        rn = atoms.get_positions()
        world.broadcast(rn, 0)

        atoms.set_positions(rn)
        return En,atoms.get_positions(),velocity
Beispiel #15
0
    def calculate_eigenmodes(self):
        if self.parallel:
            i = rank * (self.nimages - 2) // size + 1
            try:
                self.calculate_image_eigenmode(i)
            except:
                # Make sure other images also fail:
                error = world.sum(1.0)
                raise
            else:
                error = world.sum(0.0)
                if error:
                    raise RuntimeError('Parallel ERM failed during eigenmode calculations.')
            for i in range(1, self.nimages - 1):
                if self.images[i].eigenmodes is None:
                    self.images[i].eigenmodes = [np.zeros(self.images[i].get_positions().shape)]
                root = (i - 1) * size // (self.nimages - 2)
                world.broadcast(self.images[i].eigenmodes[0], root)
#                world.broadcast(self.images[i : i + 1].curvatures, root)
        else:
            for i in range(1, self.nimages - 1):
                self.calculate_image_eigenmode(i)
Beispiel #16
0
 def move(self, ro):
     """Move atoms by a random step."""
     atoms = self.atoms
     # displace coordinates
     #disp = np.random.uniform(-1., 1., (len(atoms), 3))
     disp = np.random.uniform(-1.0, 1.0, (int(len(atoms) / 3), 3))
     final_dis = []
     for i in range(int(len(atoms) / 3)):
         d = disp[i].tolist()
         for i in range(3):
             final_dis.append(d)
     disp = np.array(final_dis)
     rn = ro + self.dr * disp
     atoms.set_positions(rn)
     if self.cm is not None:
         cm = atoms.get_center_of_mass()
         atoms.translate(self.cm - cm)
         print('ajusted')
     rn = atoms.get_positions()
     world.broadcast(rn, 0)
     atoms.set_positions(rn)
     return atoms.get_positions()
Beispiel #17
0
    def calculate_energies_and_forces(self):
        images = self.images

        if not self.parallel:
            # Do all images - one at a time:
            for i in range(1, self.nimages - 1):
                self.calculate_image_energies_and_forces(i)
        else:
            # Parallelize over images:
            i = rank * (self.nimages - 2) // size + 1
            try:
                self.calculate_image_energies_and_forces(i)
            except:
                # Make sure other images also fail:
                error = world.sum(1.0)
                raise
            else:
                error = world.sum(0.0)
                if error:
                    raise RuntimeError('Parallel NEB failed')
            for i in range(1, self.nimages - 1):
                root = (i - 1) * size // (self.nimages - 2)
                world.broadcast(self.energies[i : i + 1], root)
                world.broadcast(self.forces['real'][i], root)
Beispiel #18
0
def test_attach_randomly():
    """Attach two molecules in random orientation."""
    m1 = molecule('C6H6')
    m2 = molecule('CF4')
    distance = 2.5

    if world.size > 1:
        "Check that the coordinates are correctly distributed from master."
        rng = np.random.RandomState(world.rank)  # ensure different seed
        atoms = attach_randomly_and_broadcast(m1, m2, distance, rng)

        p0 = 1. * atoms[-1].position
        world.broadcast(p0, 0)
        for i in range(1, world.size):
            pi = 1. * atoms[-1].position
            world.broadcast(pi, i)
            assert pi == pytest.approx(p0, 1e-8)

        "Check that every core has its own structure"
        rng = np.random.RandomState(world.rank)  # ensure different seed
        atoms = attach_randomly(m1, m2, distance, rng)
        p0 = 1. * atoms[-1].position
        world.broadcast(p0, 0)
        for i in range(1, world.size):
            pi = 1. * atoms[-1].position
            world.broadcast(pi, i)
            assert pi != pytest.approx(p0, 1e-8)

    rng = np.random.RandomState(42)  # ensure the same seed
    pos2_ac = np.zeros((5, 3))
    N = 25
    for i in range(N):
        atoms = attach_randomly(m1, m2, distance, rng=rng)
        pos2_ac += atoms.get_positions()[12:, :]
    # the average position should be "zero" approximately
    assert (np.abs(pos2_ac / N) <= 1).all()
Beispiel #19
0
    def move(self, ro, bests):
        """Move atoms by a random step."""
        atoms = self.atoms
        velocity = copy.deepcopy(self.velocity)

        do_pso = True
        if self.method == 'firefly':
            do_pso = False
        elif self.method == 'PSO_split':
            best_to_use = bests[-1]
            best_dist = 1e32
            for i in bests:
                d = i.get_bcm() - self.get_bcm()
                di = np.sqrt(np.vdot(d,d))
                if(di<best_dist):
                    best_to_use = i
                    best_dist = di

            do_pso = True
        else:
            do_pso = True
            best_to_use = bests[-1]

        # PSO heuristic
        if (not do_pso):
            r_arr = [None] * len(bests)
            r_sum = 0
            pe_sum = 0
            for i in range(len(bests)):
                    d = self.get_bcm() - bests[i].get_bcm()
                    r_arr[i] = np.sqrt(np.vdot(d,d))
                    r_sum += r_arr[i]
                    pe_sum += bests[i].get_energy()
            r_mean = r_sum / len(bests)
            pe_mean = abs(pe_sum / len(bests))
            denom = math.sqrt(r_mean*pe_mean)
            attract_arr = [None] * len(bests)
            for i in range(len(bests)):
                    numer = bests[i].get_energy() * r_arr[i]
                    numer *= numer
                    attract_arr[i] = math.e**(-1*numer/denom)
            sort_attract = sorted(attract_arr)

            velocity = self.inertia_weight*velocity
            E = np.random.normal(1,.01*min(15,sort_attract[-2]/max(0.0001,sort_attract[-1])), size=(len(atoms),3))
            for i in range(len(bests)):
                    velocity += attract_arr[i]*(bests[i].positions-ro)*E/sort_attract[-1]
        else:
            print "using best: ", best_to_use.get_bcm()
            for i in range(len(ro)):
                for j in range(3):
                    velocity[i][j] = self.inertia_weight*velocity[i][j] + random.uniform(0,2)*(self.rmin[i][j]-ro[i][j]) + random.uniform(0,2)*(best_to_use.positions[i][j]-ro[i][j])

        rn = ro + velocity
        rn = self.push_apart(rn)
        atoms.set_positions(rn)
        En = self.get_energy(rn)
        cm = atoms.get_center_of_mass()
        atoms.translate(self.cm - cm)

        rn = atoms.get_positions()
        world.broadcast(rn, 0)

        atoms.set_positions(rn)
        return En,atoms.get_positions(),velocity