Пример #1
0
    def _get_ionic_radii(self):
        """
        Computes ionic radii of elements for all sites in the structure.
        If valence is zero, atomic radius is used.
        """
        radii = []
        coord_finder = VoronoiCoordFinder(self._structure)

        def nearest_key(sorted_vals, key):
            i = bisect_left(sorted_vals, key)
            if i == len(sorted_vals):
                i = -1
            return sorted_vals[i]

        for i in range(len(self._structure.sites)):
            site = self._structure.sites[i]
            el = site.specie.symbol
            oxi_state = int(round(site.specie.oxi_state))
            coord_no = int(round(coord_finder.get_coordination_number(i)))
            try:
                tab_oxi_states = map(int, _ion_radii[el].keys())
                tab_oxi_states.sort()
                oxi_state = nearest_key(tab_oxi_states, oxi_state)
                radius = _ion_radii[el][str(oxi_state)][str(coord_no)]
            except KeyError:
                if coord_finder.get_coordination_number(i)-coord_no > 0:
                    new_coord_no = coord_no + 1
                else:
                    new_coord_no = coord_no - 1
                try:
                    radius = _ion_radii[el][str(oxi_state)][str(new_coord_no)]
                    coord_no = new_coord_no
                except:
                    tab_coords = map(int, _ion_radii[el][str(oxi_state)].keys())
                    tab_coords.sort()
                    new_coord_no = nearest_key(tab_coords, coord_no)
                    i = 0
                    for val in tab_coords:
                        if  val > coord_no:
                            break
                        i = i + 1
                    if i == len(tab_coords):
                        key = str(tab_coords[-1])
                        radius = _ion_radii[el][str(oxi_state)][key]
                    elif i == 0:
                        key = str(tab_coords[0])
                        radius = _ion_radii[el][str(oxi_state)][key]
                    else:
                        key = str(tab_coords[i-1])
                        radius1 = _ion_radii[el][str(oxi_state)][key]
                        key = str(tab_coords[i])
                        radius2 = _ion_radii[el][str(oxi_state)][key]
                        radius = (radius1+radius2)/2

            #implement complex checks later
            radii.append(radius)
        return radii
Пример #2
0
    def _get_coord_no_sites_chrg(self, site):
        """
        Compute the coordination number and coordination charge

        Args:
            site:
                pymatgen.core.sites.Site
        """
        struct = self._structure.copy()
        struct.append(site.specie.symbol, site.frac_coords)
        coord_finder = VoronoiCoordFinder(struct)
        coord_no = coord_finder.get_coordination_number(-1)
        coord_sites = coord_finder.get_coordinated_sites(-1)

        # In some cases coordination sites to interstitials include
        # interstitials also. Filtering them.
        def no_inter(site):
            return not site.specie.symbol == 'X'

        coord_sites = filter(no_inter, coord_sites)

        coord_chrg = 0
        for site, weight in coord_finder.get_voronoi_polyhedra(-1).items():
            if not site.specie.symbol == 'X':
                coord_chrg += weight * self._valence_dict[site.species_string]

        return coord_no, coord_sites, coord_chrg
Пример #3
0
    def _get_coord_no_sites_chrg(self, site):
        """
        Compute the coordination number and coordination charge

        Args:
            site:
                pymatgen.core.sites.Site
        """
        struct = self._structure.copy()
        struct.append(site.species_string, site.frac_coords)
        coord_finder = VoronoiCoordFinder(struct)
        coord_no = coord_finder.get_coordination_number(-1)
        coord_sites = coord_finder.get_coordinated_sites(-1)

        # In some cases coordination sites to interstitials include
        # interstitials also.
        sites_to_be_deleted = []
        for i in range(len(coord_sites)):
            if coord_sites[i].species_string == 'X':
                sites_to_be_deleted.append(i)
        sites_to_be_deleted.reverse()  # So index won't change in between
        for ind in sites_to_be_deleted:
            del coord_sites[ind]

        coord_chrg = 0
        for site, weight in coord_finder.get_voronoi_polyhedra(-1).items():
            if not site.species_string == 'X':
                coord_chrg += weight * self._valence_dict[site.species_string]

        return coord_no, coord_sites, coord_chrg
Пример #4
0
    def _get_coord_no_sites_chrg(self, site):
        """
        Compute the coordination number and coordination charge

        Args:
            site:
                pymatgen.core.sites.Site
        """
        struct = self._structure.copy()
        struct.append(site.specie.symbol, site.frac_coords)
        coord_finder = VoronoiCoordFinder(struct)
        coord_no = coord_finder.get_coordination_number(-1)
        coord_sites = coord_finder.get_coordinated_sites(-1)

        # In some cases coordination sites to interstitials include
        # interstitials also. Filtering them.
        def no_inter(site):
            return not site.specie.symbol == 'X'
        coord_sites = filter(no_inter, coord_sites)

        coord_chrg = 0
        for site, weight in coord_finder.get_voronoi_polyhedra(-1).items():
            if not site.specie.symbol == 'X':
                coord_chrg += weight * self._valence_dict[site.species_string]

        return coord_no, coord_sites, coord_chrg
Пример #5
0
    def _get_coord_no_sites_chrg(self, site):
        """
        Compute the coordination number and coordination charge

        Args:
            site:
                pymatgen.core.sites.Site
        """
        struct = self._structure.copy()
        struct.append(site.species_string, site.frac_coords)
        coord_finder = VoronoiCoordFinder(struct)
        coord_no = coord_finder.get_coordination_number(-1)
        coord_sites = coord_finder.get_coordinated_sites(-1)

        # In some cases coordination sites to interstitials include 
        # interstitials also. 
        sites_to_be_deleted = []
        for i in range(len(coord_sites)):
            if coord_sites[i].species_string == 'X':
                sites_to_be_deleted.append(i)
        sites_to_be_deleted.reverse()  # So index won't change in between
        for ind in sites_to_be_deleted:
            del coord_sites[ind]

        coord_chrg = 0
        for site, weight in coord_finder.get_voronoi_polyhedra(-1).items():
            if not site.species_string == 'X':
                coord_chrg += weight * self._valence_dict[site.species_string]

        return coord_no, coord_sites, coord_chrg
Пример #6
0
class VoronoiCoordFinderTest(unittest.TestCase):

    def setUp(self):
        filepath = os.path.join(test_dir, 'vasprun.xml')
        reader = Vasprun(filepath)
        s = reader.final_structure
        self.finder = VoronoiCoordFinder(s,[Element("O")])
    
    def test_get_voronoi_polyhedra(self):
        self.assertEqual(len(self.finder.get_voronoi_polyhedra(0).items()),10, "Incorrect number of results returned for get_voronoi_polyhedra")
        
    def test_get_coordination_number(self):
        print self.finder.get_coordination_number(0)
        self.assertAlmostEqual(self.finder.get_coordination_number(0), 5.60588600732, 7, "Incorrect coordination number returned!")                

    def test_get_coordinated_sites(self):
        self.assertEqual(len(self.finder.get_coordinated_sites(0)), 10)
Пример #7
0
    def get_cn(self, poscars, diff_sp):
        """
        A function to compute the coordinations numbers not rounded

        Output: cn
        """
        n = int(diff_sp.values()[0][0])-1
        cn=[]
        for i in range(0,len(poscars)):
            coord_no = VoronoiCoordFinder(poscars[i].structure)
            cn.append(coord_no.get_coordination_number(n))
        return cn
Пример #8
0
 def _coord_find(self):
     """
     calls VoronoiCoordFinder to compute the coordination number,
     coordination charge
     """
     for i in range(self.defect_count()):
         struct = self._structs[i].copy()
         coord_finder = VoronoiCoordFinder(struct)
         self._coord_no.append(coord_finder.get_coordination_number(-1))
         self._coord_sites.append(coord_finder.get_coordinated_sites(-1))
         coord_chrg = 0
         for site, weight in coord_finder.get_voronoi_polyhedra(-1).items():
             coord_chrg += weight * self._valence_dict[site.species_string]
         self._coord_charge_no.append(coord_chrg)
Пример #9
0
class VoronoiCoordFinderTest(PymatgenTest):
    def setUp(self):
        s = self.get_structure('LiFePO4')
        self.finder = VoronoiCoordFinder(s, [Element("O")])

    def test_get_voronoi_polyhedra(self):
        self.assertEqual(len(self.finder.get_voronoi_polyhedra(0).items()), 8)

    def test_get_coordination_number(self):
        self.assertAlmostEqual(self.finder.get_coordination_number(0),
                               5.809265748999465, 7)

    def test_get_coordinated_sites(self):
        self.assertEqual(len(self.finder.get_coordinated_sites(0)), 8)
Пример #10
0
class VoronoiCoordFinderTest(PymatgenTest):
    def setUp(self):
        s = self.get_structure('LiFePO4')
        self.finder = VoronoiCoordFinder(s, [Element("O")])

    def test_get_voronoi_polyhedra(self):
        self.assertEqual(len(self.finder.get_voronoi_polyhedra(0).items()), 8)

    def test_get_coordination_number(self):
        self.assertAlmostEqual(self.finder.get_coordination_number(0),
                               5.809265748999465, 7)

    def test_get_coordinated_sites(self):
        self.assertEqual(len(self.finder.get_coordinated_sites(0)), 8)
Пример #11
0
 def _coord_find(self):
     """
     calls VoronoiCoordFinder to compute the coordination number,
     coordination charge
     """
     for i in range(self.defect_count()):
         struct = self._structs[i].copy()
         coord_finder = VoronoiCoordFinder(struct)
         self._coord_no.append(coord_finder.get_coordination_number(-1))
         self._coord_sites.append(coord_finder.get_coordinated_sites(-1))
         coord_chrg = 0
         for site, weight in coord_finder.get_voronoi_polyhedra(-1).items():
             coord_chrg += weight * self._valence_dict[site.species_string]
         self._coord_charge_no.append(coord_chrg)
Пример #12
0
    def __init__(self, structure, valences, radii):
        """
        Args:
            structure:
                pymatgen.core.structure.Structure
            valences:
                valences of elements as a dictionary 
            radii:
                Radii of elements as a dictionary
        """

        self._structure = structure
        self._valence_dict = valences
        self._rad_dict = radii
        # Store symmetrically distinct sites, their coordination numbers
        # coordinated_sites, effective charge
        symm_finder = SymmetryFinder(self._structure)
        symm_structure = symm_finder.get_symmetrized_structure()
        equiv_site_seq = symm_structure.equivalent_sites

        self._defect_sites = []
        for equiv_sites in equiv_site_seq:
            self._defect_sites.append(equiv_sites[0])

        self._vac_site_indices = []
        for site in self._defect_sites:
            for i in range(len(self._structure.sites)):
                if site == self._structure[i]:
                    self._vac_site_indices.append(i)

        coord_finder = VoronoiCoordFinder(self._structure)
        self._defectsite_coord_no = []
        self._defect_coord_sites = []
        for i in self._vac_site_indices:
            self._defectsite_coord_no.append(
                coord_finder.get_coordination_number(i)
            )
            self._defect_coord_sites.append(
                coord_finder.get_coordinated_sites(i)
            )

        # Store the ionic radii for the elements in the structure
        # (Used to  computing the surface are and volume)
        # Computed based on valence of each element

        self._vac_eff_charges = None
        self._vol = None
        self._sa = None
Пример #13
0
    def __init__(self, structure, valences, radii):
        """
        Args:
            structure:
                pymatgen.core.structure.Structure
            valences:
                valences of elements as a dictionary 
            radii:
                Radii of elements as a dictionary
        """

        self._structure = structure
        self._valence_dict = valences
        self._rad_dict = radii
        # Store symmetrically distinct sites, their coordination numbers
        # coordinated_sites, effective charge
        symm_finder = SymmetryFinder(self._structure)
        symm_structure = symm_finder.get_symmetrized_structure()
        equiv_site_seq = symm_structure.equivalent_sites

        self._defect_sites = []
        for equiv_sites in equiv_site_seq:
            self._defect_sites.append(equiv_sites[0])

        self._vac_site_indices = []
        for site in self._defect_sites:
            for i in range(len(self._structure.sites)):
                if site == self._structure[i]:
                    self._vac_site_indices.append(i)

        coord_finder = VoronoiCoordFinder(self._structure)
        self._defectsite_coord_no = []
        self._defect_coord_sites = []
        for i in self._vac_site_indices:
            self._defectsite_coord_no.append(
                coord_finder.get_coordination_number(i))
            self._defect_coord_sites.append(
                coord_finder.get_coordinated_sites(i))

        # Store the ionic radii for the elements in the structure
        # (Used to  computing the surface are and volume)
        # Computed based on valence of each element

        self._vac_eff_charges = None
        self._vol = None
        self._sa = None
Пример #14
0
class VoronoiCoordFinderTest(unittest.TestCase):

    def setUp(self):
        filepath = os.path.join(test_dir, 'LiFePO4.cif')
        parser = CifParser(filepath)
        s = parser.get_structures()[0]
        self.finder = VoronoiCoordFinder(s, [Element("O")])

    def test_get_voronoi_polyhedra(self):
        self.assertEqual(len(self.finder.get_voronoi_polyhedra(0).items()), 8,
                         "Incorrect number of results returned for " +
                         "get_voronoi_polyhedra")

    def test_get_coordination_number(self):
        self.assertAlmostEqual(self.finder.get_coordination_number(0),
                               5.809265748999465, 7)

    def test_get_coordinated_sites(self):
        self.assertEqual(len(self.finder.get_coordinated_sites(0)), 8)
Пример #15
0
class VoronoiCoordFinderTest(unittest.TestCase):
    def setUp(self):
        filepath = os.path.join(test_dir, 'LiFePO4.cif')
        parser = CifParser(filepath)
        s = parser.get_structures()[0]
        self.finder = VoronoiCoordFinder(s, [Element("O")])

    def test_get_voronoi_polyhedra(self):
        self.assertEqual(
            len(self.finder.get_voronoi_polyhedra(0).items()), 8,
            "Incorrect number of results returned for " +
            "get_voronoi_polyhedra")

    def test_get_coordination_number(self):
        self.assertAlmostEqual(self.finder.get_coordination_number(0),
                               5.809265748999465, 7)

    def test_get_coordinated_sites(self):
        self.assertEqual(len(self.finder.get_coordinated_sites(0)), 8)
Пример #16
0
def get_coordination_numbers(d):
    """
    Helper method to get the coordination number of all sites in the final
    structure from a run.

    Args:
        d:
            Run dict generated by VaspToDbTaskDrone.

    Returns:
        Coordination numbers as a list of dict of [{"site": site_dict,
        "coordination": number}, ...].
    """
    structure = Structure.from_dict(d["output"]["crystal"])
    f = VoronoiCoordFinder(structure)
    cn = []
    for i, s in enumerate(structure.sites):
        try:
            n = f.get_coordination_number(i)
            number = int(round(n))
            cn.append({"site": s.to_dict, "coordination": number})
        except Exception:
            logger.error("Unable to parse coordination errors")
    return cn
Пример #17
0
def get_coordination_numbers(d):
    """
    Helper method to get the coordination number of all sites in the final
    structure from a run.

    Args:
        d:
            Run dict generated by VaspToDbTaskDrone.

    Returns:
        Coordination numbers as a list of dict of [{"site": site_dict,
        "coordination": number}, ...].
    """
    structure = Structure.from_dict(d["output"]["crystal"])
    f = VoronoiCoordFinder(structure)
    cn = []
    for i, s in enumerate(structure.sites):
        try:
            n = f.get_coordination_number(i)
            number = int(round(n))
            cn.append({"site": s.as_dict(), "coordination": number})
        except Exception:
            logger.error("Unable to parse coordination errors")
    return cn
Пример #18
0
spacegroup2 = SpacegroupAnalyzer(s2)
print('space group symbol of structure1:',
      spacegroup1.get_space_group_symbol())
print('space group number of structure1:',
      spacegroup1.get_space_group_number())
print('space group symbol of structure2:',
      spacegroup2.get_space_group_symbol())
print('space group number of structure2:',
      spacegroup2.get_space_group_number())
Voronoi = VoronoiCoordFinder(s2, target=None)
site = s2.num_sites
#print("s2[0]:",s2.sites)
print("s2_cart_coords[0]", s2.cart_coords[0])
#print("s2_distance_(0,1)",s2.get_distance(0,1))
polyhedra = Voronoi.get_voronoi_polyhedra(1)
coordinate = Voronoi.get_coordination_number(1)
coordinate_sites = Voronoi.get_coordinated_sites(1)
Voronoi_Analyzer = VoronoiAnalyzer()
anay = Voronoi_Analyzer.analyze(s1, n=0)
strucs = [s1, s2]
anays = Voronoi_Analyzer.analyze_structures(strucs)
print("Voronoi_Analyzer.analyze(s1,n=0):", anay)
#plt = Voronoi_Analyzer.plot_vor_analysis(anays)
relax = RelaxationAnalyzer(s1, s2)
volume_change = relax.get_percentage_volume_change()
lattice_parameter_changes = relax.get_percentage_lattice_parameter_changes()
print('initial volume:', s1.volume)
print('final volume:', s2.volume)
print("percent_volume_change:", volume_change)
print("percent_lattice_change:", lattice_parameter_changes)
bond_dist = relax.get_percentage_bond_dist_changes(max_radius=6)
Пример #19
0
    def run_task(self, fw_spec):

        MyDB.db_access().connect()
        collection = MyDB.db_access().collection(fw_spec['collection'])

        with open('vasp.out', 'r') as output:
            content = output.readlines()
        examine = content[-2].strip()
        if examine[0:3] == '1 F':
            chgcar = Chgcar.from_file('CHGCAR')
            s1 = self['struct_s1']
            s2 = self['struct_s2']
            relax_sites = []
            for site_i, site in enumerate(s1.sites):
                if site.specie == fw_spec['moving_cation']:
                    relax_sites.append(site_i)

            pf = NEBPathfinder(s1,
                               s2,
                               relax_sites=relax_sites,
                               v=ChgcarPotential(chgcar).get_v(),
                               n_images=8)
            images = pf.images

            doc = collection.find_one({
                'mp-id': fw_spec["mp-id"],
                'pair_index': fw_spec["pair_index"]
            })
            path = []
            coordination_number = []
            for image in images:
                struct = Structure.from_dict(doc["gamma_structure"])
                site_index = image.species.index(fw_spec['moving_cation'])
                cation_site = image[site_index]
                struct.insert(0,
                              cation_site.specie,
                              cation_site.frac_coords,
                              properties=cation_site.properties)
                path.append(image[site_index].as_dict())
                voro_cn = VoronoiCoordFinder(struct)
                cn = voro_cn.get_coordination_number(0)
                coordination_number.append(cn)

            collection.update(
                {
                    "mp-id": fw_spec["mp-id"],
                    "pair_index": fw_spec["pair_index"]
                }, {
                    "$set": {
                        "status": "success",
                        "CN_path": coordination_number,
                        "path": path
                    }
                })
        else:
            collection.update(
                {
                    "mp-id": fw_spec["mp-id"],
                    "pair_index": fw_spec["pair_index"]
                }, {"$set": {
                    "status": "error"
                }})

        MyDB.db_access().close()

        return FWAction()
Пример #20
0
    def _get_ionic_radii(self):
        """
        Computes ionic radii of elements for all sites in the structure.
        If valence is zero, atomic radius is used.
        """
        radii = []
        coord_finder = VoronoiCoordFinder(self._structure)

        def nearest_key(sorted_vals, key):
            i = bisect_left(sorted_vals, key)
            if i == len(sorted_vals):
                return sorted_vals[-1]
            if i == 0:
                return sorted_vals[0]
            before = sorted_vals[i - 1]
            after = sorted_vals[i]
            if after - key < key - before:
                return after
            else:
                return before

        for i in range(len(self._structure.sites)):
            site = self._structure.sites[i]
            if isinstance(site.specie, Element):
                radius = site.specie.atomic_radius
                radii.append(radius)
                continue

            el = site.specie.symbol
            oxi_state = int(round(site.specie.oxi_state))
            coord_no = int(round(coord_finder.get_coordination_number(i)))
            try:
                tab_oxi_states = map(int, _ion_radii[el].keys())
                tab_oxi_states.sort()
                oxi_state = nearest_key(tab_oxi_states, oxi_state)
                radius = _ion_radii[el][str(oxi_state)][str(coord_no)]
            except KeyError:
                if coord_finder.get_coordination_number(i) - coord_no > 0:
                    new_coord_no = coord_no + 1
                else:
                    new_coord_no = coord_no - 1
                try:
                    radius = _ion_radii[el][str(oxi_state)][str(new_coord_no)]
                    coord_no = new_coord_no
                except:
                    tab_coords = map(int,
                                     _ion_radii[el][str(oxi_state)].keys())
                    tab_coords.sort()
                    new_coord_no = nearest_key(tab_coords, coord_no)
                    i = 0
                    for val in tab_coords:
                        if val > coord_no:
                            break
                        i = i + 1
                    if i == len(tab_coords):
                        key = str(tab_coords[-1])
                        radius = _ion_radii[el][str(oxi_state)][key]
                    elif i == 0:
                        key = str(tab_coords[0])
                        radius = _ion_radii[el][str(oxi_state)][key]
                    else:
                        key = str(tab_coords[i - 1])
                        radius1 = _ion_radii[el][str(oxi_state)][key]
                        key = str(tab_coords[i])
                        radius2 = _ion_radii[el][str(oxi_state)][key]
                        radius = (radius1 + radius2) / 2

            #implement complex checks later
            radii.append(radius)
        return radii
Пример #21
0
    def get_surface_sites(self, tag=False):
        """
        Returns the surface sites and their site indices in a dictionary. The oriented unit
        cell of the slab will determine the coordination number of a typical site. We use
        VoronoiCoordFinder to determine the coordination number of bulk sites and slab
        sites. Due to the pathological error resulting from some surface sites in the
        VoronoiCoordFinder, we assume any site that has this error is a surface site as well.
        This will work for elemental systems only for now. Useful for analysis involving
        broken bonds and for finding adsorption sites.

            Args:
                tag (bool): Option to adds site attribute "is_surfsite" (bool) to
                    all sites of slab. Defaults to False

            Returns:
                A dictionary grouping sites on top and bottom of the slab together.
                    {"top": [sites with indices], "bottom": [sites with indices}

        TODO:
            Is there a way to determine site equivalence between sites in a slab and sites
            in a bulk system? This would allow us get the coordination number of a specific
            site for multi-elemental systems or systems with more than one unequivalent sites
            This will allow us to use this for compound systems.
        """

        from pymatgen.analysis.structure_analyzer import VoronoiCoordFinder

        # Get a dictionary of coordination numbers for each distinct site in the structure
        a = SpacegroupAnalyzer(self.oriented_unit_cell)
        ucell = a.get_symmetrized_structure()
        cn_dict = {}
        v = VoronoiCoordFinder(ucell)
        unique_indices = [equ[0] for equ in ucell.equivalent_indices]

        for i in unique_indices:
            el = ucell[i].species_string
            if el not in cn_dict.keys():
                cn_dict[el] = []
            # Since this will get the cn as a result of the weighted polyhedra, the
            # slightest difference in cn will indicate a different environment for a
            # species, eg. bond distance of each neighbor or neighbor species. The
            # decimal place to get some cn to be equal.
            cn = v.get_coordination_number(i)
            cn = float('%.5f' %(round(cn, 5)))
            if cn not in cn_dict[el]:
                cn_dict[el].append(cn)

        v = VoronoiCoordFinder(self)

        surf_sites_dict, properties = {"top": [], "bottom": []}, []
        for i, site in enumerate(self):
            # Determine if site is closer to the top or bottom of the slab
            top = True if site.frac_coords[2] > self.center_of_mass[2] else False

            try:
                # A site is a surface site, if its environment does
                # not fit the environment of other sites
                cn = float('%.5f' %(round(v.get_coordination_number(i), 5)))
                if cn < min(cn_dict[site.species_string]):
                    properties.append(True)
                    key = "top" if top else "bottom"
                    surf_sites_dict[key].append([site, i])
                else:
                    properties.append(False)
            except RuntimeError:
                # or if pathological error is returned, indicating a surface site
                properties.append(True)
                key = "top" if top else "bottom"
                surf_sites_dict[key].append([site, i])

        if tag:
            self.add_site_property("is_surf_site", properties)
        return surf_sites_dict