#      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")
Exemple #3
0
                      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")