Example #1
0
 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
Example #2
0
 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
Example #3
0
 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
Example #4
0
 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]
Example #5
0
    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
Example #6
0
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
Example #7
0
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
Example #8
0
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"
Example #9
0
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
Example #10
0
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
Example #11
0
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"
Example #12
0
 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
Example #13
0
    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'])
Example #14
0
 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]
Example #15
0
    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
Example #16
0
 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 
Example #17
0
    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
Example #18
0
 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
Example #19
0
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
Example #20
0
    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
Example #21
0
    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 
Example #22
0
    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