def test_scale_structure_nine(self): hcp = pymatgen.io.vaspio.Poscar.from_file("POSCAR_HCP").structure sxtend = StructureExtensions(struc_work1=hcp, scaling_size="2 0 0,0 2 0,0 0 2", name=testdir) scaled = sxtend.scale_structure() self.assertEqual(scaled, pymatgen.io.vaspio.Poscar.from_file("POSCAR_HCP_222").structure) self.assertEqual(scaled.lattice, pymatgen.io.vaspio.Poscar.from_file("POSCAR_HCP_222").structure.lattice) self.assertEqual(scaled.sites.sort(), pymatgen.io.vaspio.Poscar.from_file("POSCAR_HCP_222").structure.sites.sort())
def _vasp_poscar_setup(self): """Set up the POSCAR file for a single VASP run. """ name = self.keywords['name'] pospath = os.path.join(name, "POSCAR") if os.path.isfile(pospath): my_poscar = Poscar.from_file(pospath) #parent should have given a structure else: #this is an originating run; mast should give it a structure if self.keywords['structure'] is not None: my_poscar = Poscar(self.keywords['structure']) else: pf = os.path.join(os.path.dirname(name),'POSCAR_%s'%os.path.basename(name)) if os.path.isfile(pf): my_poscar = Poscar.from_file(pf) workdir=os.path.dirname(name) sdir=os.path.join(workdir,"structure_index_files") if os.path.exists(sdir): mystr=my_poscar.structure manname="manifest___" myatomindex=AtomIndex(structure_index_directory=sdir) newstr=myatomindex.graft_new_coordinates_from_manifest(mystr, manname, "") self.logger.info("Getting original coordinates from manifest.") new_pos=Poscar(newstr) my_poscar=new_pos self.logger.info("No POSCAR found from a parent; base structure used for %s" % self.keywords['name']) if 'mast_coordinates' in self.keywords['program_keys'].keys(): sxtend = StructureExtensions(struc_work1=my_poscar.structure, name=self.keywords['name']) coordstrucs=self.get_coordinates_only_structure_from_input() newstruc = sxtend.graft_coordinates_onto_structure(coordstrucs[0]) my_poscar.structure=newstruc.copy() dirutil.lock_directory(name) my_poscar.write_file(pospath) dirutil.unlock_directory(name) return my_poscar
def write_undefected_atom_indices(self): """Write undefected atom indices, including scaled indices. Also write an undefected manifest file. """ scales = self.scaling.keys() scales.append("") for scaling_label in scales: if scaling_label == "": mySE=SE(struc_work1=self.startstr.copy()) mystruc=mySE.keywords['struc_work1'] else: mySE=SE(struc_work1=self.startstr.copy(), scaling_size=self.scaling[scaling_label]["mast_size"]) mystruc=mySE.scale_structure() alist=list() manname=os.path.join(self.sdir,"manifest_%s__" % scaling_label) for site in mystruc: 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", site.frac_coords) ameta.write_data("element", site.species_string) ameta.write_data("scaling_label", scaling_label) alist.append(akey) self.write_manifest_file(alist,manname) return
def write_neb_phonon_sd_manifests(self): """Make NEB phonon manifests. """ neb_dict = self.input_options.get_item('neb', 'nebs') if neb_dict == None: return None nlabels = neb_dict.keys() scales = self.scaling.keys() scales.append("") for scaling_label in scales: 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 nlabel in nlabels: pdict = dict(neb_dict[nlabel]["phonon"]) for phonon_label in pdict.keys(): pcoordsraw = pdict[phonon_label]['phonon_center_site'] pthresh = pdict[phonon_label]['threshold'] pcrad = pdict[phonon_label]['phonon_center_radius'] pcoords = np.array(pcoordsraw.split(), 'float') if not (scaling_label == ""): pcoords = mySE.get_scaled_coordinates(pcoords) #pindices = self.find_orig_frac_coord_in_structure_dictionary(sdict, pcoords, pthresh+pcrad, True) pindices = self.find_orig_frac_coord_in_atom_indices( pcoords, "", scaling_label, True, 0.001 + pcrad) manname = os.path.join( self.sdir, "manifest_phonon_sd_%s_%s_%s" % (nlabel, phonon_label, scaling_label)) self.write_manifest_file(pindices, manname) return
def write_undefected_atom_indices(self): """Write undefected atom indices, including scaled indices. Also write an undefected manifest file. """ scales = self.scaling.keys() scales.append("") for scaling_label in scales: if scaling_label == "": mySE = SE(struc_work1=self.startstr.copy()) mystruc = mySE.keywords['struc_work1'] else: mySE = SE( struc_work1=self.startstr.copy(), scaling_size=self.scaling[scaling_label]["mast_size"]) mystruc = mySE.scale_structure() alist = list() manname = os.path.join(self.sdir, "manifest_%s__" % scaling_label) for site in mystruc: 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", site.frac_coords) ameta.write_data("element", site.species_string) ameta.write_data("scaling_label", scaling_label) alist.append(akey) self.write_manifest_file(alist, manname) return
def write_neb_phonon_sd_manifests(self): """Make NEB phonon manifests. """ neb_dict=self.input_options.get_item('neb','nebs') if neb_dict == None: return None nlabels=neb_dict.keys() scales = self.scaling.keys() scales.append("") for scaling_label in scales: 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 nlabel in nlabels: pdict = dict(neb_dict[nlabel]["phonon"]) for phonon_label in pdict.keys(): pcoordsraw = pdict[phonon_label]['phonon_center_site'] pthresh = pdict[phonon_label]['threshold'] pcrad = pdict[phonon_label]['phonon_center_radius'] pcoords = np.array(pcoordsraw.split(),'float') if not (scaling_label == ""): pcoords = mySE.get_scaled_coordinates(pcoords) #pindices = self.find_orig_frac_coord_in_structure_dictionary(sdict, pcoords, pthresh+pcrad, True) pindices = self.find_orig_frac_coord_in_atom_indices(pcoords,"",scaling_label,True,0.001+pcrad) manname=os.path.join(self.sdir,"manifest_phonon_sd_%s_%s_%s" % (nlabel, phonon_label, scaling_label)) self.write_manifest_file(pindices, manname) return
def test_strain_lattice(self): perfect = pymatgen.io.vaspio.Poscar.from_file("POSCAR_unstrained").structure sxtend = StructureExtensions(struc_work1=perfect) strained = sxtend.strain_lattice(" 0.98 0.92 1.03 \n") strain_compare = pymatgen.io.vaspio.Poscar.from_file("POSCAR_strained").structure self.assertEqual(strained, strain_compare) self.assertEqual(strained.lattice, strain_compare.lattice) self.assertEqual(strained.sites, strain_compare.sites)
def test_scale_structure(self): size = '1 1 0,-1 1 0,0 0 1' perfect = pymatgen.io.vaspio.Poscar.from_file("POSCAR_perfect").structure sxtend = StructureExtensions(struc_work1=perfect,scaling_size=size) scaled = sxtend.scale_structure() self.assertEqual(scaled, pymatgen.io.vaspio.Poscar.from_file("POSCAR_scaled").structure) self.assertEqual(scaled.lattice, pymatgen.io.vaspio.Poscar.from_file("POSCAR_scaled").structure.lattice) self.assertEqual(scaled.sites.sort(), pymatgen.io.vaspio.Poscar.from_file("POSCAR_scaled").structure.sites.sort())
def test_graft_coordinates(self): perfect = pymatgen.io.vaspio.Poscar.from_file("POSCAR_perfect").structure coordsonly = pymatgen.io.vaspio.Poscar.from_file("POSCAR_coordinates").structure compare_grafted = pymatgen.io.vaspio.Poscar.from_file("POSCAR_grafted").structure sxtend = StructureExtensions(struc_work1=perfect) grafted = sxtend.graft_coordinates_onto_structure(coordsonly) self.assertEqual(grafted, compare_grafted) self.assertEqual(grafted.lattice, compare_grafted.lattice) self.assertEqual(grafted.sites, compare_grafted.sites)
def test_get_sd_array_periodic_boundary(self): perfect = pymatgen.io.vaspio.Poscar.from_file("POSCAR_perfect").structure sxtend = StructureExtensions(struc_work1=perfect, name=testdir) mysd = sxtend.get_sd_array("0.95 0.95 0.95", 1, 0.07) #print mysd myarr=np.zeros([40,3],bool) for idx in [1]: myarr[idx-1][0]=True myarr[idx-1][1]=True myarr[idx-1][2]=True self.assertEqual(sum(np.fabs(sum(mysd-myarr))),0)
def test_get_sd_array(self): perfect = pymatgen.io.vaspio.Poscar.from_file("POSCAR_perfect").structure sxtend = StructureExtensions(struc_work1=perfect, name=testdir) mysd = sxtend.get_sd_array("0.5 0.5 0.5", 3) #print mysd myarr=np.zeros([40,3],bool) for idx in [8,20,25,26,28,30,32,33,36,37,38,39,40]: myarr[idx-1][0]=True myarr[idx-1][1]=True myarr[idx-1][2]=True self.assertEqual(sum(np.fabs(sum(mysd-myarr))),0)
def test_interpolation(self): ep1 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_ep1").structure ep2 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_ep2").structure compare_im1 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_im1").structure compare_im2 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_im2").structure compare_im3 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_im3").structure sxtend = StructureExtensions(struc_work1 = ep1, struc_work2 = ep2) slist = sxtend.do_interpolation(3) self.assertEqual(slist[0],ep1) self.assertEqual(slist[1],compare_im1) self.assertEqual(slist[2],compare_im2) self.assertEqual(slist[3],compare_im3) self.assertEqual(slist[4],ep2)
def test_multiple_sd_array(self): perfect = pymatgen.io.vaspio.Poscar.from_file("POSCAR_perfect").structure sxtend = StructureExtensions(struc_work1=perfect, name=testdir) mysdlist = sxtend.get_multiple_sd_array("0.5 0.5 0.5", 1) mylist=list() mylist.append(np.zeros([40,3],bool)) mylist.append(np.zeros([40,3],bool)) mylist.append(np.zeros([40,3],bool)) mylist[0][8-1][0]=True mylist[1][8-1][1]=True mylist[2][8-1][2]=True self.assertEqual(sum(np.fabs(sum(mysdlist[0]-mylist[0]))),0) self.assertEqual(sum(np.fabs(sum(mysdlist[1]-mylist[1]))),0) self.assertEqual(sum(np.fabs(sum(mysdlist[2]-mylist[2]))),0)
def set_up_neb_folders(self, image_structures): """Set up NEB folders. Args: image_structures <list of Structure>: List of image structures """ imct = 0 myname = self.keywords['name'] if 'mast_coordinates' in self.keywords['program_keys'].keys(): coordstrucs = self.get_coordinates_only_structure_from_input() newstrucs = list() sidx = 0 #ex. coordstrucs 0, 1, 2 for 3 images while sidx < self.keywords['program_keys']['mast_neb_settings'][ 'images']: sxtend = StructureExtensions( struc_work1=image_structures[sidx + 1].copy(), name=self.keywords['name']) newstrucs.append( sxtend.graft_coordinates_onto_structure(coordstrucs[sidx])) sidx = sidx + 1 while imct < len(image_structures): imposcar = Poscar(image_structures[imct]) num_str = str(imct).zfill(2) impath = os.path.join(myname, num_str) impospath = os.path.join(myname, "POSCAR_" + num_str) if 'mast_coordinates' in self.keywords['program_keys'].keys(): if imct == 0: #skip endpoint pass elif imct == len(image_structures) - 1: #skip other endpt pass else: imposcar.structure = newstrucs[imct - 1].copy() dirutil.lock_directory(myname) self.write_poscar_with_zero_velocities(imposcar, impospath) dirutil.unlock_directory(myname) try: os.makedirs(impath) except OSError: self.logger.warning("Directory at %s already exists." % impath) return None dirutil.lock_directory(impath) self.write_poscar_with_zero_velocities( imposcar, os.path.join(impath, "POSCAR")) dirutil.unlock_directory(impath) imct = imct + 1 return
def test_scale_structure(self): size = '1 1 0,-1 1 0,0 0 1' perfect = pymatgen.io.vaspio.Poscar.from_file( "POSCAR_perfect").structure sxtend = StructureExtensions(struc_work1=perfect, scaling_size=size) scaled = sxtend.scale_structure() self.assertEqual( scaled, pymatgen.io.vaspio.Poscar.from_file("POSCAR_scaled").structure) self.assertEqual( scaled.lattice, pymatgen.io.vaspio.Poscar.from_file( "POSCAR_scaled").structure.lattice) self.assertEqual( scaled.sites.sort(), pymatgen.io.vaspio.Poscar.from_file( "POSCAR_scaled").structure.sites.sort())
def set_up_neb_folders(self, image_structures): """Set up NEB folders. Args: image_structures <list of Structure>: List of image structures """ imct=0 myname = self.keywords['name'] if 'mast_coordinates' in self.keywords['program_keys'].keys(): coordstrucs=self.get_coordinates_only_structure_from_input() newstrucs=list() sidx = 0 #ex. coordstrucs 0, 1, 2 for 3 images while sidx < self.keywords['program_keys']['mast_neb_settings']['images']: sxtend = StructureExtensions(struc_work1=image_structures[sidx+1].copy(), name=self.keywords['name']) newstrucs.append(sxtend.graft_coordinates_onto_structure(coordstrucs[sidx])) sidx = sidx + 1 while imct < len(image_structures): imposcar = Poscar(image_structures[imct]) num_str = str(imct).zfill(2) impath = os.path.join(myname, num_str) impospath = os.path.join(myname, "POSCAR_" + num_str) if 'mast_coordinates' in self.keywords['program_keys'].keys(): if imct == 0: #skip endpoint pass elif imct == len(image_structures)-1: #skip other endpt pass else: imposcar.structure=newstrucs[imct-1].copy() dirutil.lock_directory(myname) imposcar.write_file(impospath) dirutil.unlock_directory(myname) try: os.makedirs(impath) except OSError: self.logger.warning("Directory at %s already exists." % impath) return None dirutil.lock_directory(impath) imposcar.write_file(os.path.join(impath, "POSCAR")) dirutil.unlock_directory(impath) imct = imct + 1 return
def test_sort_structure_and_neb_lines_really_scrambled(self): raise SkipTest neblines = list() neblines.append(["Cr","0.0 0.9 0.8","0.0 0.8 0.7"]) neblines.append(["Cr","0.4 0.2 0.1","0.3 0.3 0.2"]) neblines.append(["Cr","0.29 0.05 0.05","0.01 0.01 0.98"]) neblines.append(["Ni","0.61 0.99 0.98","0.25 0.01 0.97"]) perfect3 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_defectgroup3_scrambled").structure #print perfect3.get_sorted_structure() #print perfect4.get_sorted_structure() sxtend3 = StructureExtensions(struc_work1=perfect3) sorted3 = sxtend3.sort_structure_and_neb_lines(neblines,"00",3) compare_sorted3 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_sorted3").structure self.assertEqual(sorted3, compare_sorted3) self.assertEqual(sorted3.lattice, compare_sorted3.lattice) self.assertEqual(sorted3.sites, compare_sorted3.sites) perfect3 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_defectgroup3_really_scrambled").structure #print perfect3.get_sorted_structure() #print perfect4.get_sorted_structure() sxtend3 = StructureExtensions(struc_work1=perfect3) sorted3 = sxtend3.sort_structure_and_neb_lines(neblines,"00",3) compare_sorted3 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_sorted3").structure self.assertEqual(sorted3, compare_sorted3) self.assertEqual(sorted3.lattice, compare_sorted3.lattice) self.assertEqual(sorted3.sites, compare_sorted3.sites)
def test_scale_defect(self): perfect = pymatgen.io.vaspio.Poscar.from_file("POSCAR_perfect").structure scalingsize = "2,2,2" sxtend = StructureExtensions(struc_work1=perfect, scaling_size=scalingsize, name=testdir) scaled = sxtend.scale_structure() sxtend2 = StructureExtensions(struc_work1=scaled, struc_work2=perfect, scaling_size=scalingsize, name=testdir) vac1={'symbol':'O', 'type': 'vacancy', 'coordinates': np.array([0.25, 0.75, 0.25])} defected = sxtend2.scale_defect(vac1,'fractional',0.0001) int1={'symbol':'Ni', 'type': 'interstitial', 'coordinates': np.array([0.3, 0.3, 0.3])} sxtend3 = StructureExtensions(struc_work1=defected, struc_work2=perfect, scaling_size=scalingsize, name=testdir) defected2 = sxtend3.scale_defect(int1,'fractional',0.0001) sub1={'symbol':'Fe', 'type': 'substitution','coordinates':np.array([0.25, 0.25,0.75])} sxtend4 = StructureExtensions(struc_work1=defected2, struc_work2=perfect, scaling_size=scalingsize, name=testdir) defected3 = sxtend4.scale_defect(sub1,'fractional',0.0001) self.assertEqual(pymatgen.io.vaspio.Poscar.from_file("POSCAR_scaled_defected").structure, defected3)
def test_induce_defect_frac(self): perfect = pymatgen.io.vaspio.Poscar.from_file("POSCAR_perfect").structure compare_vac1 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_vac1").structure compare_int1 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_int1").structure compare_sub1 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_sub1").structure coord_type='fractional' threshold=1.e-4 vac1={'symbol':'O', 'type': 'vacancy', 'coordinates': np.array([0.25, 0.75, 0.25])} int1={'symbol':'Ni', 'type': 'interstitial', 'coordinates': np.array([0.3, 0.3, 0.3])} sub1={'symbol':'Fe', 'type': 'substitution','coordinates':np.array([0.25, 0.25,0.75])} sxtend = StructureExtensions(struc_work1=perfect) struc_vac1 = sxtend.induce_defect(vac1, coord_type, threshold) struc_int1 = sxtend.induce_defect(int1, coord_type, threshold) struc_sub1 = sxtend.induce_defect(sub1, coord_type, threshold) self.assertEqual(struc_vac1,compare_vac1) self.assertEqual(struc_int1,compare_int1) self.assertEqual(struc_sub1,compare_sub1) self.assertEqual(struc_vac1.lattice,compare_vac1.lattice) self.assertEqual(struc_int1.lattice,compare_int1.lattice) self.assertEqual(struc_sub1.lattice,compare_sub1.lattice) self.assertEqual(struc_vac1.sites,compare_vac1.sites) self.assertEqual(struc_int1.sites,compare_int1.sites) self.assertEqual(struc_sub1.sites,compare_sub1.sites)
def write_neb_endpoint_manifests(self): """Make NEB endpoint manifests. """ neb_dict = self.input_options.get_item('neb', 'nebs') if neb_dict == None: return None nlabels = neb_dict.keys() scales = self.scaling.keys() scales.append("") for scaling_label in scales: 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 nlabel in nlabels: def1 = nlabel.split("-")[0].strip() def2 = nlabel.split("-")[1].strip() manname1 = os.path.join( self.sdir, "manifest_%s_%s_%s" % (scaling_label, def1, nlabel)) manname2 = os.path.join( self.sdir, "manifest_%s_%s_%s" % (scaling_label, def2, nlabel)) mlist1raw = list( self.read_manifest_file("%s/manifest_%s_%s_" % (self.sdir, scaling_label, def1))) mlist2raw = list( self.read_manifest_file("%s/manifest_%s_%s_" % (self.sdir, scaling_label, def2))) mlist1 = list() mlist2 = list() for mitem in mlist1raw: #clean up leftover semicolons from defect manifests if ";" in mitem: mlist1.append(mitem.split(";")[0]) else: mlist1.append(mitem) for mitem in mlist2raw: #clean up leftover semicolons from defect manifests if ";" in mitem: mlist2.append(mitem.split(";")[0]) else: mlist2.append(mitem) maddtoend1 = list() maddtoend2 = list() nlines = list(neb_dict[nlabel]["lines"]) for nline in nlines: ncoord1 = np.array(nline[1].split(), 'float') ncoord2 = np.array(nline[2].split(), 'float') if not (scaling_label == ""): ncoord1 = mySE.get_scaled_coordinates(ncoord1) ncoord2 = mySE.get_scaled_coordinates(ncoord2) nelem = nline[0] nidx1 = self.find_orig_frac_coord_in_atom_indices( ncoord1, nelem, scaling_label, False, 0.001) nidx2 = self.find_orig_frac_coord_in_atom_indices( ncoord2, nelem, scaling_label, False, 0.001) try: mlist1.remove(nidx1) except ValueError: raise MASTError( self.__class__.__name__, "For neb %s, cannot remove atom index %s from mlist1: %s" % (nlabel, nidx1, mlist1)) maddtoend1.append(nidx1) #resort matches to the bottom try: mlist2.remove(nidx2) except ValueError: raise MASTError( self.__class__.__name__, "For neb %s, cannot remove atom index %s from mlist2: %s" % (nlabel, nidx2, mlist2)) maddtoend2.append(nidx2) if not (mlist1 == mlist2): raise MASTError( "NEB %s truncated manifests do not match: %s, %s" % (nlabel, mlist1, mlist2)) mlist1.extend(maddtoend1) mlist2.extend(maddtoend2) self.write_manifest_file(mlist1, manname1) self.write_manifest_file(mlist2, manname2) return
def test_scale_defect(self): size = '1 1 0,-1 1 0,0 0 1' perfect = pymatgen.io.vaspio.Poscar.from_file( "POSCAR_perfect").structure sxtend = StructureExtensions(struc_work1=perfect, scaling_size=size) scaled = sxtend.scale_structure() sxtend2 = StructureExtensions(struc_work1=scaled, scaling_size=size) vac1 = { 'symbol': 'O', 'type': 'vacancy', 'coordinates': np.array([0.25, 0.75, 0.25]) } defected = sxtend2.scale_defect(vac1, 'fractional', 0.0001) int1 = { 'symbol': 'Ni', 'type': 'interstitial', 'coordinates': np.array([0.3, 0.3, 0.3]) } sxtend3 = StructureExtensions(struc_work1=defected, scaling_size=size) defected2 = sxtend3.scale_defect(int1, 'fractional', 0.0001) sub1 = { 'symbol': 'Fe', 'type': 'substitution', 'coordinates': np.array([0.25, 0.25, 0.75]) } sxtend4 = StructureExtensions(struc_work1=defected2, scaling_size=size) defected3 = sxtend4.scale_defect(sub1, 'fractional', 0.0001) self.assertEqual( pymatgen.io.vaspio.Poscar.from_file( "POSCAR_scaled_defected").structure, defected3)
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 test_sort_structure_and_neb_lines(self): perfect1 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_defectgroup1").structure compare_sorted1 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_sorted1").structure perfect2 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_defectgroup2").structure compare_sorted2 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_sorted2").structure neblines = list() neblines.append(["Cr","0.3 0 0","0 0 0"]) neblines.append(["Ni","0.6 0 0","0.3 0 0"]) sxtend1 = StructureExtensions(struc_work1=perfect1, name=testdir) sorted1 = sxtend1.sort_structure_and_neb_lines(neblines,"00",3) sxtend2 = StructureExtensions(struc_work1=perfect2, name=testdir) sorted2 = sxtend2.sort_structure_and_neb_lines(neblines,"04",3) self.assertEqual(sorted1, compare_sorted1) self.assertEqual(sorted2, compare_sorted2) self.assertEqual(sorted1.lattice, compare_sorted1.lattice) self.assertEqual(sorted2.lattice, compare_sorted2.lattice) self.assertEqual(sorted1.sites, compare_sorted1.sites) self.assertEqual(sorted2.sites, compare_sorted2.sites) neblines = list() neblines.append(["Cr","0.29 0.05 0.05","0.01 0.01 0.98"]) neblines.append(["Ni","0.61 0.99 0.98","0.25 0.01 0.97"]) sxtend1 = StructureExtensions(struc_work1=perfect1, name=testdir) sorted1 = sxtend1.sort_structure_and_neb_lines(neblines,"00",3) sxtend2 = StructureExtensions(struc_work1=perfect2, name=testdir) sorted2 = sxtend2.sort_structure_and_neb_lines(neblines,"04",3) self.assertEqual(sorted1, compare_sorted1) self.assertEqual(sorted2, compare_sorted2) self.assertEqual(sorted1.lattice, compare_sorted1.lattice) self.assertEqual(sorted2.lattice, compare_sorted2.lattice) self.assertEqual(sorted1.sites, compare_sorted1.sites) self.assertEqual(sorted2.sites, compare_sorted2.sites) neblines = list() neblines.append(["Cr","0.0 0.9 0.8","0.0 0.8 0.7"]) neblines.append(["Cr","0.4 0.2 0.1","0.3 0.3 0.2"]) neblines.append(["Cr","0.29 0.05 0.05","0.01 0.01 0.98"]) neblines.append(["Ni","0.61 0.99 0.98","0.25 0.01 0.97"]) perfect3 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_defectgroup3").structure #print perfect3.get_sorted_structure() perfect4 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_defectgroup4").structure #print perfect4.get_sorted_structure() sxtend3 = StructureExtensions(struc_work1=perfect3, name=testdir) sorted3 = sxtend3.sort_structure_and_neb_lines(neblines,"00",3) #print sorted3 sxtend4 = StructureExtensions(struc_work1=perfect4, name=testdir) sorted4 = sxtend4.sort_structure_and_neb_lines(neblines,"04",3) #print sorted4 compare_sorted3 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_sorted3").structure #print compare_sorted3 compare_sorted4 = pymatgen.io.vaspio.Poscar.from_file("POSCAR_sorted4").structure #print compare_sorted4 self.assertEqual(sorted3, compare_sorted3) self.assertEqual(sorted4, compare_sorted4) self.assertEqual(sorted3.lattice, compare_sorted3.lattice) self.assertEqual(sorted4.lattice, compare_sorted4.lattice) self.assertEqual(sorted3.sites, compare_sorted3.sites) self.assertEqual(sorted4.sites, compare_sorted4.sites)
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_neb_endpoint_manifests(self): """Make NEB endpoint manifests. """ neb_dict=self.input_options.get_item('neb','nebs') if neb_dict == None: return None nlabels=neb_dict.keys() scales = self.scaling.keys() scales.append("") for scaling_label in scales: 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 nlabel in nlabels: def1 = nlabel.split("-")[0].strip() def2 = nlabel.split("-")[1].strip() manname1=os.path.join(self.sdir,"manifest_%s_%s_%s" % (scaling_label, def1, nlabel)) manname2=os.path.join(self.sdir,"manifest_%s_%s_%s" % (scaling_label, def2, nlabel)) mlist1raw=list(self.read_manifest_file("%s/manifest_%s_%s_" % (self.sdir, scaling_label, def1))) mlist2raw=list(self.read_manifest_file("%s/manifest_%s_%s_" % (self.sdir, scaling_label, def2))) mlist1=list() mlist2=list() for mitem in mlist1raw: #clean up leftover semicolons from defect manifests if ";" in mitem: mlist1.append(mitem.split(";")[0]) else: mlist1.append(mitem) for mitem in mlist2raw: #clean up leftover semicolons from defect manifests if ";" in mitem: mlist2.append(mitem.split(";")[0]) else: mlist2.append(mitem) maddtoend1=list() maddtoend2=list() nlines=list(neb_dict[nlabel]["lines"]) for nline in nlines: ncoord1 = np.array(nline[1].split(), 'float') ncoord2 = np.array(nline[2].split(), 'float') if not (scaling_label == ""): ncoord1 = mySE.get_scaled_coordinates(ncoord1) ncoord2 = mySE.get_scaled_coordinates(ncoord2) nelem = nline[0] nidx1 = self.find_orig_frac_coord_in_atom_indices(ncoord1, nelem, scaling_label, False, 0.001) nidx2 = self.find_orig_frac_coord_in_atom_indices(ncoord2, nelem, scaling_label, False, 0.001) try: mlist1.remove(nidx1) except ValueError: raise MASTError(self.__class__.__name__, "For neb %s, cannot remove atom index %s from mlist1: %s" % (nlabel, nidx1, mlist1)) maddtoend1.append(nidx1) #resort matches to the bottom try: mlist2.remove(nidx2) except ValueError: raise MASTError(self.__class__.__name__, "For neb %s, cannot remove atom index %s from mlist2: %s" % (nlabel, nidx2, mlist2)) maddtoend2.append(nidx2) if not (mlist1==mlist2): raise MASTError("NEB %s truncated manifests do not match: %s, %s" % (nlabel, mlist1, mlist2)) mlist1.extend(maddtoend1) mlist2.extend(maddtoend2) self.write_manifest_file(mlist1, manname1) self.write_manifest_file(mlist2, manname2) return