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
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
def get_atom_ofms(self, struct, symm=False): """ Calls get_single_ofm for every site in struct. If symm=True, get_single_ofm is called for symmetrically distinct sites, and counts is constructed such that ofms[i] occurs counts[i] times in the structure Args: struct (Structure): structure for find ofms for symm (bool): whether to calculate ofm for only symmetrically distinct sites Returns: ofms ([32 X 32 matrix] X len(struct)): ofms for struct if symm: ofms ([32 X 32 matrix] X number of symmetrically distinct sites): ofms for struct counts: number of identical sites for each ofm """ ofms = [] vcf = VCF(struct, allow_pathological=True) if symm: symm_struct = SpacegroupAnalyzer(struct).get_symmetrized_structure() indices = [lst[0] for lst in symm_struct.equivalent_indices] counts = [len(lst) for lst in symm_struct.equivalent_indices] else: indices = [i for i in range(len(struct.sites))] for index in indices: ofms.append(self.get_single_ofm(struct.sites[index], \ vcf.get_voronoi_polyhedra(index))) if symm: return ofms, counts return ofms
def compute(self, structure, n): params = self._params vor = VoronoiCoordFinder(structure, **params) vorp = vor.get_voronoi_polyhedra(n) cdict = {} for i in vorp: if i.species_string not in cdict: cdict[i.species_string] = vorp[i] else: cdict[i.species_string] += vorp[i] return cdict
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)
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)
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)
def substructures_from_structure(structure, weight_cutoff=1e-2): """ Helper method to calculate substructural components from a pymatgen structure object. Args: structure (Structure): Input structure weight_cutoff (float): minimum solid angle weight for inclusion in a substructure Returns: A list of Substructure objects for the given structure """ vcf = VoronoiCoordFinder(structure) substructures = [] for i, site in enumerate(structure): charge = sum([getattr(specie, "oxi_state", 0) * amt for specie, amt in site.species_and_occu.items()]) central_subspecies = SubStructureSpecie(site.specie.symbol, oxidation_state=charge, properties=site.properties, weight=1.0) peripheral_subspecies = [] for peripheral_site, weight in vcf.get_voronoi_polyhedra(i).iteritems(): if weight > weight_cutoff: charge = sum([getattr(specie, "oxi_state", 0) * amt for specie, amt in peripheral_site.species_and_occu.items()]) peripheral_subspecies.append( SubStructureSpecie(peripheral_site.specie.symbol, oxidation_state=charge, properties=peripheral_site.properties, weight=weight)) substructures.append(SubStructure(peripheral_subspecies, central_sub_species=central_subspecies)) return substructures
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)
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)
spacegroup1 = SpacegroupAnalyzer(s1) 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)
def featurize(self, struct, idx): """ Get crystal fingerprint of site with given index in input structure. Args: struct (Structure): Pymatgen Structure object. idx (int): index of target site in structure. Returns: list of weighted order parameters of target site. """ cn_fingerprint_array = defaultdict( list ) # dict where key = CN, val is array that contains each OP for that CN total_weight = math.pi / 4 # 1/4 unit circle area target = None if self.cation_anion: target = [] m_oxi = struct[idx].specie.oxi_state for site in struct: if site.specie.oxi_state * m_oxi <= 0: # opposite charge target.append(site.specie) if not target: raise ValueError( "No valid targets for site within cation_anion constraint!" ) vcf = VoronoiCoordFinder(struct, cutoff=self.cutoff_radius, target=target) n_w = vcf.get_voronoi_polyhedra(idx) dist_sorted = (sorted(n_w.values(), reverse=True)) if self.override_cn1: cn1 = 1 for d in dist_sorted[1:]: cn1 = cn1 * (dist_sorted[0]**2 - d**2) / dist_sorted[0]**2 cn_fingerprint_array[1] = [round(cn1, 6)] dist_sorted[0] = dist_sorted[1] dist_norm = [d / dist_sorted[0] for d in dist_sorted if d > 0] dist_bins = [] # bin numerical tolerances (~error bar of measurement) for d in dist_norm: if not dist_bins or (d > self.tol and dist_bins[-1] / (1 + self.tol) > d): dist_bins.append(d) for dist_idx, dist in enumerate(dist_bins): neigh_sites = [ n for n, w in n_w.items() if w > 0 and w / dist_sorted[0] >= dist / (1 + self.tol) ] cn = len(neigh_sites) if cn in self.ops: for opidx, op in enumerate(self.ops[cn]): if self.optypes[cn][opidx] == "wt": opval = 1 else: opval = \ op.get_order_parameters([struct[idx]] + neigh_sites, 0, indices_neighs=[i for i in range(1, len( neigh_sites) + 1)])[ 0] opval = opval or 0 # handles None if self.optypes[cn][ opidx] == 'bcc': # TODO: remove after pymatgen update opval = opval / 0.976 # figure out the weight for this opval based on semicircle integration method x1 = 1 - dist x2 = 1 if dist_idx == len(dist_bins) - 1 else \ 1 - dist_bins[dist_idx + 1] weight = self._semicircle_integral(x2) - \ self._semicircle_integral(x1) opval = opval * weight / total_weight cn_fingerprint_array[cn].append(opval) # convert dict to list cn_fingerprint = [] for cn in sorted(self.optypes): for op_idx, _ in enumerate(self.optypes[cn]): try: cn_fingerprint.append(cn_fingerprint_array[cn][op_idx]) except IndexError: # no OP value computed cn_fingerprint.append(0) return cn_fingerprint