# the subtrate in the substrate's vacuum space. # So ensure that the substrate vacuum spacing is sufficietly # large enough to contain the 2d material substrate = Interface(substrate_bulk, hkl=[1, 1, 0], min_thick=10, min_vac=25, primitive=False, from_ase=True) mat2d = Interface(mat2d_bulk, hkl=[1, 1, 0], min_thick=2, min_vac=0, primitive=False, from_ase=True) substrate.to(fmt='poscar', filename='POSCAR_substrate_initial.vasp') mat2d.to(fmt='poscar', filename='POSCAR_mat2d_initial.vasp') # get the matching substrate and 2D material lattices uv_substrate, uv_mat2d = get_matching_lattices(substrate, mat2d, max_area=200, max_mismatch=0.01, max_angle_diff=1, r1r2_tol=0.02) # map the intial slabs to the newly found matching lattices substrate_latt = Lattice( np.array([ uv_substrate[0][:], uv_substrate[1][:], substrate.lattice.matrix[2, :]
iface = Interface(strt, hkl=hkl, min_thick=min_thick, min_vac=min_vac, supercell=supercell, surface_coverage=0.01, ligand=hydrazine, displacement=displacement, adatom_on_lig='N', adsorb_on_species='Pb', primitive=False) iface.create_interface() iface.sort() # extract bare slab iface_slab = iface.slab iface_slab.sort() # set selective dynamics flags as required true_site = [1, 1, 1] false_site = [0, 0, 0] sd_flag_iface = [] sd_flag_slab = [] # selective dynamics flags for the interface for i in iface.sites: sd_flag_iface.append(false_site) # selective dynamics flags for the bare slab for i in iface_slab.sites: sd_flag_slab.append(false_site) interface_poscar = Poscar(iface, selective_dynamics=sd_flag_iface) slab_poscar = Poscar(iface_slab, selective_dynamics=sd_flag_slab) # poscars without selective dynamics flag iface.to('poscar', 'POSCAR_interface.vasp') iface_slab.to('poscar', 'POSCAR_slab.vasp') # poscars with selective dynamics flag interface_poscar.write_file("POSCAR_interface_with_sd.vasp") slab_poscar.write_file("POSCAR_slab_with_sd.vasp")
surface_coverage=0.01, ligand=hydrazine, displacement=displacement, adatom_on_lig='N', adsorb_on_species='Pb', primitive=False) iface.create_interface() iface.sort() # extract bare slab iface_slab = iface.slab iface_slab.sort() # set selective dynamics flags as required true_site = [1, 1, 1] false_site = [0, 0, 0] sd_flag_iface = [] sd_flag_slab = [] # selective dynamics flags for the interface for i in iface.sites: sd_flag_iface.append(false_site) # selective dynamics flags for the bare slab for i in iface_slab.sites: sd_flag_slab.append(false_site) interface_poscar = Poscar(iface, selective_dynamics=sd_flag_iface) slab_poscar = Poscar(iface_slab, selective_dynamics=sd_flag_slab) # poscars without selective dynamics flag iface.to('poscar', 'POSCAR_interface.vasp') iface_slab.to('poscar', 'POSCAR_slab.vasp') # poscars with selective dynamics flag interface_poscar.write_file("POSCAR_interface_with_sd.vasp") slab_poscar.write_file("POSCAR_slab_with_sd.vasp")
def get_grain_boundary_interface(structure=None, hkl_pair= {'hkl': [[1,0,0],[1,1,0]],\ 'thickness':[10,10]}, twist = 0, tilt = 0, separation=0): """ Args: structure: pymatgen structure to create grain boundary in hkl_pair: dict of {'hkl':thickness} twist: twist in degrees tilt: tilt in degrees """ structure = get_struct_from_mp(structure, MAPI_KEY="") sa = SpacegroupAnalyzer(structure) structure_conventional = sa.get_conventional_standard_structure() structure = structure_conventional.copy() structure.sort() #creation of lower part of grain boundary lower= Interface(structure,\ hkl = hkl_pair['hkl'][0], min_thick = hkl_pair['thickness'][0], min_vac = separation+hkl_pair['thickness'][1], primitive = False, from_ase = True, center_slab=False) lower.to(fmt="poscar", filename="POSCAR_lower.vasp") #creation of upper part of grain boundary upper= Interface(structure,\ hkl = hkl_pair['hkl'][1], min_thick = hkl_pair['thickness'][1], min_vac = 0, primitive = False, from_ase = True) #find top atoms reference of lower part of gb substrate_top_z = np.max(np.array([site.coords for site in lower])[:, 2]) # define twist and tilt vectors twist_shift_normal = lower.lattice.matrix[2,:]/\ np.linalg.norm(lower.lattice.matrix[2,:]) tilt_normal = upper.lattice.matrix[1,:]/\ np.linalg.norm(upper.lattice.matrix[2,:]) #define twist operation SymmOp object twist_op = SymmOp.from_axis_angle_and_translation(axis= twist_shift_normal,\ angle=twist, angle_in_radians=False,translation_vec=(0, 0, 0)) #define tilt operation SymmOp object tilt_op = SymmOp.from_axis_angle_and_translation(axis= tilt_normal,\ angle=tilt, angle_in_radians=False,translation_vec=(0, 0, 0)) upper.apply_operation(twist_op) upper.to(fmt="poscar", filename="POSCAR_upper.vasp") upper.apply_operation(tilt_op) #define shift separation along twist vector normal to upper plane shift = -1 * twist_shift_normal / np.linalg.norm( twist_shift_normal) * separation #define origin to shift w.r.t top of the lower grain origin = np.array([0, 0, substrate_top_z]) #shift sites in upper for site in upper: new_coords = site.coords - origin + shift lower.append(site.specie, new_coords, coords_are_cartesian=True) return lower
def get_grain_boundary_interface(structure=None, hkl_pair= {'hkl': [[1,0,0],[1,1,0]],\ 'thickness':[10,10]}, twist = 0, tilt = 0, separation=0): """ Args: structure: pymatgen structure to create grain boundary in hkl_pair: dict of {'hkl':thickness} twist: twist in degrees tilt: tilt in degrees """ structure = get_struct_from_mp(structure, MAPI_KEY="") sa = SpacegroupAnalyzer(structure) structure_conventional = sa.get_conventional_standard_structure() structure = structure_conventional.copy() structure.sort() #creation of lower part of grain boundary lower= Interface(structure,\ hkl = hkl_pair['hkl'][0], min_thick = hkl_pair['thickness'][0], min_vac = separation+hkl_pair['thickness'][1], primitive = False, from_ase = True, center_slab=False) lower.to(fmt="poscar", filename="POSCAR_lower.vasp") #creation of upper part of grain boundary upper= Interface(structure,\ hkl = hkl_pair['hkl'][1], min_thick = hkl_pair['thickness'][1], min_vac = 0, primitive = False, from_ase = True) #find top atoms reference of lower part of gb substrate_top_z = np.max(np.array([site.coords for site in lower])[:,2]) # define twist and tilt vectors twist_shift_normal = lower.lattice.matrix[2,:]/\ np.linalg.norm(lower.lattice.matrix[2,:]) tilt_normal = upper.lattice.matrix[1,:]/\ np.linalg.norm(upper.lattice.matrix[2,:]) #define twist operation SymmOp object twist_op = SymmOp.from_axis_angle_and_translation(axis= twist_shift_normal,\ angle=twist, angle_in_radians=False,translation_vec=(0, 0, 0)) #define tilt operation SymmOp object tilt_op = SymmOp.from_axis_angle_and_translation(axis= tilt_normal,\ angle=tilt, angle_in_radians=False,translation_vec=(0, 0, 0)) upper.apply_operation(twist_op) upper.to(fmt="poscar", filename="POSCAR_upper.vasp") upper.apply_operation(tilt_op) #define shift separation along twist vector normal to upper plane shift = -1*twist_shift_normal/np.linalg.norm(twist_shift_normal) * separation #define origin to shift w.r.t top of the lower grain origin = np.array([0,0, substrate_top_z]) #shift sites in upper for site in upper: new_coords = site.coords - origin + shift lower.append(site.specie, new_coords, coords_are_cartesian=True) return lower
# 2d material vacuum spacing = 0 # keep in mind that the 2d material will be put on top of # the subtrate in the substrate's vacuum space. # So ensure that the substrate vacuum spacing is sufficietly # large enough to contain the 2d material substrate = Interface(substrate_bulk, hkl = [1,1,0], min_thick = 10, min_vac = 25, primitive = False, from_ase = True) mat2d = Interface(mat2d_bulk, hkl = [1,1,0], min_thick = 2, min_vac = 0, primitive = False, from_ase = True) substrate.to(fmt='poscar', filename='POSCAR_substrate_initial.vasp') mat2d.to(fmt='poscar', filename='POSCAR_mat2d_initial.vasp') # get the matching substrate and 2D material lattices uv_substrate, uv_mat2d = get_matching_lattices(substrate, mat2d, max_area = 200, max_mismatch = 0.01, max_angle_diff = 1, r1r2_tol = 0.02) # map the intial slabs to the newly found matching lattices substrate_latt = Lattice( np.array( [ uv_substrate[0][:], uv_substrate[1][:], substrate.lattice.matrix[2,:] ] ))
ligand=hydrazine, displacement=displacement, adatom_on_lig="N", adsorb_on_species="Pb", primitive=False, ) iface.create_interface() iface.sort() # extract bare slab iface_slab = iface.slab iface_slab.sort() # set selective dynamics flags as required true_site = [1, 1, 1] false_site = [0, 0, 0] sd_flag_iface = [] sd_flag_slab = [] # selective dynamics flags for the interface for i in iface.sites: sd_flag_iface.append(false_site) # selective dynamics flags for the bare slab for i in iface_slab.sites: sd_flag_slab.append(false_site) interface_poscar = Poscar(iface, selective_dynamics=sd_flag_iface) slab_poscar = Poscar(iface_slab, selective_dynamics=sd_flag_slab) # poscars without selective dynamics flag iface.to("poscar", "POSCAR_interface.vasp") iface_slab.to("poscar", "POSCAR_slab.vasp") # poscars with selective dynamics flag interface_poscar.write_file("POSCAR_interface_with_sd.vasp") slab_poscar.write_file("POSCAR_slab_with_sd.vasp")