Exemplo n.º 1
0
 def _unique_coords(self, coords_in, magmoms_in=None):
     """
     Generate unique coordinates using coord and symmetry positions
     and also their corresponding magnetic moments, if supplied.
     """
     coords = []
     if magmoms_in:
         magmoms = []
         magmoms_in = [Magmom(magmom) for magmom in magmoms_in]
         if len(magmoms_in) != len(coords_in):
             raise ValueError
         for tmp_coord, tmp_magmom in zip(coords_in, magmoms_in):
             for op in self.symmetry_operations:
                 coord = op.operate(tmp_coord)
                 coord = np.array([i - math.floor(i) for i in coord])
                 if isinstance(op, MagSymmOp):
                     magmom = Magmom(op.operate_magmom(tmp_magmom.moment))
                 else:
                     magmom = tmp_magmom
                 if not in_coord_list_pbc(
                         coords, coord, atol=self._site_tolerance):
                     coords.append(coord)
                     magmoms.append(magmom)
         return coords, magmoms
     else:
         for tmp_coord in coords_in:
             for op in self.symmetry_operations:
                 coord = op.operate(tmp_coord)
                 coord = np.array([i - math.floor(i) for i in coord])
                 if not in_coord_list_pbc(
                         coords, coord, atol=self._site_tolerance):
                     coords.append(coord)
         return coords, [Magmom(0)] * len(coords)  # return dummy magmoms
Exemplo n.º 2
0
 def test_in_coord_list_pbc(self):
     coords = [[0, 0, 0], [0.5, 0.5, 0.5]]
     test_coord = [0.1, 0.1, 0.1]
     self.assertFalse(in_coord_list_pbc(coords, test_coord))
     self.assertTrue(in_coord_list_pbc(coords, test_coord, atol=0.15))
     test_coord = [0.99, 0.99, 0.99]
     self.assertFalse(in_coord_list_pbc(coords, test_coord, atol=0.01))
Exemplo n.º 3
0
    def symm_reduce(self, coords_set, threshold=1e-6):
        """
        Reduces the set of adsorbate sites by finding removing
        symmetrically equivalent duplicates

        Args:
            coords_set: coordinate set in cartesian coordinates
            threshold: tolerance for distance equivalence, used
                as input to in_coord_list_pbc for dupl. checking
        """
        surf_sg = SpacegroupAnalyzer(self.slab, 0.1)
        symm_ops = surf_sg.get_symmetry_operations()
        unique_coords = []
        # Convert to fractional
        coords_set = [
            cart_to_frac(self.slab.lattice, coords) for coords in coords_set
        ]
        for coords in coords_set:
            incoord = False
            for op in symm_ops:
                if in_coord_list_pbc(unique_coords,
                                     op.operate(coords),
                                     atol=threshold):
                    incoord = True
                    break
            if not incoord:
                unique_coords += [coords]
        # convert back to cartesian
        return [
            frac_to_cart(self.slab.lattice, coords) for coords in unique_coords
        ]
Exemplo n.º 4
0
    def symm_reduce(self, coords_set, threshold = 1e-6):
        """
        Reduces the set of adsorbate sites by finding removing
        symmetrically equivalent duplicates

        Args:
            coords_set: coordinate set in cartesian coordinates
            threshold: tolerance for distance equivalence, used
                as input to in_coord_list_pbc for dupl. checking
        """
        surf_sg = SpacegroupAnalyzer(self.slab, 0.1)
        symm_ops = surf_sg.get_symmetry_operations()
        unique_coords = []
        # Convert to fractional
        coords_set = [cart_to_frac(self.slab.lattice, coords) 
                      for coords in coords_set]
        for coords in coords_set:
            incoord = False
            for op in symm_ops:
                if in_coord_list_pbc(unique_coords, op.operate(coords), 
                                     atol = threshold):
                    incoord = True
                    break
            if not incoord:
                unique_coords += [coords]
        # convert back to cartesian
        return [frac_to_cart(self.slab.lattice, coords) 
                for coords in unique_coords]
Exemplo n.º 5
0
    def get_kpoint_weights(self, kpoints, atol=1e-8):
        """
        Calculate the weights for a list of kpoints.

        Args:
            kpoints (Sequence): Sequence of kpoints. np.arrays is fine. Note
                that the code does not check that the list of kpoints
                provided does not contain duplicates.
            atol (float): Tolerance for fractional coordinates comparisons.

        Returns:
            List of weights, in the SAME order as kpoints.
        """
        latt = self._structure.lattice.reciprocal_lattice
        grid = Structure(latt, ["H"], [[0, 0, 0]])
        a = SpacegroupAnalyzer(grid)
        recp_ops = a.get_symmetry_operations()
        weights = []
        for k in kpoints:
            all_k = []
            for o in recp_ops:
                k2 = o.operate(k)
                if not in_coord_list_pbc(all_k, k2, atol=atol):
                    all_k.append(k2)
            weights.append(len(all_k))
        return weights
Exemplo n.º 6
0
 def _unique_coords(self, coord_in):
     """
     Generate unique coordinates using coord and symmetry positions.
     """
     coords = []
     for op in self.symmetry_operations:
         coord = op.operate(coord_in)
         coord = np.array([i - math.floor(i) for i in coord])
         if not in_coord_list_pbc(coords, coord, atol=1e-3):
             coords.append(coord)
     return coords
Exemplo n.º 7
0
 def _unique_coords(self, coord_in):
     """
     Generate unique coordinates using coord and symmetry positions.
     """
     coords = []
     for op in self.symmetry_operations:
         coord = op.operate(coord_in)
         coord = np.array([i - math.floor(i) for i in coord])
         if not in_coord_list_pbc(coords, coord, atol=1e-3):
             coords.append(coord)
     return coords
Exemplo n.º 8
0
 def near_reduce(self, coords_set, threshold = 1e-4):
     """
     Prunes coordinate set for coordinates that are within 
     threshold
     
     Args:
         coords_set (Nx3 array-like): list or array of coordinates
         threshold (float): threshold value for distance
     """
     unique_coords = []
     coords_set = [cart_to_frac(self.slab.lattice, coords) 
                   for coords in coords_set]
     for coord in coords_set:
         if not in_coord_list_pbc(unique_coords, coord, threshold):
             unique_coords += [coord]
     return [frac_to_cart(self.slab.lattice, coords) 
             for coords in unique_coords]
Exemplo n.º 9
0
 def near_reduce(self, coords_set, threshold = 1e-4):
     """
     Prunes coordinate set for coordinates that are within 
     threshold
     
     Args:
         coords_set (Nx3 array-like): list or array of coordinates
         threshold (float): threshold value for distance
     """
     unique_coords = []
     coords_set = [cart_to_frac(self.slab.lattice, coords) 
                   for coords in coords_set]
     for coord in coords_set:
         if not in_coord_list_pbc(unique_coords, coord, threshold):
             unique_coords += [coord]
     return [frac_to_cart(self.slab.lattice, coords) 
             for coords in unique_coords]
Exemplo n.º 10
0
    def find_surface_sites_by_height(self, slab, height=0.9, xy_tol=0.05):
        """
        This method finds surface sites by determining which sites are within
        a threshold value in height from the topmost site in a list of sites

        Args:
            site_list (list): list of sites from which to select surface sites
            height (float): threshold in angstroms of distance from topmost
                site in slab along the slab c-vector to include in surface
                site determination
            xy_tol (float): if supplied, will remove any sites which are
                within a certain distance in the miller plane.

        Returns:
            list of sites selected to be within a threshold of the highest
        """

        # Get projection of coordinates along the miller index
        m_projs = np.array(
            [np.dot(site.coords, self.mvec) for site in slab.sites])

        # Mask based on window threshold along the miller index.
        topmask = (m_projs - np.amax(m_projs)) >= -height
        bottommask = (np.min(m_projs) - m_projs) >= -height
        mask = topmask if self.top_surface else bottommask

        surf_sites = [slab.sites[n] for n in np.where(mask)[0]]
        if xy_tol:
            # sort surface sites by height
            surf_sites = [s for (h, s) in zip(m_projs[mask], surf_sites)]
            surf_sites.reverse()
            unique_sites, unique_perp_fracs = [], []
            for site in surf_sites:
                this_perp = site.coords - np.dot(site.coords, self.mvec)
                this_perp_frac = cart_to_frac(slab.lattice, this_perp)
                if not in_coord_list_pbc(unique_perp_fracs, this_perp_frac):
                    unique_sites.append(site)
                    unique_perp_fracs.append(this_perp_frac)
            surf_sites = unique_sites

        return surf_sites
Exemplo n.º 11
0
    def find_surface_sites_by_height(self, slab, height=0.9, xy_tol=0.05):
        """
        This method finds surface sites by determining which sites are within
        a threshold value in height from the topmost site in a list of sites

        Args:
            site_list (list): list of sites from which to select surface sites
            height (float): threshold in angstroms of distance from topmost
                site in slab along the slab c-vector to include in surface 
                site determination
            xy_tol (float): if supplied, will remove any sites which are
                within a certain distance in the miller plane.

        Returns:
            list of sites selected to be within a threshold of the highest
        """

        # Get projection of coordinates along the miller index
        m_projs = np.array([np.dot(site.coords, self.mvec)
                            for site in slab.sites])

        # Mask based on window threshold along the miller index
        mask = (m_projs - np.amax(m_projs)) >= -height
        surf_sites = [slab.sites[n] for n in np.where(mask)[0]] 
        if xy_tol:
            # sort surface sites by height
            surf_sites = [s for (h, s) in zip(m_projs[mask], surf_sites)]
            surf_sites.reverse()
            unique_sites, unique_perp_fracs = [], []
            for site in surf_sites:
                this_perp = site.coords - np.dot(site.coords, self.mvec)
                this_perp_frac = cart_to_frac(slab.lattice, this_perp)
                if not in_coord_list_pbc(unique_perp_fracs, this_perp_frac):
                    unique_sites.append(site)
                    unique_perp_fracs.append(this_perp_frac)
            surf_sites = unique_sites

        return surf_sites