def surface_vectors(lattice, miller): ''' Given the xtal as defined with a (3x3) cell uses the ase surface module to cut the required surface. Args: lattice : ase Atoms object miller : miller indices of the surface, a tuple of integers, length 3. Returns: vectors[0/1] : the surface vectors (u,v), list of real numbers. ''' surf = surface.surface(lattice, miller, layers=1) vectors = surf.cell[0:2] return vectors[0], vectors[1]
def surface_vectors(lattice,miller): ''' Given the xtal as defined with a (3x3) cell uses the ase surface module to cut the required surface. Args: lattice : ase Atoms object miller : miller indices of the surface, a tuple of integers, length 3. Returns: vectors[0/1] : the surface vectors (u,v), list of real numbers. ''' surf = surface.surface(lattice,miller,layers=1) vectors = surf.cell[0:2] return vectors[0],vectors[1]
def make_super_cell_pymatgen(jdata): make_unit_cell(jdata) out_dir = jdata['out_dir'] path_uc = os.path.join(out_dir, global_dirname_02) from_path = path_uc from_file = os.path.join(from_path, 'POSCAR.unit') ss = Structure.from_file(from_file) # ase only support X type element for i in range(len(ss)): ss[i] = 'X' ss = AseAtomsAdaptor.get_atoms(ss) all_millers = jdata['millers'] path_sc = os.path.join(out_dir, global_dirname_02) #z_min = jdata['z_min'] layer_numb = jdata['layer_numb'] super_cell = jdata['super_cell'] cwd = os.getcwd() path_work = (path_sc) path_work = os.path.abspath(path_work) os.chdir(path_work) for miller in all_millers: miller_str = "" for ii in miller: miller_str += str(ii) path_cur_surf = create_path('surf-' + miller_str) os.chdir(path_cur_surf) #slabgen = SlabGenerator(ss, miller, z_min, 1e-3) slab = general_surface.surface(ss, indices=miller, vacuum=1e-3, layers=layer_numb) #all_slabs = slabgen.get_slabs() dlog.info(os.getcwd()) #dlog.info("Miller %s: The slab has %s termination, use the first one" %(str(miller), len(all_slabs))) #all_slabs[0].to('POSCAR', 'POSCAR') slab.write('POSCAR', vasp5=True) if super_cell[0] > 1 or super_cell[1] > 1: st = Structure.from_file('POSCAR') st.make_supercell([super_cell[0], super_cell[1], 1]) st.to('POSCAR', 'POSCAR') os.chdir(path_work) os.chdir(cwd)
def surfaces_with_termination(lattice, indices, layers, vacuum=None, tol=1e-10, termination=None, return_all=False, verbose=False): """Create surface from a given lattice and Miller indices with a given termination Parameters ========== lattice: Atoms object or str Bulk lattice structure of alloy or pure metal. Note that the unit-cell must be the conventional cell - not the primitive cell. One can also give the chemical symbol as a string, in which case the correct bulk lattice will be generated automatically. indices: sequence of three int Surface normal in Miller indices (h,k,l). layers: int Number of equivalent layers of the slab. (not the same as the layers you choose from for terminations) vacuum: float Amount of vacuum added on both sides of the slab. termination: str the atoms you wish to be in the top layer. There may be many such terminations, this function returns all terminations with the same atomic composition. e.g. 'O' will return oxygen terminated surfaces. e.g.'TiO' will return surfaces terminated with layers containing both O and Ti Returns: return_surfs: List a list of surfaces that match the specifications given """ lats = translate_lattice(lattice, indices) return_surfs = [] check = [] check2 = [] for item in lats: too_similar = False surf = surface(item, indices, layers, vacuum=vacuum, tol=tol) surf.wrap(pbc=[True] * 3) # standardize slabs positions = surf.get_scaled_positions().flatten() for i, value in enumerate(positions): if value >= 1 - tol: # move things closer to zero within tol positions[i] -= 1 surf.set_scaled_positions(np.reshape(positions, (len(surf), 3))) #rep = find_z_layers(surf) z_layers, hs = get_layers(surf, (0, 0, 1)) # just z layers matter # get the indicies of the atoms in the highest layer top_layer = [ i for i, val in enumerate(z_layers == max(z_layers)) if val ] if termination is not None: comp = [surf.get_chemical_symbols()[a] for a in top_layer] term = string2symbols(termination) # list atoms in top layer and not in requested termination check = [a for a in comp if a not in term] # list of atoms in requested termination and not in top layer check2 = [a for a in term if a not in comp] if len(return_surfs) > 0: pos_diff = [ a.get_positions() - surf.get_positions() for a in return_surfs ] for i, su in enumerate(pos_diff): similarity_test = su.flatten() < tol * 1000 if similarity_test.all(): # checks if surface is too similar to another surface too_similar = True if too_similar: continue if return_all is True: pass elif check != [] or check2 != []: continue return_surfs.append(surf) return return_surfs
def make_super_cell_pymatgen(jdata): make_unit_cell(jdata) out_dir = jdata['out_dir'] path_uc = os.path.join(out_dir, global_dirname_02) elements = [Element(ii) for ii in jdata['elements']] if 'vacuum_min' in jdata: vacuum_min = jdata['vacuum_min'] else: vacuum_min = max([float(ii.atomic_radius) for ii in elements]) from_poscar = jdata.get('from_poscar', False) if from_poscar: from_poscar_path = jdata['from_poscar_path'] poscar_name = os.path.basename(from_poscar_path) ss = Structure.from_file(poscar_name) else: from_path = path_uc from_file = os.path.join(from_path, 'POSCAR.unit') ss = Structure.from_file(from_file) # ase only support X type element for i in range(len(ss)): ss[i] = 'X' ss = AseAtomsAdaptor.get_atoms(ss) all_millers = jdata['millers'] path_sc = os.path.join(out_dir, global_dirname_02) user_layer_numb = None # set default value z_min = None if 'layer_numb' in jdata: user_layer_numb = jdata['layer_numb'] else: z_min = jdata['z_min'] super_cell = jdata['super_cell'] cwd = os.getcwd() path_work = (path_sc) path_work = os.path.abspath(path_work) os.chdir(path_work) for miller in all_millers: miller_str = "" for ii in miller: miller_str += str(ii) path_cur_surf = create_path('surf-' + miller_str) os.chdir(path_cur_surf) #slabgen = SlabGenerator(ss, miller, z_min, 1e-3) if user_layer_numb: slab = general_surface.surface(ss, indices=miller, vacuum=vacuum_min, layers=user_layer_numb) else: # build slab according to z_min value for layer_numb in range(1, max_layer_numb + 1): slab = general_surface.surface(ss, indices=miller, vacuum=vacuum_min, layers=layer_numb) if slab.cell.lengths()[-1] >= z_min: break if layer_numb == max_layer_numb: raise RuntimeError("can't build the required slab") #all_slabs = slabgen.get_slabs() dlog.info(os.getcwd()) #dlog.info("Miller %s: The slab has %s termination, use the first one" %(str(miller), len(all_slabs))) #all_slabs[0].to('POSCAR', 'POSCAR') slab.write('POSCAR', vasp5=True) if super_cell[0] > 1 or super_cell[1] > 1: st = Structure.from_file('POSCAR') st.make_supercell([super_cell[0], super_cell[1], 1]) st.to('POSCAR', 'POSCAR') os.chdir(path_work) os.chdir(cwd)