def convert_cd_to_de( cd, b_cse): """ As of pymatgen v2.0, ComputedDefect objects were deprecated in favor of DefectEntry objects in pymatgen.analysis.defects.core This function takes a ComputedDefect (either as a dict or object) and converts it into a DefectEntry object in order to handle legacy PyCDT creation within the current paradigm of PyCDT. :param cd (dict or ComputedDefect object): ComputedDefect as an object or as a dictionary :params b_cse (dict or ComputedStructureEntry object): ComputedStructureEntry of bulk entry associated with the ComputedDefect. :return: de (DefectEntry): Resulting DefectEntry object """ if type(cd) != dict: cd = cd.as_dict() if type(b_cse) != dict: b_cse = b_cse.as_dict() bulk_sc_structure = Structure.from_dict( b_cse["structure"]) #modify defect_site as required for Defect object, confirming site exists in bulk structure site_cls = cd["site"] defect_site = PeriodicSite.from_dict( site_cls) def_nom = cd["name"].lower() if "sub_" in def_nom or "as_" in def_nom: #modify site object for substitution site of Defect object site_cls["species"][0]["element"] = cd["name"].split("_")[2] defect_site = PeriodicSite.from_dict( site_cls) poss_deflist = sorted( bulk_sc_structure.get_sites_in_sphere(defect_site.coords, 0.1, include_index=True), key=lambda x: x[1]) if len(poss_deflist) != 1: raise ValueError("ComputedDefect to DefectEntry conversion failed. " "Could not determine periodic site position in bulk supercell.") # create defect object if "vac_" in def_nom: defect_obj = Vacancy(bulk_sc_structure, defect_site, charge=cd["charge"]) elif "as_" in def_nom or "sub_" in def_nom: defect_obj = Substitution(bulk_sc_structure, defect_site, charge=cd["charge"]) elif "int_" in def_nom: defect_obj = Interstitial(bulk_sc_structure, defect_site, charge=cd["charge"]) else: raise ValueError("Could not recognize defect type for {}".format( cd["name"])) # assign proper energy and parameter metadata uncorrected_energy = cd["entry"]["energy"] - b_cse["energy"] def_path = os.path.split( cd["entry"]["data"]["locpot_path"])[0] bulk_path = os.path.split( b_cse["data"]["locpot_path"])[0] p = {"defect_path": def_path, "bulk_path": bulk_path, "encut": cd["entry"]["data"]["encut"]} de = DefectEntry( defect_obj, uncorrected_energy, parameters = p) return de
def get_connected_sites(self, n, jimage=(0, 0, 0)): """ Returns a named tuple of neighbors of site n: periodic_site, jimage, index, weight. Index is the index of the corresponding site in the original structure, weight can be None if not defined. :param n: index of Site in Structure :param jimage: lattice vector of site :return: list of ConnectedSite tuples, sorted by closest first """ connected_sites = set() out_edges = [(u, v, d, 'out') for u, v, d in self.graph.out_edges(n, data=True)] in_edges = [(u, v, d, 'in') for u, v, d in self.graph.in_edges(n, data=True)] for u, v, d, dir in out_edges + in_edges: to_jimage = d['to_jimage'] if dir == 'in': u, v = v, u to_jimage = np.multiply(-1, to_jimage) site_d = self.structure[v].as_dict() site_d['abc'] = np.add(site_d['abc'], to_jimage).tolist() to_jimage = tuple(map(int, np.add(to_jimage, jimage))) periodic_site = PeriodicSite.from_dict(site_d) weight = d.get('weight', None) # from_site if jimage arg != (0, 0, 0) relative_jimage = np.subtract(to_jimage, jimage) dist = self.structure[u].distance(self.structure[v], jimage=relative_jimage) connected_site = ConnectedSite(periodic_site=periodic_site, jimage=to_jimage, index=v, weight=weight, dist=dist) connected_sites.add(connected_site) # return list sorted by closest sites first connected_sites = list(connected_sites) connected_sites.sort(key=lambda x: x.dist) return connected_sites