def guess_manifest_from_ingredient_metadata(self, ingdir, nebpc=0): """Guess the manifest name from the ingredient. Not for phonon manifests. Args: ingdir <str>: ingredient name, full path nebpc <int>: 0 for first endpoint (default) 1 for final endpoint Returns: manname <str>: manifest name guess; returns None if errors """ mymeta=Metadata(metafile="%s/metadata.txt" % (ingdir)) #phonon_label = mymeta.read_data("phonon_label") scaling_label = mymeta.read_data("scaling_label") neb_label = mymeta.read_data("neb_label") defect_label = mymeta.read_data("defect_label") if scaling_label == None: scaling_label="" if defect_label == None: if neb_label == None: defect_label="" else: if nebpc == 0: defect_label = neb_label.split("-")[0].strip() else: defect_label = neb_label.split("-")[1].strip() manname="%s/manifest_%s_%s_%s" % (self.sdir, scaling_label, defect_label, neb_label) return manname
def guess_manifest_from_ingredient_metadata(self, ingdir, nebpc=0): """Guess the manifest name from the ingredient. Not for phonon manifests. Args: ingdir <str>: ingredient name, full path nebpc <int>: 0 for first endpoint (default) 1 for final endpoint Returns: manname <str>: manifest name guess; returns None if errors """ mymeta = Metadata(metafile="%s/metadata.txt" % (ingdir)) #phonon_label = mymeta.read_data("phonon_label") scaling_label = mymeta.read_data("scaling_label") neb_label = mymeta.read_data("neb_label") defect_label = mymeta.read_data("defect_label") if scaling_label == None: scaling_label = "" if defect_label == None: if neb_label == None: defect_label = "" else: if nebpc == 0: defect_label = neb_label.split("-")[0].strip() else: defect_label = neb_label.split("-")[1].strip() manname = "%s/manifest_%s_%s_%s" % (self.sdir, scaling_label, defect_label, neb_label) return manname
def find_orig_frac_coord_in_atom_indices(self, coord, element="", scaling_label="", find_multiple=False, tol=0.0001): """Find the atomic index of an original FRACTIONAL coordinate in the structure dictionary. Args: coord <numpy array of float>: coordinate to find element <str>: element symbol to match If blank, matches any element. scaling_label <str>: scaling label If blank, must match NO scaling (blank) find_multiple <boolean>: allow multiple matches. Default False. tol <float>: tolerance Returns: atomic index <hex string>: atomic index of match, if find_multiple is false list of atomic indices of matches, if find_multiple is true Returns None if no match is found """ import glob matchstring = "%s/atom_index_*" % self.sdir idxnames = glob.glob(matchstring) rtol=tol*100 coord_matches=list() elem_matches=list() scaling_matches=list() for aname in idxnames: ameta=Metadata(metafile=aname) aidx=ameta.read_data("atom_index") atom_ofc=ameta.read_data("original_frac_coords") atom_ofc_arr=np.array(atom_ofc[1:-1].split(),'float') if np.allclose(atom_ofc_arr,coord,rtol,tol): coord_matches.append(aidx) if element == "": elem_matches = list(coord_matches) else: for aidx in coord_matches: ameta=Metadata(metafile="%s/atom_index_%s" % (self.sdir, aidx)) atom_elem=ameta.read_data("element") if (element == atom_elem): elem_matches.append(aidx) for aidx in elem_matches: ameta=Metadata(metafile="%s/atom_index_%s" % (self.sdir, aidx)) ascale=ameta.read_data("scaling_label") if (scaling_label == ascale): scaling_matches.append(aidx) allmatches = list(scaling_matches) if len(allmatches) == 0: return None if len(allmatches) > 1: if not find_multiple: raise MASTError(self.__class__.__name__, "Multiple matches found for coordinate %s: %s" % (coord, allmatches)) else: return allmatches if len(allmatches) == 1: if not find_multiple: return allmatches[0] else: return allmatches return None
def make_coordinate_and_element_list_from_manifest(self, manname, ing_label=""): """ Args: ing_label <str>: If blank, use orig_frac_coords. Otherwise, use <ing_label>_frac_coords """ if ing_label == "": ing_label = "original" coordlist = list() elemlist = list() mlist = list(self.read_manifest_file("%s/%s" % (self.sdir, manname))) for aidxline in mlist: aidxsplit = aidxline.split(";") aidx = aidxsplit[0] idxtorepl = "" if len(aidxsplit) > 1: idxtorepl = aidxsplit[1] ameta = Metadata(metafile="%s/atom_index_%s" % (self.sdir, aidx)) if idxtorepl == "": frac_coords = ameta.read_data("%s_frac_coords" % ing_label) if frac_coords == None: raise MASTError( self.__class__.__name__, "No coordinates for %s_frac_coords building from manifest %s/%s using atom index %s" % (ing_label, self.sdir, manname, aidx)) elif idxtorepl == "int": #interstitial frac_coords = ameta.read_data("original_frac_coords") if frac_coords == None: raise MASTError( self.__class__.__name__, "No coordinates for %s_frac_coords building from manifest %s/%s using atom index %s" % (ing_label, self.sdir, manname, aidx)) else: #substitution replmeta = Metadata(metafile="%s/atom_index_%s" % (self.sdir, idxtorepl)) frac_coords = replmeta.read_data("%s_frac_coords" % ing_label) if frac_coords == None: raise MASTError( self.__class__.__name__, "No coordinates for %s_frac_coords building from manifest %s/%s using atom index %s for coordinates and atom index %s for element" % (ing_label, self.sdir, manname, idxtorepl, aidx)) frac_coords = frac_coords.split("[")[1] frac_coords = frac_coords.split("]")[0] frac_array = np.array(frac_coords.split(), 'float') elem = ameta.read_data("element") coordlist.append(frac_array) elemlist.append(elem) return [coordlist, elemlist]
def make_temp_manifest_from_scrambled_structure(self, ingdir, mystr, scrambledman): """Make a temporary manifest from a scrambled structure. Args: ingdir <str>: Ingredient directory (need scaling label) mystr <pymatgen Structure>: Scrambled structure that does not match a manifest scrambledman <str>: Scrambled manifest list that the structure does match namelabel <str>: Parent label of frac coords to find Returns: writes to scrambledman """ mymeta = Metadata(metafile="%s/metadata.txt" % ingdir) scaling_label = mymeta.read_data("scaling_label") if scaling_label == None: scaling_label = "" scrambledlist = list() for site in mystr.sites: fidx = self.find_any_frac_coord_in_atom_indices( site.frac_coords, site.species_string, scaling_label, False, 0.002) scrambledlist.append(fidx) self.write_manifest_file(scrambledlist, scrambledman) return
def main(ingname=""): """Get the U value from an ingredient. Args: ingname <str>: Ingredient name, full path Returns: <string>: "LDAUU, LDAUJ (eV);x x x, x x x", ex: "LDAUU, LDAUJ (eV); 0 5 0, 0 1 0" """ trymeta = "%s/metadata.txt" % ingname frontstr = "LDAUU, LDAUJ (eV);" if os.path.isfile(trymeta): mymeta = Metadata(metafile=trymeta) myprogram = mymeta.read_data("program") else: myprogram = "None" if myprogram in ['vasp','vasp_neb']: if os.path.isdir("%s/01" % ingname): tryfile = "%s/01/OUTCAR" % ingname else: tryfile = "%s/OUTCAR" % ingname grepldauu = fileutil.grepme(tryfile, "LDAUU") if grepldauu == []: return "%s N/A" % frontstr ldauuparse = grepldauu[0].split("=")[1].strip() grepldauj = fileutil.grepme(tryfile, "LDAUJ") ldaujparse = grepldauj[0].split("=")[1].strip() return "%s %s, %s" % (frontstr, ldauuparse, ldaujparse) else: return "%s N/A" % frontstr
def main(ingname=""): """Get the last lattice from an ingredient. Args: ingname <str>: Ingredient name, full path Returns: <string>: "Last lattice (Angstroms);scale, a, b, c", ex: "Last lattice (Angstroms); scale 1, 4.01 0.2 0, 0 4.01 0, 0.1 0.1 4.01" """ trymeta = "%s/metadata.txt" % ingname frontstr = "Last lattice (Angstroms);" if os.path.isfile(trymeta): mymeta = Metadata(metafile=trymeta) myprogram = mymeta.read_data("program") else: myprogram = "None" if myprogram in ['vasp','vasp_neb']: if os.path.isdir("%s/01" % ingname): tryfile = "%s/01/CONTCAR" % ingname else: tryfile = "%s/CONTCAR" % ingname cfile = MASTFile(tryfile) if len(cfile.data) == 0: return "%s N/A" % frontstr scale = cfile.data[1].strip() avec = cfile.data[2].strip() bvec = cfile.data[3].strip() cvec = cfile.data[4].strip() return "%s scale %s, %s, %s, %s" % (frontstr, scale, avec, bvec, cvec) else: return "%s N/A" % frontstr
def main(ingname=""): """Get the energy from an ingredient. Args: ingname <str>: Ingredient name, full path Returns: <string>: "energy (eV);<energy as a string>", ex: "energy (eV); 3.0" Returns last E0 energy for a VASP run. Returns last E0 energy for all images for a VASP neb. Returns "N/A" otherwise. """ trymeta = "%s/metadata.txt" % ingname if os.path.isfile(trymeta): mymeta = Metadata(metafile=trymeta) myprogram = mymeta.read_data("program") else: myprogram = "None" if 'induce' in ingname: #skip inducedefect ingredients myprogram = "None" if 'vasp' in myprogram: if os.path.isdir("%s/01" % ingname): estr = "energies (eV)" for subdir in dirutil.immediate_subdirs(ingname): mychecker = VaspChecker(name="%s/%s" % (ingname, subdir)) estr = estr + ";%3.3f" % mychecker.get_energy_from_energy_file( ) return estr else: mychecker = VaspChecker(name=ingname) return "energy (eV);%3.3f" % mychecker.get_energy_from_energy_file( ) else: return "energy (eV);N/A"
def main(ingname=""): """Get the last pressure value from an ingredient. Args: ingname <str>: Ingredient name, full path Returns: <string>: "Last pressure (kbar);0.00", ex: "Last pressure (kbar);-23.55" """ trymeta = "%s/metadata.txt" % ingname frontstr = "Last pressure (kbar);" if os.path.isfile(trymeta): mymeta = Metadata(metafile=trymeta) myprogram = mymeta.read_data("program") else: myprogram = "None" if myprogram in ['vasp','vasp_neb']: if os.path.isdir("%s/01" % ingname): tryfile = "%s/01/OUTCAR" % ingname else: tryfile = "%s/OUTCAR" % ingname greppress = fileutil.grepme(tryfile, "external pressure") #"external pressure = -1.97 kB Pullay stress = 0.00 kB" if greppress == []: return "%s N/A" % frontstr mypress = greppress[-1].strip().split()[3] return "%s %s" % (frontstr, mypress) else: return "%s N/A" % frontstr
def main(ingname=""): """Get the last volume value from an ingredient. Args: ingname <str>: Ingredient name, full path Returns: <string>: "Last volume (Angstroms^3);0.000", ex: "Last volume (Angstroms^3); 324.456" """ trymeta = "%s/metadata.txt" % ingname frontstr = "Last volume (Angstroms^3);" if os.path.isfile(trymeta): mymeta = Metadata(metafile=trymeta) myprogram = mymeta.read_data("program") else: myprogram = "None" if myprogram in ['vasp','vasp_neb']: if os.path.isdir("%s/01" % ingname): tryfile = "%s/01/OUTCAR" % ingname else: tryfile = "%s/OUTCAR" % ingname grepvol = fileutil.grepme(tryfile, "volume of cell") if grepvol == []: return "%s N/A" % frontstr myvol = grepvol[-1].split(":")[1].strip() return "%s %s" % (frontstr, myvol) else: return "%s N/A" % frontstr
def main(ingname=""): """Get the energy from an ingredient. Args: ingname <str>: Ingredient name, full path Returns: <string>: "energy (eV);<energy as a string>", ex: "energy (eV); 3.0" Returns last E0 energy for a VASP run. Returns last E0 energy for all images for a VASP neb. Returns "N/A" otherwise. """ trymeta = "%s/metadata.txt" % ingname if os.path.isfile(trymeta): mymeta = Metadata(metafile=trymeta) myprogram = mymeta.read_data("program") else: myprogram = "None" if 'induce' in ingname: #skip inducedefect ingredients myprogram = "None" if 'vasp' in myprogram: if os.path.isdir("%s/01" % ingname): estr = "energies (eV)" for subdir in dirutil.immediate_subdirs(ingname): mychecker = VaspChecker(name="%s/%s" % (ingname, subdir)) estr = estr + ";%3.3f" % mychecker.get_energy_from_energy_file() return estr else: mychecker = VaspChecker(name=ingname) return "energy (eV);%3.3f" % mychecker.get_energy_from_energy_file() else: return "energy (eV);N/A"
def get_sd_array(self, ing_label, multiple=False): """Get a selective dynamics array. Args: ing_label <str>: Ingredient name (fullpath) multiple <bool>: Multiple (T F F, F T F, etc. for each atom and direction) or single (T T T for all indicated atoms) array """ mymeta=Metadata(metafile="%s/metadata.txt" % (ing_label)) phonon_label = mymeta.read_data("phonon_label") scaling_label = mymeta.read_data("scaling_label") if scaling_label == None: scaling_label = "" nord_label = phonon_label.split("_")[0] if "-" in nord_label: neb_label = nord_label defect_label = neb_label.split('-')[0] #always parse from first ep else: neb_label = "" defect_label = nord_label phonon_only_label = phonon_label.split("_")[-1] phononman="%s/manifest_phonon_sd_%s_%s_%s" % (self.sdir, nord_label, phonon_only_label, scaling_label) structureman="%s/manifest_%s_%s_%s" % (self.sdir, scaling_label, defect_label, neb_label) phononlist = self.read_manifest_file(phononman) structurelist = self.read_manifest_file(structureman) lensites=len(structurelist) if not multiple: mysd=np.zeros([lensites,3],bool) for lidx in range(0, lensites): if structurelist[lidx] in phononlist: mysd[lidx]=np.ones(3,bool) return mysd elif multiple: mysdlist=list() for lidx in range(0, lensites): for myct in range(0,3): mysd = np.zeros([lensites,3],bool) mysd[lidx]=np.zeros(3,bool) if structurelist[lidx] in phononlist: mysd[lidx][myct]=1 mysdlist.append(mysd) return mysdlist return
def __init__(self, allowed_keys, **kwargs): allowed_keys_base = dict() allowed_keys_base.update(allowed_keys) MASTObj.__init__(self, allowed_keys_base, **kwargs) work_dir = '/'.join(self.keywords['name'].split('/')[:-1]) topmeta = Metadata(metafile='%s/metadata.txt' % work_dir) data = topmeta.read_data(self.keywords['name'].split('/')[-1]) self.meta_dict = dict() if data: for datum in data.split(';'): self.meta_dict[datum.split(':')[0]] = datum.split(':')[1].strip() self.metafile = Metadata(metafile='%s/metadata.txt' % self.keywords['name']) self.program = self.keywords['program_keys']['mast_program'].lower() self.logger = loggerutils.get_mast_logger(self.keywords['name']) sdir=os.path.join(os.path.dirname(self.keywords['name']),"structure_index_files") if os.path.exists(sdir): self.atomindex = AtomIndex(structure_index_directory=sdir) else: self.atomindex = None if self.program == 'vasp': self.checker = VaspChecker(name=self.keywords['name'], program_keys = self.keywords['program_keys'], structure = self.keywords['structure']) self.errhandler = VaspError(name=self.keywords['name'], program_keys = self.keywords['program_keys'], structure = self.keywords['structure']) elif self.program == 'vasp_neb': self.checker = VaspNEBChecker(name=self.keywords['name'], program_keys = self.keywords['program_keys'], structure = self.keywords['structure']) self.errhandler = VaspNEBError(name=self.keywords['name'], program_keys = self.keywords['program_keys'], structure = self.keywords['structure']) elif self.program == 'phon': self.checker = PhonChecker(name=self.keywords['name'],program_keys=self.keywords['program_keys'],structure=self.keywords['structure']) self.errhandler = PhonError(name=self.keywords['name'],program_keys=self.keywords['program_keys'],structure=self.keywords['structure']) elif self.program == 'lammps': self.checker = LammpsChecker(name=self.keywords['name'],program_keys=self.keywords['program_keys'],structure=self.keywords['structure']) self.errhandler = GenericError(name=self.keywords['name'],program_keys=self.keywords['program_keys'],structure=self.keywords['structure']) elif self.program =='structopt': self.checker = StructoptChecker(name=self.keywords['name'],program_keys=self.keywords['program_keys'],structure=self.keywords['structure']) self.errhandler = GenericError(name=self.keywords['name'],program_keys=self.keywords['program_keys'],structure=self.keywords['structure']) else: allowed_keys={'name','program_keys','structure'} self.checker = GenericChecker(name=self.keywords['name'],program_keys=self.keywords['program_keys'],structure=self.keywords['structure']) self.errhandler = GenericError(name=self.keywords['name'],program_keys=self.keywords['program_keys'],structure=self.keywords['structure'])
def make_coordinate_and_element_list_from_manifest(self, manname, ing_label=""): """ Args: ing_label <str>: If blank, use orig_frac_coords. Otherwise, use <ing_label>_frac_coords """ if ing_label == "": ing_label = "original" coordlist=list() elemlist=list() mlist=list(self.read_manifest_file("%s/%s" % (self.sdir,manname))) for aidxline in mlist: aidxsplit=aidxline.split(";") aidx=aidxsplit[0] idxtorepl="" if len(aidxsplit) > 1: idxtorepl=aidxsplit[1] ameta = Metadata(metafile="%s/atom_index_%s" % (self.sdir, aidx)) if idxtorepl == "": frac_coords = ameta.read_data("%s_frac_coords" % ing_label) if frac_coords == None: raise MASTError(self.__class__.__name__, "No coordinates for %s_frac_coords building from manifest %s/%s using atom index %s" % (ing_label, self.sdir, manname, aidx)) elif idxtorepl == "int": #interstitial frac_coords = ameta.read_data("original_frac_coords") if frac_coords == None: raise MASTError(self.__class__.__name__, "No coordinates for %s_frac_coords building from manifest %s/%s using atom index %s" % (ing_label, self.sdir, manname, aidx)) else: #substitution replmeta = Metadata(metafile="%s/atom_index_%s" % (self.sdir, idxtorepl)) frac_coords = replmeta.read_data("%s_frac_coords" % ing_label) if frac_coords == None: raise MASTError(self.__class__.__name__, "No coordinates for %s_frac_coords building from manifest %s/%s using atom index %s for coordinates and atom index %s for element" % (ing_label, self.sdir, manname, idxtorepl,aidx)) frac_coords=frac_coords.split("[")[1] frac_coords=frac_coords.split("]")[0] frac_array = np.array(frac_coords.split(), 'float') elem = ameta.read_data("element") coordlist.append(frac_array) elemlist.append(elem) return [coordlist, elemlist]
def make_temp_manifest_from_scrambled_structure(self, ingdir, mystr, scrambledman): """Make a temporary manifest from a scrambled structure. Args: ingdir <str>: Ingredient directory (need scaling label) mystr <pymatgen Structure>: Scrambled structure that does not match a manifest scrambledman <str>: Scrambled manifest list that the structure does match namelabel <str>: Parent label of frac coords to find Returns: writes to scrambledman """ mymeta=Metadata(metafile="%s/metadata.txt" % ingdir) scaling_label = mymeta.read_data("scaling_label") if scaling_label == None: scaling_label="" scrambledlist=list() for site in mystr.sites: fidx=self.find_any_frac_coord_in_atom_indices(site.frac_coords, site.species_string, scaling_label, False, 0.002) scrambledlist.append(fidx) self.write_manifest_file(scrambledlist, scrambledman) return
def write_defected_atom_indices(self): """Write any additional defect atom indices and make manifests. """ defect_dict=self.input_options.get_item('defects','defects') if defect_dict == None: return None dlabels=defect_dict.keys() scales = self.scaling.keys() scales.append("") for scaling_label in scales: alist=list(self.read_manifest_file("%s/manifest_%s__" % (self.sdir, scaling_label))) if scaling_label == "": mySE=SE(struc_work1=self.startstr.copy()) else: mySE=SE(struc_work1=self.startstr.copy(), scaling_size=self.scaling[scaling_label]["mast_size"]) for dlabel in dlabels: dlist = list(alist) manname=os.path.join(self.sdir,"manifest_%s_%s_" % (scaling_label, dlabel)) dsubkeys=defect_dict[dlabel].keys() for dsubkey in dsubkeys: if "subdefect_" in dsubkey: dtype=defect_dict[dlabel][dsubkey]['type'] dcoords=defect_dict[dlabel][dsubkey]['coordinates'] delement=defect_dict[dlabel][dsubkey]['symbol'] if not (scaling_label == ""): dcoords = mySE.get_scaled_coordinates(dcoords) if dtype == "interstitial": didx=self.find_orig_frac_coord_in_atom_indices(dcoords, delement, scaling_label, False, 0.001) if didx == None: akey=self.get_new_key() aname="atom_index_%s" % akey aname = os.path.join(self.sdir, aname) ameta = Metadata(metafile=aname) ameta.write_data("atom_index",akey) ameta.write_data("original_frac_coords", dcoords) ameta.write_data("element", delement) ameta.write_data("scaling_label", scaling_label) dlist.append("%s;int" % akey) #interstitial label else: dlist.append("%s;int" % didx) elif dtype == "vacancy": didx=self.find_orig_frac_coord_in_atom_indices(dcoords, delement, scaling_label, False, 0.001) try: dlist.remove(didx) except ValueError: raise MASTError(self.__class__.__name__, "For defect %s, cannot remove atom index %s from list: %s" % (dlabel, didx, dlist)) elif dtype in ["substitution","antisite"]: didxlist=self.find_orig_frac_coord_in_atom_indices(dcoords, "", scaling_label, True, 0.001) #leave element empty; just search coords idxtorepl=list() for didx in didxlist: dmeta = Metadata(metafile="%s/atom_index_%s" % (self.sdir, didx)) dmetaelem = dmeta.read_data("element") if not (delement == dmetaelem): if didx in dlist: dlist.remove(didx) idxtorepl.append(didx) if len(idxtorepl) > 1: raise MASTError(self.__class__.__name__, "Interstitial %s is attempting to replace more than one atom: %s" % (dlabel, idxtorepl)) didxsub=self.find_orig_frac_coord_in_atom_indices(dcoords, delement, scaling_label, False, 0.001) #leave element empty; just search coords if didxsub == None: akey=self.get_new_key() aname="atom_index_%s" % akey aname = os.path.join(self.sdir, aname) ameta = Metadata(metafile=aname) ameta.write_data("atom_index",akey) ameta.write_data("original_frac_coords", dcoords) ameta.write_data("element", delement) #sub element here ameta.write_data("scaling_label", scaling_label) dlist.append("%s;%s" % (akey, idxtorepl[0])) else: dlist.append("%s;%s" % (didxsub, idxtorepl[0])) self.write_manifest_file(dlist, manname) return
def write_defected_atom_indices(self): """Write any additional defect atom indices and make manifests. """ defect_dict = self.input_options.get_item('defects', 'defects') if defect_dict == None: return None dlabels = defect_dict.keys() scales = self.scaling.keys() scales.append("") for scaling_label in scales: alist = list( self.read_manifest_file("%s/manifest_%s__" % (self.sdir, scaling_label))) if scaling_label == "": mySE = SE(struc_work1=self.startstr.copy()) else: mySE = SE( struc_work1=self.startstr.copy(), scaling_size=self.scaling[scaling_label]["mast_size"]) for dlabel in dlabels: dlist = list(alist) manname = os.path.join( self.sdir, "manifest_%s_%s_" % (scaling_label, dlabel)) dsubkeys = defect_dict[dlabel].keys() for dsubkey in dsubkeys: if "subdefect_" in dsubkey: dtype = defect_dict[dlabel][dsubkey]['type'] dcoords = defect_dict[dlabel][dsubkey]['coordinates'] delement = defect_dict[dlabel][dsubkey]['symbol'] if not (scaling_label == ""): dcoords = mySE.get_scaled_coordinates(dcoords) if dtype == "interstitial": didx = self.find_orig_frac_coord_in_atom_indices( dcoords, delement, scaling_label, False, 0.001) if didx == None: akey = self.get_new_key() aname = "atom_index_%s" % akey aname = os.path.join(self.sdir, aname) ameta = Metadata(metafile=aname) ameta.write_data("atom_index", akey) ameta.write_data("original_frac_coords", dcoords) ameta.write_data("element", delement) ameta.write_data("scaling_label", scaling_label) dlist.append("%s;int" % akey) #interstitial label else: dlist.append("%s;int" % didx) elif dtype == "vacancy": didx = self.find_orig_frac_coord_in_atom_indices( dcoords, delement, scaling_label, False, 0.001) try: dlist.remove(didx) except ValueError: raise MASTError( self.__class__.__name__, "For defect %s, cannot remove atom index %s from list: %s" % (dlabel, didx, dlist)) elif dtype in ["substitution", "antisite"]: didxlist = self.find_orig_frac_coord_in_atom_indices( dcoords, "", scaling_label, True, 0.001 ) #leave element empty; just search coords idxtorepl = list() for didx in didxlist: dmeta = Metadata(metafile="%s/atom_index_%s" % (self.sdir, didx)) dmetaelem = dmeta.read_data("element") if not (delement == dmetaelem): if didx in dlist: dlist.remove(didx) idxtorepl.append(didx) if len(idxtorepl) > 1: raise MASTError( self.__class__.__name__, "Interstitial %s is attempting to replace more than one atom: %s" % (dlabel, idxtorepl)) didxsub = self.find_orig_frac_coord_in_atom_indices( dcoords, delement, scaling_label, False, 0.001 ) #leave element empty; just search coords if didxsub == None: akey = self.get_new_key() aname = "atom_index_%s" % akey aname = os.path.join(self.sdir, aname) ameta = Metadata(metafile=aname) ameta.write_data("atom_index", akey) ameta.write_data("original_frac_coords", dcoords) ameta.write_data("element", delement) #sub element here ameta.write_data("scaling_label", scaling_label) dlist.append("%s;%s" % (akey, idxtorepl[0])) else: dlist.append("%s;%s" % (didxsub, idxtorepl[0])) self.write_manifest_file(dlist, manname) return
def find_any_frac_coord_in_atom_indices(self, coord, element="", scaling_label="", find_multiple=False, tol=0.0001): """Find the atomic index of any FRACTIONAL coordinate in the structure dictionary. Args: coord <numpy array of float>: coordinate to find element <str>: element symbol to match If blank, matches any element. scaling_label <str>: scaling label If blank, must match NO scaling (blank) find_multiple <boolean>: allow multiple matches. Default False. tol <float>: tolerance Returns: atomic index <hex string>: atomic index of match, if find_multiple is false list of atomic indices of matches, if find_multiple is true Returns None if no match is found """ import glob matchstring = "%s/atom_index_*" % self.sdir idxnames = glob.glob(matchstring) rtol = tol * 100 coord_matches = list() elem_matches = list() scaling_matches = list() namelist = list() allfolders = immediate_subdirs(os.path.dirname(self.sdir)) #ing dirs for folder in allfolders: namelist.append("%s_frac_coords" % folder) for nametofind in namelist: for aname in idxnames: ameta = Metadata(metafile=aname) aidx = ameta.read_data("atom_index") atom_ofc = ameta.read_data(nametofind) if atom_ofc == None: continue if ";" in atom_ofc: atom_ofc = atom_ofc.split( ';')[-1].strip() # get most updated atom_ofc_arr = np.array(atom_ofc[1:-1].split(), 'float') if np.allclose(atom_ofc_arr, coord, rtol, tol): coord_matches.append(aidx) if element == "": elem_matches = list(coord_matches) else: for aidx in coord_matches: ameta = Metadata(metafile="%s/atom_index_%s" % (self.sdir, aidx)) atom_elem = ameta.read_data("element") if (element == atom_elem): elem_matches.append(aidx) for aidx in elem_matches: ameta = Metadata(metafile="%s/atom_index_%s" % (self.sdir, aidx)) ascale = ameta.read_data("scaling_label") if (scaling_label == ascale): scaling_matches.append(aidx) allmatches = list(scaling_matches) allmatches = list(set(allmatches)) # get unique values if len(allmatches) == 0: return None if len(allmatches) > 1: if not find_multiple: raise MASTError( self.__class__.__name__, "Multiple matches found for coordinate %s: %s" % (coord, allmatches)) else: return allmatches if len(allmatches) == 1: if not find_multiple: return allmatches[0] else: return allmatches return None
class RecipeSetup(MASTObj): """Parses the personalized recipe file, creates the recipe plan object, and prepares the ingredient directories. Attributes: self.recipe_file <str>: Recipe file name self.input_options <InputOptions>: Input options for recipe self.structure <pymatgen Structure>: Initial structure in recipe self.work_dir <str>: Working (recipe) directory) self.logger <logging Logger>: Recipe-level log """ def __init__(self, **kwargs): MASTObj.__init__(self, ALLOWED_KEYS, **kwargs) self.recipe_file = self.keywords['recipeFile'] self.input_options = self.keywords['inputOptions'] self.structure = self.keywords['structure'] self.work_dir = self.keywords['workingDirectory'] self.logger = loggerutils.get_mast_logger("recipe setup %s" % self.work_dir) self.metafile = Metadata(metafile='%s/metadata.txt' % self.work_dir) self.logger.debug('Setting up the recipe based on the personal recipe contents passed in self.recipe_file') def get_my_ingredient_options(self, name, ingredient_type): """Creates the ingredient based on the ingredient type. Notes: GRJ 6/19/2013: If the ingredient has not be specified in the input file we create it here, and append on the defaults. In addition, the defaults are appended on here, rather than in InputParser (since each ingredient is made here this makes more sense). TTM 8/19/13: Unspecified ingredient is "default" """ self.logger.debug('Initializing ingredient %s of type %s' % (name, ingredient_type)) global_defaults = self.input_options.get_item('ingredients', 'global') if (ingredient_type not in self.input_options.get_section_keys('ingredients')): self.logger.debug('Ingredient type %s has not been specified in the input file.' % ingredient_type) self.logger.debug('Using defaults from ingredients_global.') self.input_options.set_item('ingredients', ingredient_type, global_defaults) else: self.logger.debug('Copying over defaults from ingredients_global for ingredient %s.' % ingredient_type) ing_opt = self.input_options.get_item('ingredients', ingredient_type) for glob_key, glob_value in global_defaults.items(): if glob_key not in ing_opt: ing_opt[glob_key] = glob_value self.input_options.set_item('ingredients', ingredient_type, ing_opt) #self.program = self.input_options.options['ingredients'][ingredient_type]['mast_program'] ingredient_name = os.path.join(self.work_dir, name) pkey_d = self.input_options.get_item('ingredients', ingredient_type).copy() mydata = self.metafile.read_data(os.path.basename(ingredient_name)).split(';') defect_label="" neb_label="" charge="" phonon_label="" if 'defect_' in name.lower(): for datum in mydata: if 'defect_label' in datum: defect_label = datum.split(':')[-1].strip() if not 'defects' in self.input_options.options.keys(): raise MASTError(self.__class__.__name__, "No defects section in input file. Error setting up recipe %s." % self.work_dir) defdict = self.input_options.get_item('defects','defects') if not defect_label in defdict.keys(): raise MASTError(self.__class__.__name__, "No such label %s found in the defects section dictionary." % defect_label) mydefdict = dict() mydefdict['mast_defect_settings'] = defdict[defect_label] pkey_d.update(mydefdict) break if defect_label == "": raise MASTError(self.__class__.__name__, "No defect label for %s found in ingredient's metadata.txt" % ingredient_name) if 'inducedefect' not in ingredient_type: if 'q=' in name.lower(): for datum in mydata: if 'charge' in datum: charge = int(datum.split(':')[-1]) pkey_d['mast_charge'] = charge break if 'neb_' in name.lower(): for datum in mydata: if 'neb_label' in datum: neb_label = datum.split(':')[-1].strip() if not 'neb' in self.input_options.options.keys(): raise MASTError(self.__class__.__name__, "No neb section in input file. Error setting up recipe %s." % self.work_dir) nebdict = self.input_options.get_item('neb','nebs') if not neb_label in nebdict.keys(): raise MASTError(self.__class__.__name__, "No such label %s found in the neb section dictionary." % neb_label) mynebdict = dict() mynebdict['mast_neb_settings'] = nebdict[neb_label] pkey_d.update(mynebdict) break if neb_label == "": raise MASTError(self.__class__.__name__, "No neb label for %s found in ingredient's metadata.txt" % ingredient_name) if 'neb' in name.lower(): pkey_d.update(self.input_options.options['neb']) #if 'phonon' in self.input_options.options.keys(): # pkey_d.update(self.input_options.options['phonon']) if 'phonon_' in name.lower(): for datum in mydata: if 'phonon_label' in datum: phonon_label = datum.split(':')[-1].strip() def_or_neb_label = phonon_label.split('_')[0] phonon_key = phonon_label.split('_')[-1] defdict = self.input_options.get_item('defects','defects') nebdict = self.input_options.get_item('neb','nebs') phdict=dict() if def_or_neb_label in defdict.keys(): phdict['mast_phonon_settings'] = defdict[def_or_neb_label]['phonon'][phonon_key] elif def_or_neb_label in nebdict.keys(): phdict['mast_phonon_settings'] = nebdict[def_or_neb_label]['phonon'][phonon_key] else: raise MASTError(self.__class__.__name__, "Neither defect nor neb dictionaries have phonon key %s for ingredient %s." % (phonon_key, name)) pkey_d.update(phdict) break if phonon_label == "": raise MASTError(self.__class__.__name__, "No phonon label for %s found in ingredient's metadata.txt" % ingredient_name) if 'chemical_potentials' in self.input_options.options.keys(): chempotdict=dict() chempotdict['mast_chemical_potentials']=self.input_options.options['chemical_potentials'] pkey_d.update(chempotdict) allopt=dict() allopt['name'] = ingredient_name #allopt['program'] = self.program allopt['structure'] = self.structure allopt['program_keys'] = pkey_d self.logger.debug(pkey_d) # change to debug level for logging return allopt def get_method_from_ingredient_type(self, ingredtype, methodtype=""): """Get write, ready, run, complete, and update methods from an ingredient type like volrelax_to_singlerun Args: ingredtype <str>: ingredient type methodtype <str>: method type ("mast_write_method", etc.) Returns: methodname <str>: method name ("write_default", etc.) """ raise NotImplementedError mdict=self.input_options.get_item("ingredients", ingredtype) if methodtype in mdict.keys(): return mdict[methodtype] else: mdict=self.input_options.get_item("ingredients","global") if methodtype in mdict.keys(): return mdict[methodtype] else: return None def create_recipe_plan(self): """Creates a recipe object which has the ingredients and dependency information """ import inspect #'GRJ DEBUG: %s.%s' % (self.__class__.__name__, inspect.stack()[0][3]) [how_to_update, parents_to_check, how_to_run] = ru.read_recipe(self.recipe_file) recipe_obj = RecipePlan(self.work_dir) ingredlist = how_to_run.keys() for ingred in ingredlist: self.update_top_meta_for_ingred(ingred) ingredtype = how_to_run[ingred] recipe_obj.ingredients[ingred]="I" #set all to initialized recipe_obj.ingred_input_options[ingred] = self.get_my_ingredient_options(ingred, ingredtype) if not os.path.isdir(os.path.join(self.work_dir, ingred)): self.create_ingredient(recipe_obj.ingred_input_options[ingred]) recipe_obj.write_methods[ingred] = self.get_method_list(ingredtype, "mast_write_method") recipe_obj.ready_methods[ingred] = self.get_method_list(ingredtype, "mast_ready_method") recipe_obj.run_methods[ingred] = self.get_method_list(ingredtype, "mast_run_method") recipe_obj.complete_methods[ingred] = self.get_method_list(ingredtype, "mast_complete_method") recipe_obj.update_methods[ingred] = dict() for ichild in how_to_update[ingred].keys(): updingredtype = how_to_update[ingred][ichild] recipe_obj.update_methods[ingred][ichild] = self.get_method_list(updingredtype, "mast_update_children_method") recipe_obj.parents_to_check = dict(parents_to_check) recipe_obj.summary_options = self.get_summary_options() return recipe_obj def update_top_meta_for_ingred(self, myingred): """Update the top metafile for an ingredient. Args: myingred <str>: ingredient name """ datalist=list() datalist.append("ingredient type: %s " % myingred) scaling = self.input_options.get_item('scaling') scalingsize = None if scaling: for sckeys in scaling.keys(): if sckeys in myingred: scalingsize = sckeys if scalingsize: datalist.append("scaling_label: %s" % scalingsize) #TTM add scaling label for atom index datalist.append("scaling_size: [%s]" % scaling[scalingsize]['mast_size']) kpoints = scaling[scalingsize]['mast_kpoints'] datalist.append("kpoints: %s" % kpoints) #if 'nbands' in scaling[scalingsize].keys(): # datalist.append("nbands: %s" % scaling[scalingsize]['nbands'][0]) if 'defect_' in myingred: if scaling: defectlabel = myingred.split('defect_')[1].split('_')[1] else: defectlabel = myingred.split('defect_')[1].split('_')[0] if defectlabel.isdigit(): defectlabel = "defect_" + defectlabel datalist.append("defect_label: %s" % defectlabel) if 'q=' in myingred: chargestr = myingred.split('q=')[1].split('_')[0] if chargestr[0] == 'p': chargelabel=chargestr[1:] elif chargestr[0] == 'n': chargelabel='-'+chargestr[1:] else: chargelabel=chargestr datalist.append("charge: %s" % chargelabel) if 'neb_' in myingred: if scaling: neblabel = myingred.split('neb_')[1].split('_')[1] else: neblabel = myingred.split('neb_')[1].split('_')[0] datalist.append("neb_label: %s" % neblabel) if 'phonon_' in myingred: labels = myingred.split('phonon_')[1].split('_') try: labels.remove('parse') except ValueError: pass if scaling: labels.remove(scalingsize) phononlabel = '_'.join(labels) datalist.append("defect_label: %s" % labels[0]) #Assume phonon_<S>_<N>_<Q>_<P> datalist.append("phonon_label: %s" % phononlabel) data=';'.join(datalist) self.metafile.write_data(myingred, data, 1) def create_ingredient(self, my_ingred_input_options): """Create the ingredient directory and metadata file. Args: my_ingred_input_options <Input Options>: single ingredient input options """ allowed_keys = { 'name' : (str, str(), 'Name of optimization directory'), 'program': (str, str(), 'DFT program, e.g. "vasp"'), 'program_keys': (dict, dict(), 'Dictionary of program keywords'), 'structure': (Structure, None, 'Pymatgen Structure object') } myingred = BaseIngredient(allowed_keys, name=my_ingred_input_options['name'], structure=my_ingred_input_options['structure'], program_keys=my_ingred_input_options['program_keys']) myingred.write_directory() return def start(self): """Starts the setup process, parse the recipe file Use the input options and recipe info to create directories and classes required """ if not self.recipe_file: raise MASTError(self.__class__.__name__, "Recipe contents are empty!") """if not os.path.exists(self.recipe_file): raise MASTError(self.__class__.__name__, "Recipe file not Found!")""" if not self.input_options: raise MASTError(self.__class__.__name__, "Input Options not provided!") #print 'DEBUG:, ingredients info =', #for ingredient, value in ingredients_info.items(): # print ingredient, value recipe_plan = self.create_recipe_plan() return recipe_plan def get_method_list(self, ingredtype, methodtype): """Get a method list. Methods should be of the form: methodname arguments where methodname is the method name, and arguments are the arguments, as though listed through a command line. For example, copy_file CONTCAR POSCAR Multiple methods may exist with the same keyword in the ingredients section, and all will be applied. Methods should be separated by a semicolon: mast_update_children_method copy_file CONTCAR POSCAR; softlink_file WAVECAR Args: ingredtype <str>: ingredient type methodtype <str>: method type ("mast_write_method", etc.) Returns: mlist <list>: nested list containing entries [[method1name, arg1, arg2,...],[method2name...],...] """ ioptdict=self.input_options.get_item("ingredients", ingredtype) if methodtype in ioptdict.keys(): unparsed = ioptdict[methodtype] else: globaldict=self.input_options.get_item("ingredients","global") if methodtype in globaldict.keys(): unparsed = globaldict[methodtype] else: raise MASTError(self.__class__.__name__,"No method type %s in either ingredient type %s or global ingredient." % (methodtype, ingredtype)) splitmethods = unparsed.split(";") mlist = list() #self.logger.info(splitmethods) for method_arg_item in splitmethods: method_arg_item = method_arg_item.strip() method_arg_list = shlex.split(method_arg_item) methodname = method_arg_list[0].strip() arglist = list() for argitem in method_arg_list[1:]: arglist.append(argitem.strip()) minputs = list() minputs.append(methodname) minputs.extend(arglist) mlist.append(minputs) #if not methodname in mdict.keys(): # mdict[methodname]=list(arglist) #else: # self.logger.warning("Duplicate entry in method %s for ingredient type %s; ignoring the duplicate." % (methodtype, ingredtype)) #self.logger.info(mlist) return mlist #return mdict def get_summary_options(self): """Get the summary options and give them to the recipe plan.""" sum_opts = dict() if 'summary' in self.input_options.options.keys(): sumkeys = self.input_options.get_section_keys("summary") for sumkey in sumkeys: sum_opts[sumkey] = self.input_options.get_item("summary",sumkey) return sum_opts
def _calculate_defect_formation_energies(self, scsize): perf_dirs = [] ingredients = self.recipe_plan.ingredients.keys() for i in range(len(ingredients)): if 'perfect' in ingredients[i]: perf_dirs.append(ingredients[i]) if len(perf_dirs) == 0: raise MASTError( self.__class__.__name__, "A perfect final directory (has no children and has the word 'perfect' in its name) could not be found. Check recipe %s for a perfect directory." % self.directory) def_dir = ru.read_recipe( self.input_options.get_item( "personal_recipe", "personal_recipe_list"))[1]['madelung_utility'] defects = self.input_options.get_item('defects', 'defects') chempot = self.input_options.get_item('chemical_potentials') for i in range(len(perf_dirs)): perf_meta = Metadata(metafile='%s/%s/metadata.txt' % (self.directory, perf_dirs[i])) if scsize == perf_meta.read_data('scaling_size'): perf_dir = perf_dirs[i] perfpath = os.path.join(self.directory, perf_dir) if os.path.isfile(os.path.join(perfpath, "vasprun.xml")): e_perf = pmg.io.vaspio.vasp_output.Vasprun( os.path.join(perfpath, "vasprun.xml")).final_energy else: e_perf = float( open(os.path.join( perfpath, "OSZICAR")).readlines()[-1].split('E0=')[1].split()[0]) efermi = self.get_fermi_energy(perf_dir) struct_perf = self.get_structure(perf_dir) perf_species = dict() for site in struct_perf: if (str(site.specie) not in perf_species): perf_species[str(site.specie)] = 1 else: perf_species[str(site.specie)] += 1 #print 'Perfect composition: ', perf_species #First Loop through the conditions for the defects for conditions, potentials in chempot.items(): self.e_defects[conditions] = dict() # Loop through each defect for ddir in sorted(def_dir): def_meta = Metadata(metafile='%s/%s/metadata.txt' % (self.directory, ddir)) if scsize == def_meta.read_data('scaling_size'): label = def_meta.read_data( 'defect_label') + '_q=' + def_meta.read_data('charge') charge = int(def_meta.read_data('charge')) if os.path.isfile( os.path.join(self.directory, ddir, "vasprun.xml")): energy = pmg.io.vaspio.vasp_output.Vasprun( self.directory + '/' + ddir + '/vasprun.xml').final_energy else: energy = float( open(self.directory + '/' + ddir + '/OSZICAR').readlines()[-1].split('E0=') [1].split()[0]) structure = self.get_structure(ddir) #if (label not in self.e_defects[conditions]): # self.e_defects[conditions][label] = list() # Find out how many atoms of each type are in the defects def_species = dict() for site in structure.sites: if (site.specie not in def_species): def_species[site.specie] = 1 else: def_species[site.specie] += 1 # Find the differences in the number of each atom type # between the perfect and the defect struct_diff = dict() for specie, number in def_species.items(): try: nperf = perf_species[str(specie)] except KeyError: nperf = 0 struct_diff[str(specie)] = number - nperf # Get the potential alignment correction alignment = self.get_potential_alignment(perf_dir, ddir) # Calculate the base DFE energy e_def = energy - e_perf # E_defect - E_perf for specie, number in struct_diff.items(): mu = potentials[str(specie)] e_def -= (number * mu) e_def += charge * (efermi + alignment ) # Add in the shift here! #print '%-15s%-5i%12.5f%12.5f%12.5f%12.5f' % (label.split('_')[1], charge, energy, e_perf, efermi, alignment) #print 'DFE = %f' % e_def self.e_defects[conditions][label] = e_def
def _calculate_defect_formation_energies(self,scsize): perf_dirs = [] ingredients = self.recipe_plan.ingredients.keys() for i in range(len(ingredients)): if 'perfect' in ingredients[i]: perf_dirs.append(ingredients[i]) if len(perf_dirs)==0: raise MASTError(self.__class__.__name__, "A perfect final directory (has no children and has the word 'perfect' in its name) could not be found. Check recipe %s for a perfect directory." % self.directory) def_dir = ru.read_recipe(self.input_options.get_item("personal_recipe","personal_recipe_list"))[1]['madelung_utility'] defects = self.input_options.get_item('defects', 'defects') chempot = self.input_options.get_item('chemical_potentials') for i in range(len(perf_dirs)): perf_meta = Metadata(metafile='%s/%s/metadata.txt' % (self.directory, perf_dirs[i])) if scsize == perf_meta.read_data('scaling_size'): perf_dir = perf_dirs[i] perfpath = os.path.join(self.directory, perf_dir) if os.path.isfile(os.path.join(perfpath,"vasprun.xml")): e_perf = pmg.io.vaspio.vasp_output.Vasprun(os.path.join(perfpath, "vasprun.xml")).final_energy else: e_perf = float(open(os.path.join(perfpath, "OSZICAR")).readlines()[-1].split('E0=')[1].split()[0]) efermi = self.get_fermi_energy(perf_dir) struct_perf = self.get_structure(perf_dir) perf_species = dict() for site in struct_perf: if (str(site.specie) not in perf_species): perf_species[str(site.specie)] = 1 else: perf_species[str(site.specie)] += 1 #print 'Perfect composition: ', perf_species #First Loop through the conditions for the defects for conditions, potentials in chempot.items(): self.e_defects[conditions] = dict() # Loop through each defect for ddir in sorted(def_dir): def_meta = Metadata(metafile='%s/%s/metadata.txt' % (self.directory, ddir)) if scsize == def_meta.read_data('scaling_size'): label = def_meta.read_data('defect_label')+'_q='+def_meta.read_data('charge') charge = int(def_meta.read_data('charge')) if os.path.isfile(os.path.join(self.directory, ddir, "vasprun.xml")): energy = pmg.io.vaspio.vasp_output.Vasprun(self.directory+'/'+ddir+'/vasprun.xml').final_energy else: energy = float(open(self.directory+'/'+ddir+'/OSZICAR').readlines()[-1].split('E0=')[1].split()[0]) structure = self.get_structure(ddir) #if (label not in self.e_defects[conditions]): # self.e_defects[conditions][label] = list() # Find out how many atoms of each type are in the defects def_species = dict() for site in structure.sites: if (site.specie not in def_species): def_species[site.specie] = 1 else: def_species[site.specie] += 1 # Find the differences in the number of each atom type # between the perfect and the defect struct_diff = dict() for specie, number in def_species.items(): try: nperf = perf_species[str(specie)] except KeyError: nperf = 0 struct_diff[str(specie)] = number - nperf # Get the potential alignment correction alignment = self.get_potential_alignment(perf_dir, ddir) # Calculate the base DFE energy e_def = energy - e_perf # E_defect - E_perf for specie, number in struct_diff.items(): mu = potentials[str(specie)] e_def -= (number * mu) e_def += charge * (efermi + alignment) # Add in the shift here! #print '%-15s%-5i%12.5f%12.5f%12.5f%12.5f' % (label.split('_')[1], charge, energy, e_perf, efermi, alignment) #print 'DFE = %f' % e_def self.e_defects[conditions][label] = e_def
def calculate_single_defect_formation_energy(self, mylabel, conditions, potentials): """Calculate one defect formation energy. Args: mylabel <str>: Defect label conditions <str>: Environment condition, e.g. "As-rich" potentials <dict of float>: Dictionary of chemical potentials, e.g.: potentials['As']=-6.0383 potentials['Ga']=-3.6080 potentials['Bi']=-4.5650 Returns: <float>: Defect formation energy """ pdir = self.dirs[mylabel]['perfect'] ddir = self.dirs[mylabel]['defected'] #Get perfect data perf_meta = Metadata(metafile='%s/%s/metadata.txt' % (self.recdir, pdir)) e_perf = self.get_total_energy(pdir) #e_perf = float(perf_meta.read_data('energy').split(',')[-1]) #Sometimes the energy is listed more than once. efermi = self.get_fermi_energy(pdir) struct_perf = self.get_structure(pdir) perf_species = dict() for site in struct_perf: if (str(site.specie) not in perf_species): perf_species[str(site.specie)] = 1 else: perf_species[str(site.specie)] += 1 #print 'Perfect composition: ', perf_species #Get defected data def_meta = Metadata(metafile='%s/%s/metadata.txt' % (self.recdir, ddir)) #print def_meta label = def_meta.read_data('defect_label') charge = int(def_meta.read_data('charge')) energy = self.get_total_energy(ddir) #energy = float(def_meta.read_data('energy').split(',')[-1]) structure = self.get_structure(ddir) if (label not in self.e_defects[conditions]): self.e_defects[conditions][label] = list() print 'Calculating DFEs for defect %s with charge %3i.' % (label, charge) def_species = dict() for site in structure.sites: if (site.specie not in def_species): def_species[site.specie] = 1 else: def_species[site.specie] += 1 # Find the differences in the number of each atom type # between the perfect and the defect struct_diff = dict() for specie, number in def_species.items(): try: nperf = perf_species[str(specie)] except KeyError: nperf = 0 struct_diff[str(specie)] = number - nperf # Get the potential alignment correction alignment = self.get_potential_alignment(pdir, ddir) # Calculate the base DFE energy e_def = energy - e_perf # E_defect - E_perf print "TTM DEBUG: e_def: ", e_def for specie, number in struct_diff.items(): mu = potentials[str(specie)] #print str(specie), mu, number e_def -= (number * mu) print "TTM DEBUG: number: ", number print "TTM DEBUG: mu: ", mu print "TTM DEBUG: e_def -= number*mu: ", e_def print "TTM DEBUG: charge: ", charge print "TTM DEBUG: alignment: ", alignment print "TTM DEBUG: efermi: ", efermi e_def += charge * (efermi + alignment) # Add in the shift here! print "TTM DEBUG: e_def += charge*(efermi + alignment): ", e_def #print '%-15s%-5i%12.5f%12.5f%12.5f%12.5f' % (label.split('_')[1], charge, energy, e_perf, efermi, alignment) print 'DFE = %f' % e_def self.e_defects[conditions][label].append( (charge, e_def) ) return