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 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 vac_intl(cellmax=2, mpid='', struct=None): """ Vacancy and interstitial generator Args: cellmax: maximum cell size struct: Structure object Returns: def_str: defect structures """ if struct == None: with MPRester() as mp: struct = mp.get_structure_by_material_id(mpid) if mpid == '': print("Provide structure") sg_mat = SpacegroupAnalyzer(struct) struct = sg_mat.get_conventional_standard_structure() def_str = [] count = 0 cell_arr = [cellmax, cellmax, cellmax] vac = Vacancy(struct, {}, {}) for el in list(struct.symbol_set): scs = vac.make_supercells_with_defects(cell_arr, el) for i in range(len(scs)): if i == 0: pos = Poscar(scs[i]) pos.comment = str('bulk') + str('.') + str('cellmax') + str( cellmax) if count == 0: def_str.append(pos) count = count + 1 else: pos = Poscar(scs[i]) pos.comment = str('vac') + str('cellmax') + str(cellmax) + str( '@') + str(vac.get_defectsite_multiplicity(i)) + str( 'Element') + str(el) if pos not in def_str: def_str.append(pos) struct_valrad_eval = ValenceIonicRadiusEvaluator(struct) val = struct_valrad_eval.valences rad = struct_valrad_eval.radii struct_val = val struct_rad = rad intl = Interstitial(struct, val, rad) for el in struct.composition.elements: 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) if pos not in def_str: def_str.append(pos) print(len(def_str)) return def_str
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 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 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)
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
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 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
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