def get_aligned_lattices(slab_sub, slab_2d, max_area=200, max_mismatch=0.05, max_angle_diff=1, r1r2_tol=0.2): """ given the 2 slab structures and the alignment paramters, return slab structures with lattices that are aligned with respect to each other """ # get the matching substrate and 2D material lattices uv_substrate, uv_mat2d = get_matching_lattices(slab_sub, slab_2d, max_area=max_area, max_mismatch=max_mismatch, max_angle_diff=max_angle_diff, r1r2_tol=r1r2_tol) if not uv_substrate and not uv_mat2d: print("no matching u and v, trying adjusting the parameters") sys.exit() substrate = Structure.from_sites(slab_sub) mat2d = Structure.from_sites(slab_2d) # 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, :] ])) # to avoid numerical issues with find_mapping mat2d_fake_c = mat2d.lattice.matrix[2, :] / np.linalg.norm(mat2d.lattice.matrix[2, :]) * 5.0 mat2d_latt = Lattice(np.array( [ uv_mat2d[0][:], uv_mat2d[1][:], mat2d_fake_c ])) mat2d_latt_fake = Lattice(np.array( [ mat2d.lattice.matrix[0, :], mat2d.lattice.matrix[1, :], mat2d_fake_c ])) _, __, scell = substrate.lattice.find_mapping(substrate_latt, ltol=0.05, atol=1) scell[2] = np.array([0, 0, 1]) substrate.make_supercell(scell) _, __, scell = mat2d_latt_fake.find_mapping(mat2d_latt, ltol=0.05, atol=1) scell[2] = np.array([0, 0, 1]) mat2d.make_supercell(scell) # modify the substrate lattice so that the 2d material can be # grafted on top of it lmap = Lattice(np.array( [ substrate.lattice.matrix[0, :], substrate.lattice.matrix[1, :], mat2d.lattice.matrix[2, :] ])) mat2d.modify_lattice(lmap) return substrate, mat2d
def get_aligned_lattices(slab_sub, slab_2d, max_area=200, max_mismatch=0.05, max_angle_diff=1, r1r2_tol=0.2): """ given the 2 slab structures and the alignment paramters, return slab structures with lattices that are aligned with respect to each other """ # get the matching substrate and 2D material lattices uv_substrate, uv_mat2d = get_matching_lattices( slab_sub, slab_2d, max_area=max_area, max_mismatch=max_mismatch, max_angle_diff=max_angle_diff, r1r2_tol=r1r2_tol) if not uv_substrate and not uv_mat2d: print("no matching u and v, trying adjusting the parameters") sys.exit() substrate = Structure.from_sites(slab_sub) mat2d = Structure.from_sites(slab_2d) # 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, :] ])) # to avoid numerical issues with find_mapping mat2d_fake_c = mat2d.lattice.matrix[2, :] / np.linalg.norm( mat2d.lattice.matrix[2, :]) * 5.0 mat2d_latt = Lattice( np.array([uv_mat2d[0][:], uv_mat2d[1][:], mat2d_fake_c])) mat2d_latt_fake = Lattice( np.array([ mat2d.lattice.matrix[0, :], mat2d.lattice.matrix[1, :], mat2d_fake_c ])) _, __, scell = substrate.lattice.find_mapping(substrate_latt, ltol=0.05, atol=1) scell[2] = np.array([0, 0, 1]) substrate.make_supercell(scell) _, __, scell = mat2d_latt_fake.find_mapping(mat2d_latt, ltol=0.05, atol=1) scell[2] = np.array([0, 0, 1]) mat2d.make_supercell(scell) # modify the substrate lattice so that the 2d material can be # grafted on top of it lmap = Lattice( np.array([ substrate.lattice.matrix[0, :], substrate.lattice.matrix[1, :], mat2d.lattice.matrix[2, :] ])) mat2d.modify_lattice(lmap) return substrate, mat2d
def test_find_mapping(self): m = np.array([[0.1, 0.2, 0.3], [-0.1, 0.2, 0.7], [0.6, 0.9, 0.2]]) latt = Lattice(m) op = SymmOp.from_origin_axis_angle([0, 0, 0], [2, 3, 3], 35) rot = op.rotation_matrix scale = np.array([[1, 1, 0], [0, 1, 0], [0, 0, 1]]) latt2 = Lattice(np.dot(rot, np.dot(scale, m).T).T) (latt, rot, scale2) = latt2.find_mapping(latt) self.assertAlmostEqual(abs(np.linalg.det(rot)), 1) self.assertTrue(np.allclose(scale2, scale) or np.allclose(scale2, -scale))
def test_find_mapping(self): m = np.array([[0.1, 0.2, 0.3], [-0.1, 0.2, 0.7], [0.6, 0.9, 0.2]]) latt = Lattice(m) op = SymmOp.from_origin_axis_angle([0, 0, 0], [2, 3, 3], 35) rot = op.rotation_matrix scale = np.array([[1, 1, 0], [0, 1, 0], [0, 0, 1]]) latt2 = Lattice(np.dot(rot, np.dot(scale, m).T).T) (latt, rot, scale2) = latt2.find_mapping(latt) self.assertAlmostEqual(abs(np.linalg.det(rot)), 1) self.assertTrue( np.allclose(scale2, scale) or np.allclose(scale2, -scale))
def test_find_mapping(self): m = np.array([[0.1, 0.2, 0.3], [-0.1, 0.2, 0.7], [0.6, 0.9, 0.2]]) latt = Lattice(m) op = SymmOp.from_origin_axis_angle([0, 0, 0], [2, 3, 3], 35) rot = op.rotation_matrix scale = np.array([[1, 1, 0], [0, 1, 0], [0, 0, 1]]) latt2 = Lattice(np.dot(rot, np.dot(scale, m).T).T) (aligned_out, rot_out, scale_out) = latt2.find_mapping(latt) self.assertAlmostEqual(abs(np.linalg.det(rot)), 1) rotated = SymmOp.from_rotation_and_translation(rot_out).operate_multi(latt.matrix) self.assertArrayAlmostEqual(rotated, aligned_out.matrix) self.assertArrayAlmostEqual(np.dot(scale_out, latt2.matrix), aligned_out.matrix) self.assertArrayAlmostEqual(aligned_out.parameters, latt.parameters) self.assertFalse(np.allclose(aligned_out.parameters, latt2.parameters))
def test_find_mapping(self): m = np.array([[0.1, 0.2, 0.3], [-0.1, 0.2, 0.7], [0.6, 0.9, 0.2]]) latt = Lattice(m) op = SymmOp.from_origin_axis_angle([0, 0, 0], [2, 3, 3], 35) rot = op.rotation_matrix scale = np.array([[1, 1, 0], [0, 1, 0], [0, 0, 1]]) latt2 = Lattice(np.dot(rot, np.dot(scale, m).T).T) (aligned_out, rot_out, scale_out) = latt2.find_mapping(latt) self.assertAlmostEqual(abs(np.linalg.det(rot)), 1) rotated = SymmOp.from_rotation_and_translation(rot_out).operate_multi(latt.matrix) self.assertArrayAlmostEqual(rotated, aligned_out.matrix) self.assertArrayAlmostEqual(np.dot(scale_out, latt2.matrix), aligned_out.matrix) self.assertArrayAlmostEqual(aligned_out.lengths_and_angles, latt.lengths_and_angles) self.assertFalse(np.allclose(aligned_out.lengths_and_angles, latt2.lengths_and_angles))
def process_sys( slab_sub, slab_2d, uv_substrate, uv_mat2d, ): """ """ #| - process_sys substrate = Structure.from_sites(slab_sub) mat2d = Structure.from_sites(slab_2d) # 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, :] ] ) ) # to avoid numerical issues with find_mapping mat2d_fake_c = mat2d.lattice.matrix[2, :] / np.linalg.norm( mat2d.lattice.matrix[2, :]) * 5.0 mat2d_latt = Lattice( np.array( [ uv_mat2d[0][:], uv_mat2d[1][:], mat2d_fake_c ] ) ) mat2d_latt_fake = Lattice( np.array( [ mat2d.lattice.matrix[0, :], mat2d.lattice.matrix[1, :], mat2d_fake_c ] ) ) _, __, scell = substrate.lattice.find_mapping(substrate_latt, ltol=0.05, atol=1) scell[2] = np.array([0, 0, 1]) substrate.make_supercell(scell) _, __, scell = mat2d_latt_fake.find_mapping(mat2d_latt, ltol=0.05, atol=1) scell[2] = np.array([0, 0, 1]) mat2d.make_supercell(scell) # modify the substrate lattice so that the 2d material can be # grafted on top of it lmap = Lattice( np.array( [ substrate.lattice.matrix[0, :], substrate.lattice.matrix[1, :], mat2d.lattice.matrix[2, :] ] ) ) mat2d.modify_lattice(lmap) return(substrate, mat2d)
def mismatch_strts(film=[], subs=[]): z = ZSLGenerator() matches = list( z(film.lattice.matrix[:2], subs.lattice.matrix[:2], lowest=True)) info = {} info["mismatch_u"] = "na" info["mismatch_v"] = "na" info["mismatch_angle"] = "na" info["area1"] = "na" info["area2"] = "na" info["film_sl"] = film info["subs_sl"] = subs try: uv1 = matches[0]["sub_sl_vecs"] uv2 = matches[0]["film_sl_vecs"] # uv1=[[-8.52917200e+00, 9.12745800e+00, 3.66344517e-17],[1.27937580e+01, 9.12745800e+00, 1.34228735e-15]] # uv2=[[7.02403800e+00, 1.05360570e+01, 1.07524571e-15],[-1.40480760e+01, 7.02403800e+00, -4.30098283e-16]] u = np.array(uv1) v = np.array(uv2) a1 = u[0] a2 = u[1] b1 = v[0] b2 = v[1] mismatch_u = np.linalg.norm(b1) / np.linalg.norm(a1) - 1 mismatch_v = np.linalg.norm(b2) / np.linalg.norm(a2) - 1 angle1 = (np.arccos( np.dot(a1, a2) / np.linalg.norm(a1) / np.linalg.norm(a2)) * 180 / np.pi) angle2 = (np.arccos( np.dot(b1, b2) / np.linalg.norm(b1) / np.linalg.norm(b2)) * 180 / np.pi) mismatch_angle = abs(angle1 - angle2) area1 = np.linalg.norm(np.cross(a1, a2)) area2 = np.linalg.norm(np.cross(b1, b2)) uv_substrate = uv1 uv_mat2d = uv2 substrate_latt = Lattice( np.array([ uv_substrate[0][:], uv_substrate[1][:], subs.lattice.matrix[2, :] ])) # to avoid numerical issues with find_mapping mat2d_fake_c = (film.lattice.matrix[2, :] / np.linalg.norm(film.lattice.matrix[2, :]) * 5.0) mat2d_latt = Lattice( np.array([uv_mat2d[0][:], uv_mat2d[1][:], mat2d_fake_c])) mat2d_latt_fake = Lattice( np.array([ film.lattice.matrix[0, :], film.lattice.matrix[1, :], mat2d_fake_c ])) _, __, scell = subs.lattice.find_mapping(substrate_latt, ltol=0.05, atol=1) scell[2] = np.array([0, 0, 1]) subs.make_supercell(scell) _, __, scell = mat2d_latt_fake.find_mapping(mat2d_latt, ltol=0.05, atol=1) scell[2] = np.array([0, 0, 1]) film.make_supercell(scell) # modify the substrate lattice so that the 2d material can be # grafted on top of it lmap = Lattice( np.array([ subs.lattice.matrix[0, :], subs.lattice.matrix[1, :], film.lattice.matrix[2, :], ])) film.modify_lattice(lmap) # print ("film",film) # print ("subs",subs) info["mismatch_u"] = mismatch_u info["mismatch_v"] = mismatch_v info["mismatch_angle"] = mismatch_angle info["area1"] = area1 info["area2"] = area2 info["film_sl"] = film info["subs_sl"] = subs except: pass return info