def surfer(mpid='', vacuum=15, layers=2, mat=None, max_index=1, write_file=True): """ ASE surface bulder Args: vacuum: vacuum region mat: Structure object max_index: maximum miller index min_slab_size: minimum slab size Returns: structures: list of surface Structure objects """ if mat == None: with MPRester() as mp: mat = mp.get_structure_by_material_id(mpid) if mpid == '': print('Provide structure') sg_mat = SpacegroupAnalyzer(mat) mat_cvn = sg_mat.get_conventional_standard_structure() mat_cvn.sort() indices = get_symmetrically_distinct_miller_indices(mat_cvn, max_index) ase_atoms = AseAtomsAdaptor().get_atoms(mat_cvn) structures = [] pos = Poscar(mat_cvn) try: pos.comment = str('sbulk') + str('@') + str('vac') + str(vacuum) + str( '@') + str('layers') + str(layers) except: pass structures.append(pos) if write_file == True: mat_cvn.to(fmt='poscar', filename=str('POSCAR-') + str('cvn') + str('.vasp')) for i in indices: ase_slab = surface(ase_atoms, i, layers) ase_slab.center(vacuum=vacuum, axis=2) slab_pymatgen = AseAtomsAdaptor().get_structure(ase_slab) slab_pymatgen.sort() surf_name = '_'.join(map(str, i)) pos = Poscar(slab_pymatgen) try: pos.comment = str("Surf-") + str(surf_name) + str('@') + str( 'vac') + str(vacuum) + str('@') + str('layers') + str(layers) except: pass if write_file == True: pos.write_file(filename=str('POSCAR-') + str("Surf-") + str(surf_name) + str('.vasp')) structures.append(pos) return structures
def poscar(self): """ generating poscar for relaxation calculations """ print( '--------------------------------------------------------------------------------------------------------' ) print("Generation of VASP files for the cell relaxation:") print( '--------------------------------------------------------------------------------------------------------' ) self.symData.structure = Structure.from_file(self.args.pos[0]) sym1 = float(self.args.sympre[0]) sym2 = float(self.args.symang[0]) aa = SpacegroupAnalyzer(self.symData.structure, symprec=sym1, angle_tolerance=sym2) self.symData.space_group = aa.get_space_group_number() print("Space group number =", self.symData.space_group) spg = aa.get_space_group_symbol() print("Space group symbol =", str(spg)) self.symData.number_of_species = len(self.symData.structure.species) print("Number of atoms = {}".format(len( self.symData.structure.species))) pos_name = "POSCAR" structure00 = Poscar(self.symData.structure) structure00.write_file(filename=pos_name, significant_figures=16) return self.symData
def write_to_file(invars, collect_structures): f = open("{}/ORDERING_OUTPUT.txt".format(invars.run_dir), 'a') f.write("Writing new structures to disk\n") f.write("-------------------------------------------------------------------------------------\n\n") f.close() for entry in collect_structures: f = open("{}/ORDERING_OUTPUT.txt".format(invars.run_dir), 'a') folder_name = "space_group-No-{}".format(entry) if os.path.isdir('{}/{}'.format(invars.run_dir, folder_name)): f.write("{} directory is already present\n".format(folder_name)) f.write("Going in to look for files\n") current_dir = '{}/{}'.format(invars.run_dir, folder_name) else: f.write("Creating {} directory\n".format(folder_name)) os.mkdir(folder_name) current_dir = "{}/{}".format(invars.run_dir, folder_name) f.close() for i, new_strt in enumerate(collect_structures[entry]): str_name = "{}-str-{}.vasp".format(folder_name, (i+1)) if os.path.isfile("{}/{}".format(current_dir, str_name)): f = open("{}/ORDERING_OUTPUT.txt".format(invars.run_dir), 'a') f.write("{} file is already present\n".format(str_name)) f.close() pass else: w = Poscar(new_strt) w.write_file("{}/{}".format(current_dir, str_name)) if invars.calc_distort == '.FASLE.': pass elif invars.calc_distort == '.TRUE.' \ and os.path.isdir('{}/distortions-str-{}'.format(current_dir, (i+1))) is False: f = open("{}/ORDERING_OUTPUT.txt".format(invars.run_dir), 'a') f.write("Evaluating distortions for {}\n".format(str_name)) f.write("-------------------------------------------------------------------------------------\n") f.write('creating distortions-{} directory\n\n'.format(i+1)) os.mkdir('{}/distortions-str-{}'.format(current_dir,(i+1))) dist_dir = '{}/distortions-str-{}'.format(current_dir,(i+1)) f.close() #print distortion_files match_atoms(new_strt, invars, dist_dir) elif invars.calc_distort == '.TRUE.' \ and os.path.isdir('{}/distortions-str-{}'.format(current_dir, (i+1))) is True: f = open("{}/ORDERING_OUTPUT.txt".format(invars.run_dir), 'a') f.write('distortions-str-{} directory already present\nGoing in...\n\n'.format(i+1)) dist_dir = '{}/distortions-str-{}'.format(current_dir, (i+1)) f.close() match_atoms(new_strt, invars, dist_dir)
def vac_antisite_def_struct_gen(c_size=15, mpid="", struct=None, write_file=True): """ Vacancy, antisite generator Args: c_size: cell size struct: Structure object or mpid: materials project id Returns: def_str: defect structures in Poscar object format """ def_str = [] if struct == None: with MPRester() as mp: struct = mp.get_structure_by_material_id(mpid) if mpid == "": print("Provide structure") c_size = c_size prim_struct_sites = len(struct.sites) struct = SpacegroupAnalyzer(struct).get_conventional_standard_structure() dim1 = int((float(c_size) / float(max(abs(struct.lattice.matrix[0]))))) + 1 dim2 = int(float(c_size) / float(max(abs(struct.lattice.matrix[1])))) + 1 dim3 = int(float(c_size) / float(max(abs(struct.lattice.matrix[2])))) + 1 cellmax = max(dim1, dim2, dim3) conv_struct_sites = len(struct.sites) conv_prim_rat = int(conv_struct_sites / prim_struct_sites) sc_scale = [dim1, dim2, dim3] print("sc_scale", sc_scale) tmp = struct.copy() tmp.make_supercell(sc_scale) sc_tmp = tmp # Poscar(tmp).structure .make_supercell(list(sc_scale)) scs = list(VacancyGenerator(struct)) supercell = Poscar(sc_tmp) supercell.comment = str("bulk") + str("@") + str("cellmax") + str(cellmax) def_str.append(supercell) if write_file == True: supercell.write_file("POSCAR-" + str("bulk") + str(".vasp")) for i in range(len(scs)): sc = scs[i].generate_defect_structure(sc_scale) poscar = Poscar(sc) # mpvis.get_poscar(sc) pmg_name = str(scs[i].name).split("_") sitespecie = pmg_name[1] mult = pmg_name[2].split("mult")[1] name = (str("vacancy_") + str(i + 1) + str("_mult-") + str(mult) + str("_sitespecie-") + str(sitespecie) + str("@cellmax") + str(cellmax)) poscar.comment = str(name) def_str.append(poscar) if write_file == True: filename = (str("POSCAR-") + str("vacancy_") + str(i + 1) + str("_mult-") + str(mult) + str("_sitespecie-") + str(sitespecie) + str(".vasp")) poscar.write_file(filename) return def_str
def write_structures(structures, file_name): import tempfile import zipfile from os.path import basename, join import os if len(structures) > 1: result_archive = zipfile.ZipFile(join(os.getcwd(), basename(file_name) + '.zip'), mode='w') for name, structure in structures.items(): sorted_sites = list( sorted(structure.sites.copy(), key=lambda site: site.specie.symbol)) sorted_structure = Structure.from_sites(sorted_sites) with tempfile.NamedTemporaryFile() as tmpfile: Poscar(structure=sorted_structure).write_file(tmpfile.name) result_archive.write(tmpfile.name, arcname=basename(file_name) + '-' + name) result_archive.close() write_message('Archive file: {0}'.format( join(os.getcwd(), basename(file_name) + '.zip')), level=DEBUG) else: #There is just one file write only that one structure_key = list(structures.keys())[0] sorted_sites = list( sorted(structures[structure_key].sites.copy(), key=lambda site: site.specie.symbol)) sorted_structure = Structure.from_sites(sorted_sites) p = Poscar(structure=sorted_structure) fname = join(os.getcwd(), basename(file_name) + structure_key + '.vasp') p.write_file(fname) write_message('Output file: {0}'.format(fname), level=DEBUG)
def mp_id(mpid): """ materials project の ID から POSCAR を作成 """ mpr = MPRester("WTxsDhRV7g2Mcbqw") strctr = mpr.get_structure_by_material_id(mpid) poscar = Poscar(strctr) poscar.write_file('POSCAR_{0}'.format(mpid))
def pmg_surfer(mpid='', vacuum=15, mat=None, max_index=1, min_slab_size=15): if mat == None: with MPRester() as mp: mat = mp.get_structure_by_material_id(mpid) if mpid == '': print('Provide structure') sg_mat = SpacegroupAnalyzer(mat) mat_cvn = sg_mat.get_conventional_standard_structure() mat_cvn.sort() indices = get_symmetrically_distinct_miller_indices(mat_cvn, max_index) #ase_atoms = AseAtomsAdaptor().get_atoms(mat_cvn) structures = [] pos = Poscar(mat_cvn) try: pos.comment = str('sbulk') + str('@') + str('vac') + str(vacuum) + str( '@') + str('size') + str(min_slab_size) except: pass structures.append(pos) mat_cvn.to(fmt='poscar', filename=str('POSCAR-') + str('cvn') + str('.vasp')) for i in indices: slab = SlabGenerator(initial_structure=mat_cvn, miller_index=i, min_slab_size=min_slab_size, min_vacuum_size=vacuum, lll_reduce=False, center_slab=True, primitive=False).get_slab() normal_slab = slab.get_orthogonal_c_slab() slab_pymatgen = Poscar(normal_slab).structure #ase_slab.center(vacuum=vacuum, axis=2) #slab_pymatgen = AseAtomsAdaptor().get_structure(ase_slab) xy_size = min_slab_size dim1 = int((float(xy_size) / float(max(abs(slab_pymatgen.lattice.matrix[0]))))) + 1 dim2 = int( float(xy_size) / float(max(abs(slab_pymatgen.lattice.matrix[1])))) + 1 slab_pymatgen.make_supercell([dim1, dim2, 1]) slab_pymatgen.sort() surf_name = '_'.join(map(str, i)) pos = Poscar(slab_pymatgen) try: pos.comment = str("Surf-") + str(surf_name) + str('@') + str( 'vac') + str(vacuum) + str('@') + str('size') + str( min_slab_size) except: pass pos.write_file(filename=str('POSCAR-') + str("Surf-") + str(surf_name) + str('.vasp')) structures.append(pos) return structures
def prim(src): """ primitive cell に変換 """ srcpos = Poscar.from_file(src) finder = SpacegroupAnalyzer(srcpos.structure) prim_str = finder.get_primitive_standard_structure() dstpos = Poscar(prim_str) dst = 'POSCAR_prim' Cabinet.reserve_file(dst) dstpos.write_file(dst)
def refined(src): """ refined poscar を 作成する """ srcpos = Poscar.from_file(src) finder = SpacegroupAnalyzer(srcpos.structure, symprec=5e-1, angle_tolerance=8) scr_std = finder.get_refined_structure() dstpos = Poscar(scr_std) dst = "POSCAR_refined" Cabinet.reserve_file(dst) dstpos.write_file(dst)
def std(src='POSCAR'): """ conventional standard cell に変換 """ srcpos = Poscar.from_file(src) finder = SpacegroupAnalyzer(srcpos.structure) std_str = finder.get_conventional_standard_structure() dstpos = Poscar(std_str) dst = 'POSCAR_std' Cabinet.reserve_file(dst) dstpos.write_file(dst)
def refined(src='POSCAR'): """ refined cell を 作成する """ srcpos = Poscar.from_file(src) finder = SpacegroupAnalyzer(srcpos.structure, symprec=5e-1, angle_tolerance=8) std_str = finder.get_refined_structure() dstpos = Poscar(std_str) dst = 'POSCAR_refined' Cabinet.reserve_file(dst) dstpos.write_file(dst)
def surfer(vacuum=15, layers=2, mat=None, max_index=1, write_file=True): """ ASE surface bulder Args: vacuum: vacuum region mat: Structure object max_index: maximum miller index min_slab_size: minimum slab size Returns: structures: list of surface Structure objects """ if mat == None: print("Provide structure") sg_mat = SpacegroupAnalyzer(mat) mat_cvn = sg_mat.get_conventional_standard_structure() mat_cvn.sort() indices = get_symmetrically_distinct_miller_indices(mat_cvn, max_index) ase_atoms = AseAtomsAdaptor().get_atoms(mat_cvn) structures = [] pos = Poscar(mat_cvn) try: pos.comment = (str("sbulk") + str("@") + str("vac") + str(vacuum) + str("@") + str("layers") + str(layers)) except: pass structures.append(pos) if write_file == True: mat_cvn.to(fmt="poscar", filename=str("POSCAR-") + str("cvn") + str(".vasp")) for i in indices: ase_slab = surface(ase_atoms, i, layers) ase_slab.center(vacuum=vacuum, axis=2) slab_pymatgen = AseAtomsAdaptor().get_structure(ase_slab) slab_pymatgen.sort() surf_name = "_".join(map(str, i)) pos = Poscar(slab_pymatgen) try: pos.comment = (str("Surf-") + str(surf_name) + str("@") + str("vac") + str(vacuum) + str("@") + str("layers") + str(layers)) except: pass if write_file == True: pos.write_file(filename=str("POSCAR-") + str("Surf-") + str(surf_name) + str(".vasp")) structures.append(pos) return structures
def run_task(self, fw_spec): structure_dict = fw_spec["structure"] if self.get("rescale_volume", False): spec_structure = Structure.from_dict(structure_dict) scaling_volume = spec_structure.volume * self["rescale_volume"] spec_structure.scale_lattice(scaling_volume) structure_dict = spec_structure.as_dict() _poscar = Poscar(structure_dict) _poscar.write_file("POSCAR") return FWAction()
def convert_fmt(args): iformat = args.input_format[0] oformat = args.output_format[0] filename = args.input_filename[0] out_filename = args.output_filename[0] try: if iformat == "POSCAR": p = Poscar.from_file(filename) structure = p.structure elif iformat == "CIF": r = CifParser(filename) structure = r.get_structures()[0] elif iformat == "CONVENTIONAL_CIF": r = CifParser(filename) structure = r.get_structures(primitive=False)[0] elif iformat == "CSSR": structure = Cssr.from_file(filename).structure else: structure = Structure.from_file(filename) if oformat == "smart": structure.to(filename=out_filename) elif oformat == "POSCAR": p = Poscar(structure) p.write_file(out_filename) elif oformat == "CIF": w = CifWriter(structure) w.write_file(out_filename) elif oformat == "CSSR": c = Cssr(structure) c.write_file(out_filename) elif oformat == "VASP": ts = TransformedStructure( structure, [], history=[{"source": "file", "datetime": str(datetime.datetime.now()), "original_file": open(filename).read()}]) ts.write_vasp_input(MPRelaxSet, output_dir=out_filename) elif oformat == "MITVASP": ts = TransformedStructure( structure, [], history=[{"source": "file", "datetime": str(datetime.datetime.now()), "original_file": open(filename).read()}]) ts.write_vasp_input(MITRelaxSet, output_dir=out_filename) except Exception as ex: print("Error converting file. Are they in the right format?") print(str(ex))
def constrain(structs, fnames, atom_index, in_str=" "): #len(structs)==1 mlog.debug("len(structs): {} ".format(len(structs))) mlog.debug("fnames: {} ".format(fnames[0])) for struct, fname in zip(structs, fnames): mlog.debug(fname) mlog.debug(struct) natom = struct.num_sites selective_dynamics = [[True for col in range(3)] for row in range(natom)] for i in range(natom): if i in atom_index: selective_dynamics[i] = [False, False, False] tmp_struct = Structure( struct.lattice, struct.species, struct.frac_coords, site_properties={'selective_dynamics': selective_dynamics}) poscar = Poscar(tmp_struct) poscar.comment = poscar.comment + ' |--> ' + in_str filename = 'Fixed_' + fname + '.vasp' poscar.write_file(filename)
subs = ccopy.frac_coords for atom in range(0, len(subby)): for coord in range(0, 3): subs[atom][coord] = subby[atom][ coord] * interval * increment + nm_coords[atom][coord] # Add displacement to zero modes structure index = range(0, len(species)) for i in index: ccopy.replace(i, species[i], coords=subs[i]) # Export to POSCAR struct = Poscar(ccopy) value = increment * 100 * interval struct.write_file(output_path + "/%s_%s%%.vasp" % (mode_filename, value)) #e.g. 'Y2+_100%' if numberomodes == 2: for interval2 in range(0, intervals + 1): for interval in range(0, intervals + 1): ccopy = copy.copy(trans_nomode) species = ccopy.species subs = ccopy.frac_coords for atom in range(0, len(subby)): for coord in range(0, 3): subs[atom][coord] = subby[atom][ coord] * interval * increment + subby2[atom][ coord] * interval2 * increment + nm_coords[atom][ coord]
def vac_antisite_def_struct_gen(c_size=15, mpid='', struct=None, write_file=True): """ Vacancy, antisite generator Args: c_size: cell size struct: Structure object or mpid: materials project id Returns: def_str: defect structures in Poscar object format """ def_str = [] if struct == None: with MPRester() as mp: struct = mp.get_structure_by_material_id(mpid) if mpid == '': print("Provide structure") c_size = c_size dim1 = int((float(c_size) / float(max(abs(struct.lattice.matrix[0]))))) + 1 dim2 = int(float(c_size) / float(max(abs(struct.lattice.matrix[1])))) + 1 dim3 = int(float(c_size) / float(max(abs(struct.lattice.matrix[2])))) + 1 cellmax = max(dim1, dim2, dim3) prim_struct_sites = len(struct.sites) struct = SpacegroupAnalyzer(struct).get_conventional_standard_structure() conv_struct_sites = len(struct.sites) conv_prim_rat = int(conv_struct_sites / prim_struct_sites) sc_scale = [dim1, dim2, dim3] print("sc_scale", sc_scale) struct_valrad_eval = ValenceIonicRadiusEvaluator(struct) val = struct_valrad_eval.valences rad = struct_valrad_eval.radii struct_val = val struct_rad = rad vac = Vacancy(struct, {}, {}) scs = vac.make_supercells_with_defects(sc_scale) for i in range(len(scs)): sc = scs[i] poscar = Poscar(sc) #mpvis.get_poscar(sc) interdir = mpid if not i: fin_dir = os.path.join(interdir, 'bulk') poscar.comment = str('bulk') + str('@') + str('cellmax') + str( cellmax) def_str.append(poscar) if write_file == True: poscar.write_file('POSCAR-' + str('bulk') + str(".vasp")) else: blk_str_sites = set(scs[0].sites) vac_str_sites = set(sc.sites) vac_sites = blk_str_sites - vac_str_sites vac_site = list(vac_sites)[0] site_mult = int( vac.get_defectsite_multiplicity(i - 1) / conv_prim_rat) vac_site_specie = vac_site.specie vac_symbol = vac_site.specie.symbol vac_dir = 'vacancy_{}_mult-{}_sitespecie-{}'.format( str(i), site_mult, vac_symbol) fin_dir = os.path.join(interdir, vac_dir) try: poscar.comment = str(vac_dir) + str('@') + str( 'cellmax') + str(cellmax) except: pass pos = poscar def_str.append(pos) if write_file == True: poscar.write_file('POSCAR-' + str(vac_dir) + str(".vasp")) struct_species = scs[0].types_of_specie for specie in set(struct_species) - set([vac_site_specie]): subspecie_symbol = specie.symbol anti_struct = sc.copy() anti_struct.append(specie, vac_site.frac_coords) poscar = Poscar(anti_struct) as_dir = 'antisite_{}_mult-{}_sitespecie-{}_subspecie-{}'.format( str(i), site_mult, vac_symbol, subspecie_symbol) fin_dir = os.path.join(interdir, as_dir) poscar.comment = str(as_dir) + str('@') + str('cellmax') + str( cellmax) pos = poscar def_str.append(pos) if write_file == True: poscar.write_file('POSCAR-' + str(as_dir) + str(".vasp")) return def_str
# This initializes the REST adaptor. Put your own API key in. from pymatgen import MPRester from pymatgen.core.surface import generate_all_slabs from pymatgen.io.vasp import Poscar a = MPRester("") # Entries are the basic unit for thermodynamic and other analyses in pymatgen. # This gets all entries belonging to the Fe material. entry = a.get_entry_by_material_id( "mp-13", inc_structure=True, property_data=["material_id", "energy", "energy_per_atom", "volume"]) slabs = generate_all_slabs(entry.structure, 1, 4, 10) print(len(slabs)) print(slabs[0]) pos = Poscar(slabs[0]) pos.write_file(filename="POSCAR_fe_111")
def match_atoms(str1, invars, dist_dir): f = open("{}/ORDERING_OUTPUT.txt".format(invars.run_dir), 'a') distortion_files = os.listdir(invars.distortion_directory) f.write("distortion\t\tSpace group #\n") f.write( "-------------------------------------------------------------------------------------\n" ) for filename in distortion_files: poscar = Poscar.from_file(("{}/{}").format(invars.distortion_directory, filename)) str2 = poscar.structure new_coords = [] for i, posi1 in enumerate(str1.cart_coords): distance = 1e100 coord_holder = [] bounds = np.array(str1.lattice.abc) for j, posi2 in enumerate(str2.cart_coords): min_dists = np.min(np.dstack( ((np.array(posi1) - np.array(posi2)) % bounds, (np.array(posi2) - np.array(posi1)) % bounds)), axis=2) dists = np.sqrt(np.sum(min_dists**2, axis=1)) if dists < distance: distance = dists coord_holder = str2.frac_coords[j] new_coords = np.append(new_coords, coord_holder) new_coords = new_coords.reshape(str1.num_sites, 3) # Arrange atoms in a list that matches the list of the a0a0a0 structure distorted_structure = Structure(str1.lattice, str1.species, new_coords) space_group = int( SpacegroupAnalyzer(distorted_structure, invars.symprec).get_space_group_number()) str_name = "{}-SG-{}.vasp".format(filename, space_group) if os.path.isfile(str_name): f.write("{}\t\t\t{}\n".format(filename, space_group)) else: f.write("{}\t\t\t{}\n".format(filename, space_group)) w = Poscar(distorted_structure) w.write_file("{}/{}".format(dist_dir, str_name)) #f.write("\n") f.write( "-------------------------------------------------------------------------------------\n" ) f.write( "-------------------------------------------------------------------------------------\n" ) f.close() #lattice = Lattice.from_parameters(a=str1.basis_vectors[0][0], b=str1.basis_vectors[1][1], c=str1.basis_vectors[2][2], alpha=90,beta=90,gamma=90) #rot_X_new_coords = np.dot(new_coords, X_cell_rotation()) #print "New Coords original" #print new_coords #print "rotated in X new Coords" #print rot_X_new_coords #all_permut_of_str.append(Structure(lattice, str1.species, rot_X_new_coords)) #all_permut_of_str.append(structure_x_rot) #rot_Y_new_coords = np.dot(new_coords, Y_cell_rotation()) #all_permut_of_str.append(Structure(lattice, str1.species, rot_Y_new_coords)) #rot_Z_new_coords = np.dot(new_coords, Z_cell_rotation()) #all_permut_of_str.append(Structure(lattice, str1.species, rot_Z_new_coords)) #print len(all_permut_of_str) #all_permut_of_str = compare_structures(all_permut_of_str) '''
def find_unique_structures(base_crystal_path, directory): """ DESCRIPTION: Given a base crystal structure along with a directory containing CIF structures, determine how many unique configurations are in the directory, and assign a configuration ID number to each CIF structure in the directory. Results can be seen in the outputted unique.csv file. The function uses the base crystal structure provided to find the space group and associated symmetry operations, which are then used to see whether the CIF structures in the directory are equivalent. PARAMETERS: base_crystal_path: string The path to the base crystal CIF structure. Note that this structure should contain the space group that you want to check all other structures to. If the symmetry of this structure is incorrect, you will get unexpected results. directory: string The path to the directory containing the CIF structures to compare. Note that this function assumes that the CIF names are all prefixed by a dash and followed by an interger, ie "LiCoO2-1", "LiCoO2-2", "LiCoO2-3"..., ect. RETURNS: None """ # convert all files (they should all be cif files) in the directory into Structures and place them into a list cif_file_names = [ os.path.splitext(os.path.basename(path))[0] for path in os.listdir(directory) if path.endswith('.cif') ] cif_files = [ directory + path for path in os.listdir(directory) if path.endswith('.cif') ] cif_files = sorted(cif_files, key=lambda x: int(x.split("-")[-1].replace(".cif", ""))) cif_file_names = sorted(cif_file_names, key=lambda x: int(x.split("-")[-1])) structures = [IStructure.from_file(path) for path in cif_files] print(cif_file_names) # Get the base crystal structure base_crystal = IStructure.from_file(base_crystal_path) # Get the space group of the base crystal analyzer = SpacegroupAnalyzer(base_crystal) spacegroup = analyzer.get_space_group_operations() print(spacegroup) id = 1 num_structures = len(structures) config_dict = {} unique_structs = [] for i in range(num_structures): config1 = structures[i] unique_cif_name = cif_file_names[i] if not unique_cif_name in config_dict: config_dict[unique_cif_name] = id print("%s Unique Structures Found..." % (id)) unique_structs.append(config1) id += 1 for j in range(num_structures): cif_name = cif_file_names[j] config2 = structures[j] if not cif_name in config_dict: isEquivalent = spacegroup.are_symmetrically_equivalent( config1, config2) if isEquivalent: config_dict[cif_name] = config_dict[unique_cif_name] print("----------------------------------------------") print("%s Total Unique Structures Found" % (id - 1)) print("----------------------------------------------") with open('unique.csv', 'w') as f: for key in config_dict.keys(): f.write("%s,%s\n" % (key, config_dict[key])) crystal_name = os.path.splitext(os.path.basename(base_crystal_path))[0] directory_path = "{}-unique".format(crystal_name) if not os.path.isdir(directory_path): os.mkdir(directory_path) num_unique_structures = len(unique_structs) for i in range(num_unique_structures): config = unique_structs[i] #Save to CIF filename = crystal_name + '_ewald' + '_{}'.format(i + 1) w = CifWriter(config) w.write_file(directory_path + '/' + filename + '.cif') # print("Cif file saved to {}.cif".format(filename)) #Save to POSCAR poscar = Poscar(config) poscar.write_file(directory_path + '/' + filename)
def generate_ewald_orderings(path, choose_file, oxidation_states, num_structures): """ DESCRIPTION: Given a disordered CIF structure with at least one crystallographic site that is shared by more than one element, all permutations will have their electrostatic energy calculated via an Ewald summation, given that all ion charges are specified. Ordered CIF structures will be generated, postpended with a number that indicates the stability ranking of the structure. For example, if a CIF file called "Na2Mn2Fe(VO4)3.cif" is inputted with num_structures=3, then the function will generate 3 ordered output files, "Na2Mn2Fe(VO4)3-ewald-1", "Na2Mn2Fe(VO4)3-ewald-2", and "Na2Mn2Fe(VO4)3-ewald-3", with "Na2Mn2Fe(VO4)3-ewald-1" being the most stable and "Na2Mn2Fe(VO4)3-ewald-3" being the least stable. Note that this function does not take into account the symmetry of the crystal, and thus it may give several structures which are symmetrically identical under a space group. Use "find_unique_structures" to isolate unique orderings. PARAMETERS: path: string The file path to the CIF file. The CIF file must be a disordered structure, or else an error will occur. A disordered structure will have one site that is occupied by more than one element, with occupancies less than 1: i.e. Fe at 0,0,0.5 with an occupancy of 0.75, and Mn at the same site 0,0,0.5 with an occupancy of 0.25. This function cannot handle multivalent elements, for example it cannot handle a structure that has Mn in both the 2+ and 3+ redox state. choose_file: boolean Setting this parameter to True brings up the file explorer dialog for the user to manually select the CIF file oxidation_states: dictionary A dictionary that maps each element in the structure to a particular oxidation state. E.g. {"Fe": 3, "Mn": 2, "O": -2, "V": 5, "Na": 1, "Al":3} Make sure that all elements in the structure is assigned an oxidation state. It is ok to add more elements than needed. num_structures: int The number of strcutures to be outputted by the function. There can be hundreds or thousands of candidate structures, however in practice only the first few (or even only the first, most stable) structures are needed. RETURNS: None """ # open file dialog if file is to be manually chosen if choose_file: root = tk.Tk() root.withdraw() path = filedialog.askopenfilename() #Read cif file cryst = Structure.from_file(path) analyzer = SpacegroupAnalyzer(cryst) space_group = analyzer.get_space_group_symbol() print(space_group) symm_struct = analyzer.get_symmetrized_structure() cryst = TransformedStructure(symm_struct) #Create Oxidation State Transform oxidation_transform = OxidationStateDecorationTransformation( oxidation_states) #Create Ewald Ordering Transform object which will be passed into the transmuter ordering_transform = OrderDisorderedStructureTransformation( symmetrized_structures=True) # apply the order-disorder transform on the structure for any site that has fractional occupancies transmuter = StandardTransmuter([cryst], [oxidation_transform, ordering_transform], extend_collection=num_structures) print("Ewald optimization successful!") num_structures = len(transmuter.transformed_structures) for i in range(num_structures): newCryst = transmuter.transformed_structures[i].final_structure #Save to CIF structure_name = os.path.splitext(os.path.basename(path))[0] save_directory = structure_name if not os.path.isdir(save_directory): os.mkdir(save_directory) filename = structure_name + '/' + structure_name + '-ewald' + '-%i' % ( i + 1) w = CifWriter(newCryst) w.write_file(filename + '.cif') print("Cif file saved to {}.cif".format(filename)) #Save to POSCAR poscar = Poscar(newCryst) poscar.write_file(filename) print("POSCAR file saved to {}".format(filename))
def vasp_converge_files(structure, input_dir=None, incar_settings=None, config=None): """ Generates input files for single-shot GGA convergence test calculations. Automatically sets ISMEAR (in INCAR) to 2 (if metallic) or 0 if not. Recommended to use with vaspup2.0 Args: structure (Structure object): Structure to create input files for input_dir (str): Folder in which to create 'input' folder with VASP input files (default: None) incar_settings (dict): Dictionary of user INCAR settings (AEXX, NCORE etc.) to override default settings. Highly recommended to look at output INCARs or DefectsWithTheBoys.vasp_input source code, to see what the default INCAR settings are. (default: None) config (str): CONFIG file string. If provided, will also write the CONFIG file to each 'input' directory (default: None) """ # Variable parameters first vaspconvergeincardict = { '# May need to change ISMEAR, NCORE, KPAR, AEXX, ENCUT, NUPDOWN, ISPIN': 'variable parameters', 'NUPDOWN': "0 # But could be 1 etc. if ya think we got a bit of magnetic shit going down", 'NCORE': 12, '#KPAR': 1, 'ENCUT': 450, 'ISMEAR': "0 # Change to 2 for Metals", 'ISPIN': 2, 'ICORELEVEL': 0, 'GGA': 'PS', 'ALGO': 'Normal', 'ADDGRID': True, 'EDIFF': 1e-07, 'EDIFFG': -0.01, 'IBRION': -1, 'ICHARG': 1, 'ISIF': 3, 'LASPH': True, 'LORBIT': 11, 'LREAL': False, 'LVHAR': True, 'LWAVE': True, 'NEDOS': 2000, 'NELM': 100, 'NSW': 0, 'PREC': 'Accurate', 'SIGMA': 0.2 } if all(is_metal(element) for element in structure.composition.elements): vaspconvergeincardict['ISMEAR'] = 2 # If metals only else: vaspconvergeincardict['ISMEAR'] = 0 # Gaussian smearing otherwise if incar_settings: vaspconvergeincardict.update(incar_settings) # Directory vaspconvergeinputdir = input_dir + "/input/" if input_dir else 'VASP_Files/input/' if not os.path.exists(vaspconvergeinputdir): os.makedirs(vaspconvergeinputdir) vasppotcardict = { 'POTCAR': { 'Ac': 'Ac', 'Ag': 'Ag', 'Al': 'Al', 'Ar': 'Ar', 'As': 'As', 'Au': 'Au', 'B': 'B', 'Ba': 'Ba_sv', 'Be': 'Be_sv', 'Bi': 'Bi', 'Br': 'Br', 'C': 'C', 'Ca': 'Ca_sv', 'Cd': 'Cd', 'Ce': 'Ce', 'Cl': 'Cl', 'Co': 'Co', 'Cr': 'Cr_pv', 'Cs': 'Cs_sv', 'Cu': 'Cu_pv', 'Dy': 'Dy_3', 'Er': 'Er_3', 'Eu': 'Eu', 'F': 'F', 'Fe': 'Fe_pv', 'Ga': 'Ga_d', 'Gd': 'Gd', 'Ge': 'Ge_d', 'H': 'H', 'He': 'He', 'Hf': 'Hf_pv', 'Hg': 'Hg', 'Ho': 'Ho_3', 'I': 'I', 'In': 'In_d', 'Ir': 'Ir', 'K': 'K_sv', 'Kr': 'Kr', 'La': 'La', 'Li': 'Li_sv', 'Lu': 'Lu_3', 'Mg': 'Mg_pv', 'Mn': 'Mn_pv', 'Mo': 'Mo_pv', 'N': 'N', 'Na': 'Na_pv', 'Nb': 'Nb_pv', 'Nd': 'Nd_3', 'Ne': 'Ne', 'Ni': 'Ni_pv', 'Np': 'Np', 'O': 'O', 'Os': 'Os_pv', 'P': 'P', 'Pa': 'Pa', 'Pb': 'Pb_d', 'Pd': 'Pd', 'Pm': 'Pm_3', 'Pr': 'Pr_3', 'Pt': 'Pt', 'Pu': 'Pu', 'Rb': 'Rb_sv', 'Re': 'Re_pv', 'Rh': 'Rh_pv', 'Ru': 'Ru_pv', 'S': 'S', 'Sb': 'Sb', 'Sc': 'Sc_sv', 'Se': 'Se', 'Si': 'Si', 'Sm': 'Sm_3', 'Sn': 'Sn_d', 'Sr': 'Sr_sv', 'Ta': 'Ta_pv', 'Tb': 'Tb_3', 'Tc': 'Tc_pv', 'Te': 'Te', 'Th': 'Th', 'Ti': 'Ti_pv', 'Tl': 'Tl_d', 'Tm': 'Tm_3', 'U': 'U', 'V': 'V_pv', 'W': 'W_pv', 'Xe': 'Xe', 'Y': 'Y_sv', 'Yb': 'Yb_2', 'Zn': 'Zn', 'Zr': 'Zr_sv' } } vaspconvergekpts = Kpoints().from_dict({ 'comment': 'Kpoints from vasp_gam_files', 'generation_style': 'Gamma' }) vaspconvergeincar = Incar.from_dict(vaspconvergeincardict) vaspconvergeinput = DictSet(structure, config_dict=vasppotcardict) vaspconvergeinput.potcar.write_file(vaspconvergeinputdir + 'POTCAR') vaspconvergeposcar = Poscar(structure) vaspconvergeposcar.write_file(vaspconvergeinputdir + 'POSCAR') with zopen(vaspconvergeinputdir + 'INCAR', "wt") as f: f.write(vaspconvergeincar.get_string()) vaspconvergekpts.write_file(vaspconvergeinputdir + 'KPOINTS') # generate CONFIG file if config: with open(vaspconvergeinputdir + 'CONFIG', 'w+') as config_file: config_file.write(config) with open(vaspconvergeinputdir + 'CONFIG', 'a') as config_file: config_file.write(f"""\nname="{input_dir[13:]}" # input_dir""")
def twoD_operation(): #sepline(ch='2D structure operation',sp='=') print('your choice ?') print('{} >>> {}'.format('1', 'build rippled structure')) print('{} >>> {}'.format('2', 'build multi-layered structure')) print('{} >>> {}'.format('3', 'split multi-layered structure')) print('{} >>> {}'.format('4', 'resize vacuum layer')) print('{} >>> {}'.format('5', 'center atomic-layer along z direction')) print('{} >>> {}'.format('6', 'apply strain along different direction')) print('{} >>> {}'.format('7', 'constrain atom in specific range')) print('{} >>> {}'.format('8', 'get a substrate for 2D material (online!!!)')) wait_sep() in_str = "" while in_str == "": in_str = input().strip() choice = int(in_str) if choice == 1: struct = readstructure() margin_dist = 1.0 # assert (struct.lattice.is_orthogonal) print("input the supercell scaling factor") print('for x direction can be: 10 1 1') print('for y direction can be: 1 10 1') wait_sep() scale_str = input() scaling = [int(x) for x in scale_str.split()] if (len(scaling) != 3): print('unknow format') else: if scaling[0] >= scaling[1]: direction = 0 # for x direction else: direction = 1 # for y direction print("input the strain range") print("example: 0.02:0.1:10 ") wait_sep() strain_str = input() tmp = [float(x) for x in strain_str.split(":")] strain = [] if len(tmp) == 3: strain_range = np.linspace(tmp[0], tmp[1], int(tmp[2])) # print(strain_range) else: print("unknow format") return print("input the index of atom need to be fixed") print("example: 1 10 11 20 ") print("0 means fix the atom automatically") wait_sep() atom_index_str = input() try: atom_index = [int(x) for x in strain_str.split("")] auto_fix = False except: atom_index = [int(atom_index_str)] auto_fix = True struct_sc = struct.copy() struct_sc.make_supercell(scaling) natom = struct_sc.num_sites min_z = np.min(struct_sc.cart_coords[:, 2]) tmp_coords = np.ones((struct_sc.num_sites, 1)) * min_z cart_coords = struct_sc.cart_coords cart_coords[:, 2] = cart_coords[:, 2] - tmp_coords.T + 0.01 frac_coords_new = np.dot(cart_coords, np.linalg.inv(struct_sc.lattice.matrix)) for i_strain in strain_range: new_lat_matrix = struct_sc.lattice.matrix new_lat_matrix[direction, direction] = struct_sc.lattice.matrix[ direction, direction] * (1 - i_strain) fname = "%10.5f" % ( i_strain ) + '_wo.vasp' # structure only applied with in-plan strain struct_wo_ripple = Structure(new_lat_matrix, struct_sc.species, frac_coords_new) struct_wo_ripple.to(filename=fname.strip(), fmt='poscar') frac_coords_new_cp = struct_wo_ripple.frac_coords.copy() cart_coords_new_cp = struct_wo_ripple.cart_coords.copy() nz = 0 selective_dynamics = [[True for col in range(3)] for row in range(natom)] z_shift = np.zeros((natom, 3)) for i_atom in range(natom): z_shift[i_atom, 2] = 40 * (2 * i_strain - 10 * i_strain**2) * np.sin( cart_coords_new_cp[i_atom, direction] * np.pi / new_lat_matrix[direction, direction]) if cart_coords_new_cp[i_atom, direction] < nz or cart_coords_new_cp[ i_atom, direction] > new_lat_matrix[ direction, direction] - nz: z_shift[i_atom, 2] = 0.0 if auto_fix: if struct_wo_ripple[i_atom].coords[direction]<margin_dist or \ struct_wo_ripple[i_atom].coords[direction] > new_lat_matrix[direction,direction]-margin_dist: selective_dynamics[i_atom] = [False, False, False] else: if i_atom in atom_index: selective_dynamics[i_atom] = [False, False, False] struct_w_ripple=Structure(new_lat_matrix,struct_sc.species,cart_coords_new_cp+z_shift,coords_are_cartesian=True,\ site_properties={'selective_dynamics':selective_dynamics}) fname = "%10.5f" % ( i_strain ) + '_w.vasp' # structure applied with in-plan strain and ripple struct_w_ripple.to(filename=fname.strip(), fmt='poscar') elif choice == 2: struct = readstructure() print("input the number of layers") wait_sep() in_str = "" while in_str == "": in_str = input().strip() layer_number = int(in_str) print("input the layer distance") wait_sep() species = [] in_str = "" while in_str == "": in_str = input().strip() layer_distance = float(in_str) new_struct = move_to_zcenter(struct) struct_thickness = np.max(new_struct.cart_coords[:, 2]) - np.min( new_struct.cart_coords[:, 2]) natom = new_struct.num_sites new_cart_coords = np.zeros((natom * layer_number, 3)) for i in range(layer_number): new_cart_coords[i * natom:(i + 1) * natom, 0:2] = new_struct.cart_coords[:, 0:2] new_cart_coords[i * natom:(i + 1) * natom, 2] = new_struct.cart_coords[:, 2] + i * ( layer_distance + struct_thickness) species.extend(new_struct.species) new_lat = new_struct.lattice.matrix new_lat[2, 2] = new_lat[2, 2] + layer_distance * layer_number tmp_struct = Structure(new_lat, species, new_cart_coords, coords_are_cartesian=True) tmp1_struct = move_to_zcenter(tmp_struct) tmp2_struct = tmp1_struct.get_sorted_structure() tmp2_struct.to(filename='layer_' + str(layer_number) + '.vasp', fmt='poscar') elif choice == 3: ProperDist = 3.5 # Ang struct = readstructure() (atom_index, in_str) = atom_selection(struct) print("input the splitting distance, 10 Ang is enough!") wait_sep() in_str = "" while in_str == "": in_str = input().strip() SplitDistance = float(in_str) print("numbers of splitting site, 50 sites are enough!") wait_sep() in_str = "" while in_str == "": in_str = input().strip() NumberSplitSite = int(in_str) DensityN = int(NumberSplitSite * 0.75) SparseN = NumberSplitSite - DensityN + 1 # print(DensityN,SparseN) dist = ProperDist / (DensityN - 1) SplitDistanceArray = np.zeros(NumberSplitSite + 1) for Nsite in range(DensityN): SplitDistanceArray[Nsite] = (Nsite) * dist dist = (SplitDistance - ProperDist) / SparseN for Nsite in range(SparseN): SplitDistanceArray[Nsite + DensityN] = ProperDist + (Nsite + 1) * dist # print(SplitDistanceArray) coords = struct.cart_coords for Nsite in range(NumberSplitSite + 1): coords = struct.cart_coords for atom in atom_index: coords[atom, 2] = coords[atom, 2] + SplitDistanceArray[Nsite] tmp_struct = Structure(struct.lattice, struct.species, coords, coords_are_cartesian=True) fname = str(Nsite) + '.vasp' tmp_struct.to(filename=fname, fmt='poscar') data = np.zeros((NumberSplitSite + 1, 2)) for i, j in enumerate(SplitDistanceArray): data[i][0] = i data[i][1] = j head_line = "#%(key1)+12s %(key2)+12s" % { 'key1': 'index', 'key2': 'distance/Ang' } fmt = "%12d %12.6f" + '\n' write_col_data('split.dat', data, head_line, sp_fmt=fmt) return elif choice == 4: struct = readstructure() new_struct = move_to_zcenter(struct) struct_thickness = np.max(new_struct.cart_coords[:, 2]) - np.min( new_struct.cart_coords[:, 2]) vac_layer_thickness = new_struct.lattice.c - struct_thickness print("current vacuum layer thickness is %6.3f Ang" % (vac_layer_thickness)) print("input the new value of vacuum layer thickness") wait_sep() in_str = "" while in_str == "": in_str = input().strip() nvac_layer_thickness = float(in_str) assert (nvac_layer_thickness > struct_thickness) new_lat = new_struct.lattice.matrix new_lat[2, 2] = nvac_layer_thickness tmp_struct = Structure(new_lat, new_struct.species, new_struct.cart_coords, coords_are_cartesian=True) center_struct = move_to_zcenter(tmp_struct) center_struct.to(filename='new_vacuum.vasp', fmt='poscar') return elif choice == 5: struct = readstructure() new_struct = move_to_zcenter(struct) new_struct.to(filename='z-center.vasp', fmt='poscar') return elif choice == 6: struct = readstructure() assert (struct.lattice.is_orthogonal) try: import sympy except: print("you must install sympy module") return new_struct = move_to_zcenter(struct) print("input the elastic of material by order : C11 C12 C22 C66") wait_sep() in_str = "" while in_str == "": in_str = input().strip().split() elastic_constant = [float(x) for x in in_str] if len(elastic_constant) != 4: print("you must input C11 C12 C22 C66") return C11 = elastic_constant[0] C12 = elastic_constant[1] C22 = elastic_constant[2] C66 = elastic_constant[3] print("input applied force: e.x. 1.0 GPa nm") wait_sep() in_str = "" while in_str == "": in_str = input().strip() sigma = float(in_str) orig_struct = new_struct.copy() new_struct = new_struct.copy() natom = orig_struct.num_sites lat = orig_struct.lattice.matrix pos = orig_struct.frac_coords nps = 37 phi = np.linspace(0, 360, nps) * np.pi / 180 vzz = C12 / C22 temp_num = (C11 * C22 - C12**2) / (C22 * C66) d1 = C11 / C22 + 1.0 - temp_num d2 = -(2.0 * C12 / C22 - temp_num) d3 = C11 / C22 F = sigma * C22 / (C11 * C22 - C12**2.0) Poisson=(vzz*(np.cos(phi))**4.0-d1*(np.cos(phi))**2.0*(np.sin(phi))**2.0+vzz*(np.sin(phi))**4.0)/\ ((np.cos(phi))**4.0+d2*(np.cos(phi))**2.0*(np.sin(phi))**2.0+d3*(np.sin(phi))**4.0) eps_theta = F * ((np.cos(phi))**4 + d2 * (np.cos(phi))**2.0 * (np.sin(phi))**2.0 + d3 * (np.sin(phi))**4.0) t = sympy.Symbol('t', real=True) e = sympy.Symbol('e', real=True) v = sympy.Symbol('v', real=True) eprim = sympy.Matrix([[e + 1, 0], [0, 1 - e * v]]) R = sympy.Matrix([[sympy.cos(t), -sympy.sin(t)], [sympy.sin(t), sympy.cos(t)]]) eps_mat = R * eprim * R.adjugate() for k in range(len(phi)): cur__phi = phi[k] * 180 / np.pi Rot = eps_mat.subs({e: eps_theta[k], v: Poisson[k], t: phi[k]}) fname = str(k) + '.vasp' final_lat = np.matrix(np.eye(3)) final_lat[0, 0] = Rot[0, 0] final_lat[0, 1] = Rot[0, 1] final_lat[1, 0] = Rot[1, 0] final_lat[1, 1] = Rot[1, 1] lat_new = lat * final_lat tmp_struct = Structure(lat_new, new_struct.species, pos) tmp_struct.to(filename=fname, fmt='poscar') return elif choice == 7: struct = readstructure() natom = struct.num_sites atom_index, in_str = atom_selection(struct) selective_dynamics = [[True for col in range(3)] for row in range(natom)] for i in range(natom): if i in atom_index: selective_dynamics[i] = [False, False, False] tmp_struct = Structure( struct.lattice, struct.species, struct.frac_coords, site_properties={'selective_dynamics': selective_dynamics}) poscar = Poscar(tmp_struct) poscar.comment = poscar.comment + ' |--> ' + in_str poscar.write_file('Fixed.vasp') return elif choice == 8: print('your choice ?') print('{} >>> {}'.format('1', 'input 2D structure from local disk')) print('{} >>> {}'.format('2', 'get 2D structure online')) wait_sep() in_str = "" while in_str == "": in_str = input().strip() choice = int(in_str) if choice == 1: mpid = None struct = readstructure() else: print("input the mp-id for your structure") wait_sep() in_str = "" while in_str == "": in_str = input().strip() mpid = in_str struct = None film, substrates = make_connect(mpid=mpid, struct=struct) df = get_subs(film, substrates) df.to_csv('substrate.csv', sep=',', header=True, index=True) return else: print("unkonw choice") return
Module_Number, Situation_Number)) for Diffusion_Atom in Diffusion_Atoms: for Diffusion_Position in Diffusion_Positions: Substitutional_Number = Diffusion_Position[1] - 1 Substitutional_structure = deepcopy(Structure_Poscar.structure) Substitutional_Coord = deepcopy(Substitutional_structure[Substitutional_Number].coords) Substitutional_structure.remove_sites(range(Substitutional_Number, Substitutional_Number + 1)) Substitutional_structure.append(Diffusion_Atom, Substitutional_Coord, coords_are_cartesian=True) sd_init = np.ones((Substitutional_structure.num_sites, 3)) for number_atom in range(0,Substitutional_structure.num_sites): atom_position_z = Substitutional_structure[number_atom].z if atom_position_z<bottom_limit or atom_position_z >upper_limit: sd_init[number_atom]=np.zeros((1,3)) sd_atoms = sd_init Neb_Path = '/mnt/c/Users/jackx/OneDrive/Calculation_Data/TC17_TI80/NEB_Files/M{0}_S{1}/Substitutional/{2}/Optimistic/{3}'.format( Module_Number, Situation_Number, Diffusion_Atom, Diffusion_Position[ 0]) if os.path.exists(Neb_Path): shutil.rmtree(Neb_Path) os.makedirs(Neb_Path) Poscar_write = Poscar(Substitutional_structure) Poscar_write.selective_dynamics = sd_atoms Poscar_write.write_file('{}/POSCAR'.format(Neb_Path)) Poscar_write.structure.to(filename='{}/POSCAR.cif'.format(Neb_Path))
def vac_antisite_def_struct_gen(c_size=15,mpid='',struct=None): """ Vacancy, antisite generator Args: c_size: cell size struct: Structure object or mpid: materials project id Returns: def_str: defect structures in Poscar object format """ def_str=[] if struct ==None: with MPRester() as mp: struct = mp.get_structure_by_material_id(mpid) if mpid == '': print ("Provide structure") c_size=c_size dim1=int((float(c_size)/float( max(abs(struct.lattice.matrix[0])))))+1 dim2=int(float(c_size)/float( max(abs(struct.lattice.matrix[1]))))+1 dim3=int(float(c_size)/float( max(abs(struct.lattice.matrix[2]))))+1 cellmax=max(dim1,dim2,dim3) #print ("in vac_def cellmax=",cell prim_struct_sites = len(struct.sites) struct = SpacegroupAnalyzer(struct).get_conventional_standard_structure() conv_struct_sites = len(struct.sites) conv_prim_rat = int(conv_struct_sites/prim_struct_sites) #sc_scale = get_sc_scale(struct,cellmax) sc_scale=[dim1,dim2,dim3] #sc_scale=[cellmax,cellmax,cellmax] print ("sc_scale",sc_scale) #mpvis = MITRelaxSet #MPGGAVaspInputSet() # Begin defaults: All default settings. #blk_vasp_incar_param = {'IBRION':-1,'EDIFF':1e-4,'EDIFFG':0.001,'NSW':0,} #def_vasp_incar_param = {'ISIF':2,'NELM':99,'IBRION':2,'EDIFF':1e-6, # 'EDIFFG':0.001,'NSW':40,} #kpoint_den = 6000 # End defaults #ptcr_flag = True #try: # potcar = mpvis.get_potcar(struct) #except: # print ("VASP POTCAR folder not detected.\n" \ # "Only INCAR, POSCAR, KPOINTS are generated.\n" \ # "If you have VASP installed on this system, \n" \ # "refer to pymatgen documentation for configuring the settings.") # ptcr_flag = False struct_valrad_eval = ValenceIonicRadiusEvaluator(struct) val = struct_valrad_eval.valences rad = struct_valrad_eval.radii struct_val = val struct_rad = rad vac = Vacancy(struct, {}, {}) scs = vac.make_supercells_with_defects(sc_scale) #site_no = scs[0].num_sites #if site_no > cellmax: # max_sc_dim = max(sc_scale) # i = sc_scale.index(max_sc_dim) # sc_scale[i] -= 1 # scs = vac.make_supercells_with_defects(sc_scale) #print ('struct',scs) for i in range(len(scs)): sc = scs[i] #print (type(sc)) poscar = Poscar(sc) #mpvis.get_poscar(sc) #kpoints = Kpoints.automatic_density(sc,kpoint_den) #incar = mpvis.get_incar(sc) #if ptcr_flag: # potcar = mpvis.get_potcar(sc) interdir = mpid if not i: fin_dir = os.path.join(interdir,'bulk') #try: # os.makedirs(fin_dir) #except: # pass #incar.update(blk_vasp_incar_param) #incar.write_file(os.path.join(fin_dir,'INCAR')) #poscar.write_file(os.path.join(fin_dir,'POSCAR')) poscar.comment=str('bulk')+str('@')+str('cellmax')+str(cellmax) def_str.append(poscar) poscar.write_file('POSCAR-'+str('bulk')+str(".vasp")) #if ptcr_flag: # potcar.write_file(os.path.join(fin_dir,'POTCAR')) #kpoints.write_file(os.path.join(fin_dir,'KPOINTS')) else: blk_str_sites = set(scs[0].sites) vac_str_sites = set(sc.sites) vac_sites = blk_str_sites - vac_str_sites vac_site = list(vac_sites)[0] site_mult = int(vac.get_defectsite_multiplicity(i-1)/conv_prim_rat) #try: # site_mult = int(vac.get_defectsite_multiplicity(i-1)/conv_prim_rat) #except: # site_mult=1 # pass vac_site_specie = vac_site.specie vac_symbol = vac_site.specie.symbol vac_dir ='vacancy_{}_mult-{}_sitespecie-{}'.format(str(i), site_mult, vac_symbol) fin_dir = os.path.join(interdir,vac_dir) #try: # os.makedirs(fin_dir) #except: # pass #incar.update(def_vasp_incar_param) try: poscar.comment=str(vac_dir)+str('@')+str('cellmax')+str(cellmax) except: pass pos=poscar #pos=poscar.structure def_str.append(pos) #poscar.write_file(os.path.join(fin_dir,'POSCAR')) poscar.write_file('POSCAR-'+str(vac_dir)+str(".vasp")) #incar.write_file(os.path.join(fin_dir,'INCAR')) #if ptcr_flag: # potcar.write_file(os.path.join(fin_dir,'POTCAR')) #kpoints.write_file(os.path.join(fin_dir,'KPOINTS')) # Antisite generation at all vacancy sites struct_species = scs[0].types_of_specie for specie in set(struct_species)-set([vac_site_specie]): subspecie_symbol = specie.symbol anti_struct = sc.copy() anti_struct.append(specie, vac_site.frac_coords) poscar = Poscar(anti_struct) #incar = mpvis.get_incar(anti_struct) #incar.update(def_vasp_incar_param) as_dir ='antisite_{}_mult-{}_sitespecie-{}_subspecie-{}'.format( str(i), site_mult, vac_symbol, subspecie_symbol) fin_dir = os.path.join(interdir,as_dir) #try: # os.makedirs(fin_dir) #except: # pass poscar.comment=str(as_dir)+str('@')+str('cellmax')+str(cellmax) pos=poscar #pos=poscar.structure def_str.append(pos) #poscar.write_file(os.path.join(fin_dir,'POSCAR')) poscar.write_file('POSCAR-'+str(as_dir)+str(".vasp")) #incar.write_file(os.path.join(fin_dir,'INCAR')) #if ptcr_flag: # potcar.write_file(os.path.join(fin_dir,'POTCAR')) #kpoints.write_file(os.path.join(fin_dir,'KPOINTS')) #try: # struct.make_supercell(sc_scale) # intl = Interstitial(struct, val, rad) # cell_arr=sc_scale # for el in struct.composition.elements: # scs = intl.make_supercells_with_defects(1,el) # #scs = intl.make_supercells_with_defects(cell_arr,el) # for i in range(1,len(scs)): # pos=Poscar(scs[i]) # pos.comment=str('intl_')+str('cellmax')+str(cellmax)+str('@')+str(intl.get_defectsite_coordination_number(i-1))+str('Element')+str(el) # def_str.append(pos) # pos.write_file('POSCAR-'+str('intl_')+str('cellmax')+str(cellmax)+str('@')+str(intl.get_defectsite_coordination_number(i-1))+str('Element')+str(el)) #except: # pass return def_str
def poscar_wr(num, d): x = d[num]['final_str'] fileout = Poscar(x) filename = d[num]['final_str'].formula.replace(" ", "") + '.vasp' fileout.write_file(filename) print("Wrote " + filename)
# jaesung adds error handling code if flag == False: metadata["errorMessage"] = "Maximum Number of sites exceeded!" outputFileName = nowDatetime + "_" + condition ## devsky added file extension fname = os.path.split(file_path)[1] if fname != "POSCAR" and fname != "CIF" and fname != "CONTCAR": fname = str(file_path).split('_')[-1:][0] if condition == "download": outputFileName = outputFileName + "_" + chooseFileFormat structure.to(chooseFileFormat, poscarOutputPath + "/" + outputFileName) else: outputFileName = outputFileName + "_" + fname poscar_structure.write_file(poscarOutputPath + "/" + outputFileName) jsonFileName = nowDatetime + "_" + condition + "_METADATA.json" with open(poscarOutputPath + "/" + jsonFileName, 'w') as outfile: json.dump(metadata, outfile) ## devsky modified for JAVA output metadata["outputDatetime"] = nowDatetime metadata["outputFileName"] = outputFileName metadata["jsonFileName"] = jsonFileName outputMetadata = json.dumps(metadata) print(outputMetadata)
def pmg_surfer(vacuum=15, mat=None, max_index=1, min_slab_size=15, write_file=True): """ Pymatgen surface builder for a Poscar Args: vacuum: vacuum region mat: Structure object max_index: maximum miller index min_slab_size: minimum slab size Returns: structures: list of surface Structure objects """ if mat == None: print("Provide structure") sg_mat = SpacegroupAnalyzer(mat) mat_cvn = sg_mat.get_conventional_standard_structure() mat_cvn.sort() indices = get_symmetrically_distinct_miller_indices(mat_cvn, max_index) structures = [] pos = Poscar(mat_cvn) try: pos.comment = (str("sbulk") + str("@") + str("vac") + str(vacuum) + str("@") + str("size") + str(min_slab_size)) except: pass structures.append(pos) if write_file == True: mat_cvn.to(fmt="poscar", filename=str("POSCAR-") + str("cvn") + str(".vasp")) for i in indices: slab = SlabGenerator( initial_structure=mat_cvn, miller_index=i, min_slab_size=min_slab_size, min_vacuum_size=vacuum, lll_reduce=False, center_slab=True, primitive=False, ).get_slab() normal_slab = slab.get_orthogonal_c_slab() slab_pymatgen = Poscar(normal_slab).structure xy_size = min_slab_size dim1 = (int((float(xy_size) / float(max(abs(slab_pymatgen.lattice.matrix[0]))))) + 1) dim2 = (int( float(xy_size) / float(max(abs(slab_pymatgen.lattice.matrix[1])))) + 1) slab_pymatgen.make_supercell([dim1, dim2, 1]) slab_pymatgen.sort() surf_name = "_".join(map(str, i)) pos = Poscar(slab_pymatgen) try: pos.comment = (str("Surf-") + str(surf_name) + str("@") + str("vac") + str(vacuum) + str("@") + str("size") + str(min_slab_size)) except: pass if write_file == True: pos.write_file(filename=str("POSCAR-") + str("Surf-") + str(surf_name) + str(".vasp")) structures.append(pos) return structures