def test_subset(self):
        sm = StructureMatcher(
            ltol=0.2,
            stol=0.3,
            angle_tol=5,
            primitive_cell=False,
            scale=True,
            attempt_supercell=False,
            allow_subset=True,
        )
        l = Lattice.orthorhombic(10, 20, 30)
        s1 = Structure(l, ["Si", "Si", "Ag"], [[0, 0, 0.1], [0, 0, 0.2], [0.7, 0.4, 0.5]])
        s2 = Structure(l, ["Si", "Ag"], [[0, 0.1, 0], [-0.7, 0.5, 0.4]])
        result = sm.get_s2_like_s1(s1, s2)

        self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords, [0, 0, 0.1])), 1)
        self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords, [0.7, 0.4, 0.5])), 1)

        # test with fewer species in s2
        s1 = Structure(l, ["Si", "Ag", "Si"], [[0, 0, 0.1], [0, 0, 0.2], [0.7, 0.4, 0.5]])
        s2 = Structure(l, ["Si", "Si"], [[0, 0.1, 0], [-0.7, 0.5, 0.4]])
        result = sm.get_s2_like_s1(s1, s2)
        mindists = np.min(s1.lattice.get_all_distances(s1.frac_coords, result.frac_coords), axis=0)
        self.assertLess(np.max(mindists), 1e-6)

        self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords, [0, 0, 0.1])), 1)
        self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords, [0.7, 0.4, 0.5])), 1)

        # test with not enough sites in s1
        # test with fewer species in s2
        s1 = Structure(l, ["Si", "Ag", "Cl"], [[0, 0, 0.1], [0, 0, 0.2], [0.7, 0.4, 0.5]])
        s2 = Structure(l, ["Si", "Si"], [[0, 0.1, 0], [-0.7, 0.5, 0.4]])
        self.assertEqual(sm.get_s2_like_s1(s1, s2), None)
示例#2
0
 def test_find_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(find_in_coord_list_pbc(coords, test_coord))
     self.assertEqual(find_in_coord_list_pbc(coords, test_coord,
                                             atol=0.15)[0], 0)
     test_coord = [0.99, 0.99, 0.99]
     self.assertEqual(
         find_in_coord_list_pbc(coords, test_coord, atol=0.02)[0], 0)
     test_coord = [-0.499, -0.499, -0.499]
     self.assertEqual(
         find_in_coord_list_pbc(coords, test_coord, atol=0.01)[0], 1)
def find_site_ce(structure, target_site):
    """
    Returns mp_symbol of site environment of given site
    :param structure: (Structure) Structure containing target Site
    :param target_site: (Site) target Site
    :return: (String) mp_symbol of site coordination environment of given site
    """

    # Find index of target_site
    target_isite = find_in_coord_list_pbc(structure.frac_coords, target_site.frac_coords)[0]

    # Set up LocalGeometryFinder
    s1_finder = polyfinder.LocalGeometryFinder()
    s1_finder.setup_structure(structure)
    s1_finder.setup_parameters(centering_type='standard', structure_refinement='none')

    # Find site environment from LocalGeometryFinder
    environments = s1_finder.compute_structure_environments_detailed_voronoi(only_indices=[target_isite],
                                                                             maximum_distance_factor=1.5)

    # Calculate actual site polyhedra using 'strategy'
    strategy = strategies.SimplestChemenvStrategy()
    strategy.set_structure_environments(environments)
    site_environment = strategy.get_site_coordination_environment(site=None, isite=target_isite)

    return site_environment[0]
示例#4
0
    def _get_neighbor_array(self, phonon_center_site, phonon_center_radius, mystruc, tol=1e-1):
        """
            Get a neighbor-index array.
            Use program_keywords 'phonon_center_site' and
            'phonon_center_radius' to limit the number of phonons calculated.
            Args:
                phonon_center_site <str>: phonon center site (coordinate)
                phonon_center_radius <float>: phonon center radius in Angstroms. If nonzero, all atoms in a radius around EACH site found in phonon_center_site will also be taken into account
                mystruc <Structure>: pymatgen Structure
                tol <float>: Tolerance for match-searching.
        """
        if phonon_center_site == None:
            return None
        pcscoord = np.array(phonon_center_site.strip().split(), float)
        scalingsize = self.metafile.read_data("scaling_size")
        if not (scalingsize == None):
            pcscoord = np.dot(pcscoord, np.linalg.inv(self.scaleinput))
            # scale = scalingsize.split('[')[1].split(']')[0]
            # try:
            #    scaleinput = [int(scale.split(',')[0]),int(scale.split(',')[1]),int(scale.split(',')[2])] # input scaling size like [2,1,2]
            #    pcscoord = pcscoord / np.array(scaleinput)
            # except ValueError: # input scaling matrix like [1 1 0,1 -1 0,0 0 1]
            #    scaleinput = np.array([map(int, scale.split(',')[0].split()),map(int, scale.split(',')[1].split()),map(int, scale.split(',')[2].split())])
            #    pcscoord = np.dot(pcscoord, np.linalg.inv(scaleinput))
        tol = float(tol)
        pcsarr = find_in_coord_list_pbc(mystruc.frac_coords, pcscoord, tol)
        uniqsites = np.unique(pcsarr)

        if len(uniqsites) == 0:
            raise MASTError(
                "pmgextend/structure_extensions", "No sites found for phonon centering for %s" % self.keywords["name"]
            )

        if phonon_center_radius == None:
            return uniqsites

        nrad = float(phonon_center_radius)
        if nrad == 0:
            return uniqsites
        if nrad < 0:
            raise MASTError(
                "pmgextend/structure_extensions",
                "Phonon center radius should not be less than zero for %s!" % self.keywords["name"],
            )

        nbtotarr = None
        for pcs in uniqsites:
            neighbors = mystruc.get_neighbors(mystruc[pcs], nrad, True)
            if nbtotarr == None:
                nbtotarr = neighbors
            else:
                np.concatenate([nbtotarr, neighbors])
        nbsitelist = list()
        for nbr in nbtotarr:
            nbsitelist.append(nbr[-1])
        nbsitelist = np.array(nbsitelist)
        alltotarr = np.concatenate([uniqsites, nbsitelist])
        allsites = np.unique(alltotarr)
        return allsites
 def test_get_s2_like_s1(self):
     sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, 
                           primitive_cell=False, scale=True, 
                           attempt_supercell=True)
     l = Lattice.orthorhombic(1, 2, 3)
     s1 = Structure(l, ['Si', 'Si', 'Ag'], 
                    [[0,0,0.1],[0,0,0.2],[.7,.4,.5]])
     s1.make_supercell([2,1,1])
     s2 = Structure(l, ['Si', 'Si', 'Ag'], 
                    [[0,0.1,0],[0,0.1,-0.95],[-.7,.5,.375]])
     result = sm.get_s2_like_s1(s1, s2)
     
     self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords, 
                                                 [0.35,0.4,0.5])), 1)
     self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords, 
                                                 [0,0,0.125])), 1)
     self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords, 
                                                 [0,0,0.175])), 1)
示例#6
0
    def test_get_s2_like_s1(self):
        sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5,
                              primitive_cell=False, scale=True,
                              attempt_supercell=True)
        l = Lattice.orthorhombic(1, 2, 3)
        s1 = Structure(l, ['Si', 'Si', 'Ag'],
                       [[0,0,0.1],[0,0,0.2],[.7,.4,.5]])
        s1.make_supercell([2,1,1])
        s2 = Structure(l, ['Si', 'Si', 'Ag'],
                       [[0,0.1,0],[0,0.1,-0.95],[-.7,.5,.375]])
        result = sm.get_s2_like_s1(s1, s2)

        self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords,
                                                    [0.35,0.4,0.5])), 1)
        self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords,
                                                    [0,0,0.125])), 1)
        self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords,
                                                    [0,0,0.175])), 1)
示例#7
0
    def test_subset(self):
        sm = StructureMatcher(ltol=0.2,
                              stol=0.3,
                              angle_tol=5,
                              primitive_cell=False,
                              scale=True,
                              attempt_supercell=False,
                              allow_subset=True)
        l = Lattice.orthorhombic(10, 20, 30)
        s1 = Structure(l, ['Si', 'Si', 'Ag'],
                       [[0, 0, 0.1], [0, 0, 0.2], [.7, .4, .5]])
        s2 = Structure(l, ['Si', 'Ag'], [[0, 0.1, 0], [-.7, .5, .4]])
        result = sm.get_s2_like_s1(s1, s2)

        self.assertEqual(
            len(find_in_coord_list_pbc(result.frac_coords, [0, 0, 0.1])), 1)
        self.assertEqual(
            len(find_in_coord_list_pbc(result.frac_coords, [0.7, 0.4, 0.5])),
            1)

        #test with fewer species in s2
        s1 = Structure(l, ['Si', 'Ag', 'Si'],
                       [[0, 0, 0.1], [0, 0, 0.2], [.7, .4, .5]])
        s2 = Structure(l, ['Si', 'Si'], [[0, 0.1, 0], [-.7, .5, .4]])
        result = sm.get_s2_like_s1(s1, s2)
        mindists = np.min(s1.lattice.get_all_distances(s1.frac_coords,
                                                       result.frac_coords),
                          axis=0)
        self.assertLess(np.max(mindists), 1e-6)

        self.assertEqual(
            len(find_in_coord_list_pbc(result.frac_coords, [0, 0, 0.1])), 1)
        self.assertEqual(
            len(find_in_coord_list_pbc(result.frac_coords, [0.7, 0.4, 0.5])),
            1)

        #test with not enough sites in s1
        #test with fewer species in s2
        s1 = Structure(l, ['Si', 'Ag', 'Cl'],
                       [[0, 0, 0.1], [0, 0, 0.2], [.7, .4, .5]])
        s2 = Structure(l, ['Si', 'Si'], [[0, 0.1, 0], [-.7, .5, .4]])
        self.assertEqual(sm.get_s2_like_s1(s1, s2), None)
示例#8
0
 def get_matching_coord(coord):
     keys = list(coord_to_species.keys())
     coords = np.array(keys)
     for op in self.symmetry_operations:
         c = op.operate(coord)
         inds = find_in_coord_list_pbc(coords, c, atol=self._site_tolerance)
         # cant use if inds, because python is dumb and np.array([0]) evaluates
         # to False
         if len(inds):
             return keys[inds[0]]
     return False
    def test_subset(self):
        sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, 
                              primitive_cell=False, scale=True, 
                              attempt_supercell=False,
                              allow_subset=True)
        l = Lattice.orthorhombic(10, 20, 30)
        s1 = Structure(l, ['Si', 'Si', 'Ag'], 
                       [[0,0,0.1],[0,0,0.2],[.7,.4,.5]])
        s2 = Structure(l, ['Si', 'Ag'], 
                       [[0,0.1,0],[-.7,.5,.4]])
        result = sm.get_s2_like_s1(s1, s2)
        
        self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords, 
                                                    [0,0,0.1])), 1)
        self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords, 
                                                    [0.7,0.4,0.5])), 1)

        #test with fewer species in s2
        s1 = Structure(l, ['Si', 'Ag', 'Si'], 
                       [[0,0,0.1],[0,0,0.2],[.7,.4,.5]])
        s2 = Structure(l, ['Si', 'Si'], 
                       [[0,0.1,0],[-.7,.5,.4]])
        result = sm.get_s2_like_s1(s1, s2)
        
        self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords, 
                                                    [0,0,0.1])), 1)
        self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords, 
                                                    [0.7,0.4,0.5])), 1)
        
        #test with not enough sites in s1
        #test with fewer species in s2
        s1 = Structure(l, ['Si', 'Ag', 'Cl'], 
                       [[0,0,0.1],[0,0,0.2],[.7,.4,.5]])
        s2 = Structure(l, ['Si', 'Si'], 
                       [[0,0.1,0],[-.7,.5,.4]])
        self.assertEqual(sm.get_s2_like_s1(s1, s2), None)
示例#10
0
    def induce_defect(self, defect, coord_type, threshold):
        """Creates a defect, and returns the modified structure
            Args:
                defect <dict>: Defect subdictionary (single 
                               defect) of the form:
                        {'symbol': 'cr', 'type': 'interstitial', 
                    'coordinates': array([ 0. ,  0.5,  0. ])}}
                coord_type <str>: cartesian or fractional
                threshold <float>: Threshold for finding the
                                   defect position in what may
                                   be a relaxed, imperfect 
                                   structure.
            Returns:
                defected structure <Structure>
        """
        struct_ed = self.keywords['struc_work1'].copy()
        symbol = defect['symbol'].title()  #Cap first letter

        # If we have cartesian coordinates, then we convert them to fractional here.
        if ('cartesian' in coord_type):
            defect['coordinates'] = self._cart2frac(
                defect['coordinates'], self.keywords['struc_work1'])

        if (defect['type'] == 'vacancy'):
            self.logger.info('Creating a %s vacancy at %s' %
                             (symbol, str(defect['coordinates'])))
            index = find_in_coord_list_pbc(
                self.keywords['struc_work1'].frac_coords,
                defect['coordinates'],
                atol=threshold)
            if len(index) > 1:
                raise MASTError(
                    self.__class__.__name__,
                    "Multiple indices %s found. Check structure and/or adjust threshold %s to finer tolerance for ingredient %s"
                    % (index, threshold, self.keywords['name']))
            if len(index) == 0:
                raise MASTError(
                    self.__class__.__name__,
                    "No indices found. Check structure and/or adjust threshold %s to lower tolerance for ingredient %s"
                    % (threshold, self.keywords['name']))
            struct_ed.remove_sites([index])
        elif (defect['type'] == 'interstitial'):
            self.logger.info('Creating a %s interstitial at %s' %
                             (symbol, str(defect['coordinates'])))
            struct_ed.append(symbol,
                             defect['coordinates'],
                             coords_are_cartesian=False,
                             validate_proximity=True)
        elif (defect['type'] in ['antisite', 'substitution']):
            self.logger.info('Creating a %s antisite at %s' %
                             (symbol, str(defect['coordinates'])))
            index = find_in_coord_list_pbc(
                self.keywords['struc_work1'].frac_coords,
                defect['coordinates'],
                atol=threshold)
            if len(index) > 1:
                raise MASTError(
                    self.__class__.__name__,
                    "Multiple indices %s found. Check structure and/or adjust threshold %s to finer tolerance for ingredient %s"
                    % (index, threshold, self.keywords['name']))
            if len(index) == 0:
                raise MASTError(
                    self.__class__.__name__,
                    "No indices found. Check structure and/or adjust threshold %s to lower tolerance for ingredient %s"
                    % (threshold, self.keywords['name']))
            struct_ed.replace(index, symbol)
            struct_ed = struct_ed.get_sorted_structure()
        else:
            raise RuntimeError('Defect type %s not supported' % defect['type'])

        return struct_ed
示例#11
0
    def _get_neighbor_array(self,
                            phonon_center_site,
                            phonon_center_radius,
                            mystruc,
                            tol=1e-1):
        """
            Get a neighbor-index array.
            Use program_keywords 'phonon_center_site' and
            'phonon_center_radius' to limit the number of phonons calculated.
            Args:
                phonon_center_site <str>: phonon center site (coordinate)
                phonon_center_radius <float>: phonon center radius in Angstroms. If nonzero, all atoms in a radius around EACH site found in phonon_center_site will also be taken into account
                mystruc <Structure>: pymatgen Structure
                tol <float>: Tolerance for match-searching.
        """
        if phonon_center_site == None:
            return None
        pcscoord = np.array(phonon_center_site.strip().split(), float)
        scalingsize = self.metafile.read_data('scaling_size')
        if not (scalingsize == None):
            pcscoord = np.dot(pcscoord, np.linalg.inv(self.scaleinput))
            #scale = scalingsize.split('[')[1].split(']')[0]
            #try:
            #    scaleinput = [int(scale.split(',')[0]),int(scale.split(',')[1]),int(scale.split(',')[2])] # input scaling size like [2,1,2]
            #    pcscoord = pcscoord / np.array(scaleinput)
            #except ValueError: # input scaling matrix like [1 1 0,1 -1 0,0 0 1]
            #    scaleinput = np.array([map(int, scale.split(',')[0].split()),map(int, scale.split(',')[1].split()),map(int, scale.split(',')[2].split())])
            #    pcscoord = np.dot(pcscoord, np.linalg.inv(scaleinput))
        tol = float(tol)
        pcsarr = find_in_coord_list_pbc(mystruc.frac_coords, pcscoord, tol)
        uniqsites = np.unique(pcsarr)

        if len(uniqsites) == 0:
            raise MASTError(
                "pmgextend/structure_extensions",
                "No sites found for phonon centering for %s" %
                self.keywords['name'])

        if phonon_center_radius == None:
            return uniqsites

        nrad = float(phonon_center_radius)
        if nrad == 0:
            return uniqsites
        if nrad < 0:
            raise MASTError(
                "pmgextend/structure_extensions",
                "Phonon center radius should not be less than zero for %s!" %
                self.keywords['name'])

        nbtotarr = None
        for pcs in uniqsites:
            neighbors = mystruc.get_neighbors(mystruc[pcs], nrad, True)
            if nbtotarr == None:
                nbtotarr = neighbors
            else:
                np.concatenate([nbtotarr, neighbors])
        nbsitelist = list()
        for nbr in nbtotarr:
            nbsitelist.append(nbr[-1])
        nbsitelist = np.array(nbsitelist)
        alltotarr = np.concatenate([uniqsites, nbsitelist])
        allsites = np.unique(alltotarr)
        return allsites
示例#12
0
 def sort_structure_and_neb_lines(self, neblines, folderstr, images=0):
     """Sort the structure in an approved way:
         1. Remove lines which closely match the neb moving 
            lines in the NEB section.
         2. Sort the structure by element and coordinate.
         3. Prepend the NEB moving lines to their element 
            sections.
         4. Return the modified structure.
         Args:
             folderstr <str>  : '00' = initial config, 
                                '0N+1' = final config,
                                '0N' = corresponding image
             neblines <list>  : list of NEB lines
             images <int>     : number of images
         Returns:
             sorted structure <Structure>
     """
     import MAST.data
     atol = 0.1  # Need fairly large tolerance to account for relaxation.
     sortedstruc = self.keywords['struc_work1'].get_sorted_structure()
     struct_ed = sortedstruc.copy()
     nebidx = list()
     elemstarts = self._get_element_indices(sortedstruc)
     for nebline in neblines:
         nebdict = self._parse_neb_line(nebline)
         temp_fin = sortedstruc.copy()
         temp_fin.append(nebdict['element'], nebdict['coord'][1])
         temp_start = sortedstruc.copy()
         temp_start.append(nebdict['element'], nebdict['coord'][0])
         strlist = temp_start.interpolate(temp_fin, images + 1)
         lastidx = strlist[0].num_sites - 1
         if folderstr == '00':
             mycoord = nebdict['coord'][0]
         elif folderstr == str(images + 1).zfill(2):
             mycoord = nebdict['coord'][1]
         else:
             mystridx = int(folderstr)
             mycoord = strlist[mystridx].frac_coords[lastidx]
         scalingsize = self.metafile.read_data('scaling_size')
         if not (scalingsize == None):
             mycoord = np.dot(mycoord, np.linalg.inv(self.scaleinput))
             #scale = scalingsize.split('[')[1].split(']')[0]
             #try:
             #    scaleinput = [int(scale.split(',')[0]),int(scale.split(',')[1]),int(scale.split(',')[2])] # input scaling size like [2,1,2]
             #    mycoord = mycoord / np.array(scaleinput)
             #except ValueError: # input scaling matrix like [1 1 0,1 -1 0,0 0 1]
             #    scaleinput = np.array([map(int, scale.split(',')[0].split()),map(int, scale.split(',')[1].split()),map(int, scale.split(',')[2].split())])
             #    mycoord = np.dot(mycoord, np.linalg.inv(scaleinput))
         indexraw = find_in_coord_list_pbc(sortedstruc.frac_coords, mycoord,
                                           atol)
         index = list()
         for indexentry in indexraw:
             if sortedstruc.species[indexentry] == temp_start.species[
                     lastidx]:
                 index.append(indexentry)
         if len(index) == 0:
             raise MASTError(
                 "pmgextend/structure_extensions",
                 "No coordinate found matching %s for %s" %
                 (mycoord, self.keywords['name']))
         nebidx.append(index[0])  #only take first site?
         mysite = sortedstruc.sites[index[0]]
         myelem = MAST.data.atomic_number[mysite.species_string]
         struct_ed.remove_sites([index[0]])
         struct_ed.insert(elemstarts[myelem], mysite.specie,
                          mysite.frac_coords)
         sortedstruc = struct_ed.copy()  #get new ordering
     if not len(nebidx) == len(neblines):
         raise MASTError(
             "pmgextend/structure_extensions",
             "Not all NEB lines found for %s" % self.keywords['name'])
     return struct_ed
示例#13
0
    def induce_defect(self, defect, coord_type, threshold):
        """Creates a defect, and returns the modified structure
            Args:
                defect <dict>: Defect subdictionary (single 
                               defect) of the form:
                        {'symbol': 'cr', 'type': 'interstitial', 
                    'coordinates': array([ 0. ,  0.5,  0. ])}}
                coord_type <str>: cartesian or fractional
                threshold <float>: Threshold for finding the
                                   defect position in what may
                                   be a relaxed, imperfect 
                                   structure.
            Returns:
                defected structure <Structure>
        """
        struct_ed = self.keywords["struc_work1"].copy()
        symbol = defect["symbol"].title()  # Cap first letter

        # If we have cartesian coordinates, then we convert them to fractional here.
        if "cartesian" in coord_type:
            defect["coordinates"] = self._cart2frac(defect["coordinates"], self.keywords["struc_work1"])

        if defect["type"] == "vacancy":
            self.logger.info("Creating a %s vacancy at %s" % (symbol, str(defect["coordinates"])))
            index = find_in_coord_list_pbc(
                self.keywords["struc_work1"].frac_coords, defect["coordinates"], atol=threshold
            )
            if len(index) > 1:
                raise MASTError(
                    self.__class__.__name__,
                    "Multiple indices %s found. Check structure and/or adjust threshold %s to finer tolerance for ingredient %s"
                    % (index, threshold, self.keywords["name"]),
                )
            if len(index) == 0:
                raise MASTError(
                    self.__class__.__name__,
                    "No indices found. Check structure and/or adjust threshold %s to lower tolerance for ingredient %s"
                    % (threshold, self.keywords["name"]),
                )
            struct_ed.remove_sites([index])
        elif defect["type"] == "interstitial":
            self.logger.info("Creating a %s interstitial at %s" % (symbol, str(defect["coordinates"])))
            struct_ed.append(symbol, defect["coordinates"], coords_are_cartesian=False, validate_proximity=True)
        elif defect["type"] in ["antisite", "substitution"]:
            self.logger.info("Creating a %s antisite at %s" % (symbol, str(defect["coordinates"])))
            index = find_in_coord_list_pbc(
                self.keywords["struc_work1"].frac_coords, defect["coordinates"], atol=threshold
            )
            if len(index) > 1:
                raise MASTError(
                    self.__class__.__name__,
                    "Multiple indices %s found. Check structure and/or adjust threshold %s to finer tolerance for ingredient %s"
                    % (index, threshold, self.keywords["name"]),
                )
            if len(index) == 0:
                raise MASTError(
                    self.__class__.__name__,
                    "No indices found. Check structure and/or adjust threshold %s to lower tolerance for ingredient %s"
                    % (threshold, self.keywords["name"]),
                )
            struct_ed.replace(index, symbol)
            struct_ed = struct_ed.get_sorted_structure()
        else:
            raise RuntimeError("Defect type %s not supported" % defect["type"])

        return struct_ed
示例#14
0
    def sort_structure_and_neb_lines(self, neblines, folderstr, images=0):
        """Sort the structure in an approved way:
            1. Remove lines which closely match the neb moving 
               lines in the NEB section.
            2. Sort the structure by element and coordinate.
            3. Prepend the NEB moving lines to their element 
               sections.
            4. Return the modified structure.
            Args:
                folderstr <str>  : '00' = initial config, 
                                   '0N+1' = final config,
                                   '0N' = corresponding image
                neblines <list>  : list of NEB lines
                images <int>     : number of images
            Returns:
                sorted structure <Structure>
        """
        import MAST.data

        atol = 0.1  # Need fairly large tolerance to account for relaxation.
        sortedstruc = self.keywords["struc_work1"].get_sorted_structure()
        struct_ed = sortedstruc.copy()
        nebidx = list()
        elemstarts = self._get_element_indices(sortedstruc)
        for nebline in neblines:
            nebdict = self._parse_neb_line(nebline)
            temp_fin = sortedstruc.copy()
            temp_fin.append(nebdict["element"], nebdict["coord"][1])
            temp_start = sortedstruc.copy()
            temp_start.append(nebdict["element"], nebdict["coord"][0])
            strlist = temp_start.interpolate(temp_fin, images + 1)
            lastidx = strlist[0].num_sites - 1
            if folderstr == "00":
                mycoord = nebdict["coord"][0]
            elif folderstr == str(images + 1).zfill(2):
                mycoord = nebdict["coord"][1]
            else:
                mystridx = int(folderstr)
                mycoord = strlist[mystridx].frac_coords[lastidx]
            scalingsize = self.metafile.read_data("scaling_size")
            if not (scalingsize == None):
                mycoord = np.dot(mycoord, np.linalg.inv(self.scaleinput))
                # scale = scalingsize.split('[')[1].split(']')[0]
                # try:
                #    scaleinput = [int(scale.split(',')[0]),int(scale.split(',')[1]),int(scale.split(',')[2])] # input scaling size like [2,1,2]
                #    mycoord = mycoord / np.array(scaleinput)
                # except ValueError: # input scaling matrix like [1 1 0,1 -1 0,0 0 1]
                #    scaleinput = np.array([map(int, scale.split(',')[0].split()),map(int, scale.split(',')[1].split()),map(int, scale.split(',')[2].split())])
                #    mycoord = np.dot(mycoord, np.linalg.inv(scaleinput))
            indexraw = find_in_coord_list_pbc(sortedstruc.frac_coords, mycoord, atol)
            index = list()
            for indexentry in indexraw:
                if sortedstruc.species[indexentry] == temp_start.species[lastidx]:
                    index.append(indexentry)
            if len(index) == 0:
                raise MASTError(
                    "pmgextend/structure_extensions",
                    "No coordinate found matching %s for %s" % (mycoord, self.keywords["name"]),
                )
            nebidx.append(index[0])  # only take first site?
            mysite = sortedstruc.sites[index[0]]
            myelem = MAST.data.atomic_number[mysite.species_string]
            struct_ed.remove_sites([index[0]])
            struct_ed.insert(elemstarts[myelem], mysite.specie, mysite.frac_coords)
            sortedstruc = struct_ed.copy()  # get new ordering
        if not len(nebidx) == len(neblines):
            raise MASTError("pmgextend/structure_extensions", "Not all NEB lines found for %s" % self.keywords["name"])
        return struct_ed
def get_connectivity_description_1(structure, radius=2.6, peripheral_species=None, central_species=None):
    """
    Writes a verbal description of the connectivity between cations in a structure and does differentiate between
    species on different sites in the unit cell. Uses the Chemenv module in Pymatgen to calculate the coordination
    environment for specific sites.

    :param structure: (Structure) target Structure
    :param radius: (float) radius within which to determine whether a nearby atom is a peripheral ion
    :param peripheral_species: (List of Strings) list of species strings of what we consider the peripheral species of
    the polyhedra in the structure
    :param central_species: (List of Strings) list of species strings of what we consider the central species of the
    polyhedra in the structure
    :return: (dict) dictionary of strings containing verbal descriptions of connectivites between cations in the given
    structure; keys = cation tag (eg: Li1, Na2, where the letters represent the species and the number distinguishes
    the species from the other instances of that same species in the unit cell); dict values = String descriptions of
    connectivity
    """

    if peripheral_species is None:
        peripheral_species = ['O2-', 'O', 'F-', 'F', 'Cl-', 'Cl', 'I-', 'I', 'Br-', 'Br', 'S2-', 'S', 'N', 'N3-']
    if central_species is None:
        central_species = []

    connectivity_matrix, all_polyhedra, supercell = \
        get_connectivity_matrix(structure, True, radius, peripheral_species, central_species)

    lgf = polyfinder.LocalGeometryFinder()
    lgf.setup_parameters(centering_type='standard', structure_refinement='none')
    lgf.setup_structure(supercell)
    environments = lgf.compute_structure_environments_detailed_voronoi(maximum_distance_factor=1.5)
    light_se = se.LightStructureEnvironments(strategies.SimplestChemenvStrategy(), environments)
    path_to_jsons = os.path.dirname(cg_files.__file__)

    descriptions = {}
    for cation_1 in connectivity_matrix.keys():
        descriptions[cation_1] = ""
    for cation_1 in connectivity_matrix.keys():
        example_poly1 = get_ex_poly(all_polyhedra, cation_1)
        target_isite1 = find_in_coord_list_pbc(supercell.frac_coords, example_poly1.central_ion.frac_coords)[0]
        print supercell[target_isite1]
        print light_se._coordination_environments
        site_environment1 = light_se._coordination_environments[target_isite1]['ce_symbol']
        with open(path_to_jsons+"/%s.json" % site_environment1) as json_file:
            data1 = json.load(json_file)
        cn1 = data1['name']

        descriptions[cation_1] += cation_1 + " are " + cn1 + ". \n"
        for cation_2 in connectivity_matrix[cation_1].keys():
            connected = False
            for connectivity_type in connectivity_matrix[cation_1][cation_2].keys():
                if connectivity_matrix[cation_1][cation_2][connectivity_type] != 0:
                    connected = True
            if connected:
                descriptions[cation_1] += "They are "
                first = True
                for connectivity_type in connectivity_matrix[cation_1][cation_2].keys():
                    if connectivity_matrix[cation_1][cation_2][connectivity_type] != 0:
                        if first:
                            descriptions[cation_1] += connectivity_type + "-connected "
                            first = False
                        else:
                            descriptions[cation_1] += "and " + connectivity_type + "-connected "

                example_poly2 = get_ex_poly(all_polyhedra, cation_1)
                target_isite2 = find_in_coord_list_pbc(supercell.frac_coords, example_poly2.central_ion.frac_coords)[0]
                print supercell[target_isite2]
                print light_se._coordination_environments
                site_environment2 = light_se._coordination_environments[target_isite2]['ce_symbol']
                with open(path_to_jsons+"/%s.json" % site_environment2) as json_file:
                    data2 = json.load(json_file)
                cn2 = data2['name']
                descriptions[cation_1] += "to " + cn2 + " " + cation_2 + ". "
    return descriptions