def test_find_match1(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=True, scale=True, attempt_supercell=False) l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ['Si', 'Si', 'Ag'], [[0, 0, 0.1], [0, 0, 0.2], [.7, .4, .5]]) s2 = Structure(l, ['Si', 'Si', 'Ag'], [[0, 0.1, 0], [0, 0.1, -0.95], [.7, .5, .375]]) s1, s2, fu, s1_supercell = sm._preprocess(s1, s2, False) match = sm._strict_match(s1, s2, fu, s1_supercell=True, use_rms=True, break_on_match=False) scale_matrix = match[2] s2.make_supercell(scale_matrix) fc = s2.frac_coords + match[3] fc -= np.round(fc) self.assertAlmostEqual(np.sum(fc), 0.9) self.assertAlmostEqual(np.sum(fc[:, :2]), 0.1) cart_dist = np.sum(match[1] * (l.volume / 3)**(1 / 3)) self.assertAlmostEqual(cart_dist, 0.15)
def test_find_match2(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=True, scale=True, attempt_supercell=False) l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ['Si', 'Si'], [[0, 0, 0.1], [0, 0, 0.2]]) s2 = Structure(l, ['Si', 'Si'], [[0, 0.1, 0], [0, 0.1, -0.95]]) s1, s2, fu, s1_supercell = sm._preprocess(s1, s2, False) match = sm._strict_match(s1, s2, fu, s1_supercell=False, use_rms=True, break_on_match=False) scale_matrix = match[2] s2.make_supercell(scale_matrix) s2.translate_sites(range(len(s2)), match[3]) self.assertAlmostEqual(np.sum(s2.frac_coords), 0.3) self.assertAlmostEqual(np.sum(s2.frac_coords[:, :2]), 0)
def test_disordered_primitive_to_ordered_supercell(self): sm_atoms = StructureMatcher( ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=True, attempt_supercell=True, allow_subset=True, supercell_size='num_atoms', comparator=OrderDisorderElementComparator()) sm_sites = StructureMatcher( ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=True, attempt_supercell=True, allow_subset=True, supercell_size='num_sites', comparator=OrderDisorderElementComparator()) lp = Lattice.orthorhombic(10, 20, 30) pcoords = [[0, 0, 0], [0.5, 0.5, 0.5]] ls = Lattice.orthorhombic(20, 20, 30) scoords = [[0, 0, 0], [0.75, 0.5, 0.5]] prim = Structure(lp, [{'Na': 0.5}, {'Cl': 0.5}], pcoords) supercell = Structure(ls, ['Na', 'Cl'], scoords) supercell.make_supercell([[-1, 1, 0], [0, 1, 1], [1, 0, 0]]) self.assertFalse(sm_sites.fit(prim, supercell)) self.assertTrue(sm_atoms.fit(prim, supercell)) self.assertRaises(ValueError, sm_atoms.get_s2_like_s1, prim, supercell) self.assertEqual(len(sm_atoms.get_s2_like_s1(supercell, prim)), 4)
def test_get_supercell_matrix(self): sm = StructureMatcher(ltol=0.1, stol=0.3, angle_tol=2, primitive_cell=False, scale=True, attempt_supercell=True) l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ['Si', 'Si', 'Ag'], [[0,0,0.1],[0,0,0.2],[.7,.4,.5]]) s1.make_supercell([2,1,1]) s2 = Structure(l, ['Si', 'Si', 'Ag'], [[0,0.1,0],[0,0.1,-0.95],[-.7,.5,.375]]) result = sm.get_supercell_matrix(s1, s2) self.assertTrue((result == [[-2,0,0],[0,1,0],[0,0,1]]).all()) s1 = Structure(l, ['Si', 'Si', 'Ag'], [[0,0,0.1],[0,0,0.2],[.7,.4,.5]]) s1.make_supercell([[1, -1, 0],[0, 0, -1],[0, 1, 0]]) s2 = Structure(l, ['Si', 'Si', 'Ag'], [[0,0.1,0],[0,0.1,-0.95],[-.7,.5,.375]]) result = sm.get_supercell_matrix(s1, s2) self.assertTrue((result == [[-1,-1,0],[0,0,-1],[0,1,0]]).all()) #test when the supercell is a subset sm = StructureMatcher(ltol=0.1, stol=0.3, angle_tol=2, primitive_cell=False, scale=True, attempt_supercell=True, allow_subset=True) del s1[0] result = sm.get_supercell_matrix(s1, s2) self.assertTrue((result == [[-1,-1,0],[0,0,-1],[0,1,0]]).all())
def test_get_mapping(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=True, attempt_supercell=False, allow_subset = True) l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ['Ag', 'Si', 'Si'], [[.7,.4,.5],[0,0,0.1],[0,0,0.2]]) s1.make_supercell([2,1,1]) s2 = Structure(l, ['Si', 'Si', 'Ag'], [[0,0.1,-0.95],[0,0.1,0],[-.7,.5,.375]]) shuffle = [2,0,1,3,5,4] s1 = Structure.from_sites([s1[i] for i in shuffle]) #test the mapping s2.make_supercell([2,1,1]) #equal sizes for i, x in enumerate(sm.get_mapping(s1, s2)): self.assertEqual(s1[x].species_and_occu, s2[i].species_and_occu) del s1[0] #s1 is subset of s2 for i, x in enumerate(sm.get_mapping(s2, s1)): self.assertEqual(s1[i].species_and_occu, s2[x].species_and_occu) #s2 is smaller than s1 del s2[0] del s2[1] self.assertRaises(ValueError, sm.get_mapping, s2, s1)
def test_get_supercell_matrix(self): sm = StructureMatcher(ltol=0.1, stol=0.3, angle_tol=2, primitive_cell=False, scale=True, attempt_supercell=True) l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ['Si', 'Si', 'Ag'], [[0,0,0.1],[0,0,0.2],[.7,.4,.5]]) s1.make_supercell([2,1,1]) s2 = Structure(l, ['Si', 'Si', 'Ag'], [[0,0.1,0],[0,0.1,-0.95],[-.7,.5,.375]]) result = sm.get_supercell_matrix(s1, s2) self.assertTrue((result == [[-2,0,0],[0,1,0],[0,0,1]]).all()) s1 = Structure(l, ['Si', 'Si', 'Ag'], [[0,0,0.1],[0,0,0.2],[.7,.4,.5]]) s1.make_supercell([[1, -1, 0],[0, 0, -1],[0, 1, 0]]) s2 = Structure(l, ['Si', 'Si', 'Ag'], [[0,0.1,0],[0,0.1,-0.95],[-.7,.5,.375]]) result = sm.get_supercell_matrix(s1, s2) self.assertTrue((result == [[-1,-1,0],[0,0,-1],[0,1,0]]).all()) #test when the supercell is a subset sm = StructureMatcher(ltol=0.1, stol=0.3, angle_tol=2, primitive_cell=False, scale=True, attempt_supercell=True, allow_subset=True) del s1[0] result = sm.get_supercell_matrix(s1, s2) self.assertTrue((result == [[-1,-1,0],[0,0,-1],[0,1,0]]).all())
def test_get_mapping(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=True, attempt_supercell=False, allow_subset=True) l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ['Ag', 'Si', 'Si'], [[.7, .4, .5], [0, 0, 0.1], [0, 0, 0.2]]) s1.make_supercell([2, 1, 1]) s2 = Structure(l, ['Si', 'Si', 'Ag'], [[0, 0.1, -0.95], [0, 0.1, 0], [-.7, .5, .375]]) shuffle = [2, 0, 1, 3, 5, 4] s1 = Structure.from_sites([s1[i] for i in shuffle]) #test the mapping s2.make_supercell([2, 1, 1]) #equal sizes for i, x in enumerate(sm.get_mapping(s1, s2)): self.assertEqual(s1[x].species_and_occu, s2[i].species_and_occu) del s1[0] #s1 is subset of s2 for i, x in enumerate(sm.get_mapping(s2, s1)): self.assertEqual(s1[i].species_and_occu, s2[x].species_and_occu) #s2 is smaller than s1 del s2[0] del s2[1] self.assertRaises(ValueError, sm.get_mapping, s2, s1)
def test_disordered_primitive_to_ordered_supercell(self): sm_atoms = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=True, attempt_supercell=True, allow_subset=True, supercell_size = 'num_atoms', comparator=OrderDisorderElementComparator()) sm_sites = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=True, attempt_supercell=True, allow_subset=True, supercell_size = 'num_sites', comparator=OrderDisorderElementComparator()) lp = Lattice.orthorhombic(10, 20, 30) pcoords = [[0, 0, 0], [0.5, 0.5, 0.5]] ls = Lattice.orthorhombic(20,20,30) scoords = [[0, 0, 0], [0.75, 0.5, 0.5]] prim = Structure(lp, [{'Na':0.5}, {'Cl':0.5}], pcoords) supercell = Structure(ls, ['Na', 'Cl'], scoords) supercell.make_supercell([[-1,1,0],[0,1,1],[1,0,0]]) self.assertFalse(sm_sites.fit(prim, supercell)) self.assertTrue(sm_atoms.fit(prim, supercell)) self.assertRaises(ValueError, sm_atoms.get_s2_like_s1, prim, supercell) self.assertEqual(len(sm_atoms.get_s2_like_s1(supercell, prim)), 4)
def test_find_match2(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=True, scale=True, attempt_supercell=False) l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ["Si", "Si"], [[0, 0, 0.1], [0, 0, 0.2]]) s2 = Structure(l, ["Si", "Si"], [[0, 0.1, 0], [0, 0.1, -0.95]]) s1, s2, fu, s1_supercell = sm._preprocess(s1, s2, False) match = sm._strict_match(s1, s2, fu, s1_supercell=False, use_rms=True, break_on_match=False) scale_matrix = match[2] s2.make_supercell(scale_matrix) s2.translate_sites(range(len(s2)), match[3]) self.assertAlmostEqual(np.sum(s2.frac_coords), 0.3) self.assertAlmostEqual(np.sum(s2.frac_coords[:, :2]), 0)
def test_find_match1(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=True, scale=True, attempt_supercell=False) l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ["Si", "Si", "Ag"], [[0, 0, 0.1], [0, 0, 0.2], [0.7, 0.4, 0.5]]) s2 = Structure(l, ["Si", "Si", "Ag"], [[0, 0.1, 0], [0, 0.1, -0.95], [0.7, 0.5, 0.375]]) s1, s2, fu, s1_supercell = sm._preprocess(s1, s2, False) match = sm._strict_match(s1, s2, fu, s1_supercell=True, use_rms=True, break_on_match=False) scale_matrix = match[2] s2.make_supercell(scale_matrix) fc = s2.frac_coords + match[3] fc -= np.round(fc) self.assertAlmostEqual(np.sum(fc), 0.9) self.assertAlmostEqual(np.sum(fc[:, :2]), 0.1) cart_dist = np.sum(match[1] * (l.volume / 3) ** (1 / 3)) self.assertAlmostEqual(cart_dist, 0.15)
def test_find_match2(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=True, scale=True, attempt_supercell=False) l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ['Si', 'Si'], [[0,0,0.1],[0,0,0.2]]) s2 = Structure(l, ['Si', 'Si'], [[0,0.1,0],[0,0.1,-0.95]]) match = sm._find_match(s1, s2, break_on_match = False, use_rms = True, niggli = False) scale_matrix = np.round(np.dot(match[2].matrix, s2.lattice.inv_matrix)).astype('int') s2.make_supercell(scale_matrix) fc = s2.frac_coords + match[3] fc -= np.round(fc) self.assertAlmostEqual(np.sum(fc), 0.3) self.assertAlmostEqual(np.sum(fc[:,:2]), 0)
def test_find_match2(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=True, scale=True, attempt_supercell=False) l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ['Si', 'Si'], [[0,0,0.1],[0,0,0.2]]) s2 = Structure(l, ['Si', 'Si'], [[0,0.1,0],[0,0.1,-0.95]]) match = sm._find_match(s1, s2, break_on_match = False, use_rms = True, niggli = False) scale_matrix = np.round(np.dot(match[2].matrix, s2.lattice.inv_matrix)).astype('int') s2.make_supercell(scale_matrix) fc = s2.frac_coords + match[3] fc -= np.round(fc) self.assertAlmostEqual(np.sum(fc), 0.3) self.assertAlmostEqual(np.sum(fc[:,:2]), 0)
def test_get_s2_like_s1(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=True, attempt_supercell=True) l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ['Si', 'Si', 'Ag'], [[0,0,0.1],[0,0,0.2],[.7,.4,.5]]) s1.make_supercell([2,1,1]) s2 = Structure(l, ['Si', 'Si', 'Ag'], [[0,0.1,0],[0,0.1,-0.95],[-.7,.5,.375]]) result = sm.get_s2_like_s1(s1, s2) self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords, [0.35,0.4,0.5])), 1) self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords, [0,0,0.125])), 1) self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords, [0,0,0.175])), 1)
def test_get_s2_like_s1(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=True, attempt_supercell=True) l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ['Si', 'Si', 'Ag'], [[0,0,0.1],[0,0,0.2],[.7,.4,.5]]) s1.make_supercell([2,1,1]) s2 = Structure(l, ['Si', 'Si', 'Ag'], [[0,0.1,0],[0,0.1,-0.95],[-.7,.5,.375]]) result = sm.get_s2_like_s1(s1, s2) self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords, [0.35,0.4,0.5])), 1) self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords, [0,0,0.125])), 1) self.assertEqual(len(find_in_coord_list_pbc(result.frac_coords, [0,0,0.175])), 1)
def test_get_s2_large_s2(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=False, attempt_supercell=True, allow_subset=False, supercell_size='volume') l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ['Ag', 'Si', 'Si'], [[.7,.4,.5],[0,0,0.1],[0,0,0.2]]) l2 = Lattice.orthorhombic(1.01, 2.01, 3.01) s2 = Structure(l2, ['Si', 'Si', 'Ag'], [[0,0.1,-0.95],[0,0.1,0],[-.7,.5,.375]]) s2.make_supercell([[0,-1,0],[1,0,0],[0,0,1]]) result = sm.get_s2_like_s1(s1, s2) for x,y in zip(s1, result): self.assertLess(x.distance(y), 0.08)
def test_get_s2_large_s2(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=False, attempt_supercell=True, allow_subset=False, supercell_size='volume') l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ['Ag', 'Si', 'Si'], [[.7,.4,.5],[0,0,0.1],[0,0,0.2]]) l2 = Lattice.orthorhombic(1.01, 2.01, 3.01) s2 = Structure(l2, ['Si', 'Si', 'Ag'], [[0,0.1,-0.95],[0,0.1,0],[-.7,.5,.375]]) s2.make_supercell([[0,-1,0],[1,0,0],[0,0,1]]) result = sm.get_s2_like_s1(s1, s2) for x,y in zip(s1, result): self.assertLess(x.distance(y), 0.08)
def run_optimize(file_primitive, file_dfset, scaling_matrix): qeobj = QEParser() qeobj.load_initial_structure(file_primitive) structure = Structure(qeobj.lattice_vector.transpose(), qeobj.kd_in_str, qeobj.x_fractional) Structure.make_supercell(structure, scaling_matrix) print("Supercell generated. # Atoms: %i" % structure.num_sites) print("") prefix0 = 'supercell' # Generate displacement files gen_alm_input('ALM1.in', prefix0, 'optimize', structure, 1, "*-* None", dfset=file_dfset) command = ("%s/alm/alm ALM1.in > ALM1.log" % ALAMODE_root) os.system(command)
def run_displacement(file_primitive, prefix, scaling_matrix, disp_magnitude_angstrom): qeobj = QEParser() qeobj.load_initial_structure(file_primitive) structure = Structure(qeobj.lattice_vector.transpose(), qeobj.kd_in_str, qeobj.x_fractional) Structure.make_supercell(structure, scaling_matrix) print("Supercell generated. # Atoms: %i" % structure.num_sites) print("") prefix0 = 'supercell' disp = np.zeros((structure.num_sites, 3)) # update structural information of qeobj qeobj_mod = update_qeobj(qeobj, structure) # create the supercell structure qeobj_mod.generate_structures(prefix0, ['original'], [disp]) # rename the file command = ("mv %s1.pw.in %s0.scf.in" % (prefix0, prefix0)) os.system(command) # Generate displacement files gen_alm_input('ALM0.in', prefix0, 'suggest', structure, 1, "*-* None") command = ("%s/alm/alm ALM0.in > ALM0.log" % ALAMODE_root) os.system(command) dispobj = AlamodeDisplace("fd", qeobj_mod, verbosity=0) header_list, disp_list \ = dispobj.generate(file_pattern=["%s.pattern_HARMONIC" % prefix0], magnitude=disp_magnitude_angstrom) qeobj_mod.generate_structures(prefix, header_list, disp_list)
def test_supercell_subsets(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=True, attempt_supercell=True, allow_subset=True, supercell_size='volume') sm_no_s = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=True, attempt_supercell=True, allow_subset=False, supercell_size='volume') l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ['Ag', 'Si', 'Si'], [[.7,.4,.5],[0,0,0.1],[0,0,0.2]]) s1.make_supercell([2,1,1]) s2 = Structure(l, ['Si', 'Si', 'Ag'], [[0,0.1,-0.95],[0,0.1,0],[-.7,.5,.375]]) shuffle = [0,2,1,3,4,5] s1 = Structure.from_sites([s1[i] for i in shuffle]) #test when s1 is exact supercell of s2 result = sm.get_s2_like_s1(s1, s2) for a, b in zip(s1, result): self.assertTrue(a.distance(b) < 0.08) self.assertEqual(a.species_and_occu, b.species_and_occu) self.assertTrue(sm.fit(s1, s2)) self.assertTrue(sm.fit(s2, s1)) self.assertTrue(sm_no_s.fit(s1, s2)) self.assertTrue(sm_no_s.fit(s2, s1)) rms = (0.048604032430991401, 0.059527539448807391) self.assertTrue(np.allclose(sm.get_rms_dist(s1, s2), rms)) self.assertTrue(np.allclose(sm.get_rms_dist(s2, s1), rms)) #test when the supercell is a subset of s2 subset_supercell = s1.copy() del subset_supercell[0] result = sm.get_s2_like_s1(subset_supercell, s2) self.assertEqual(len(result), 6) for a, b in zip(subset_supercell, result): self.assertTrue(a.distance(b) < 0.08) self.assertEqual(a.species_and_occu, b.species_and_occu) self.assertTrue(sm.fit(subset_supercell, s2)) self.assertTrue(sm.fit(s2, subset_supercell)) self.assertFalse(sm_no_s.fit(subset_supercell, s2)) self.assertFalse(sm_no_s.fit(s2, subset_supercell)) rms = (0.053243049896333279, 0.059527539448807336) self.assertTrue(np.allclose(sm.get_rms_dist(subset_supercell, s2), rms)) self.assertTrue(np.allclose(sm.get_rms_dist(s2, subset_supercell), rms)) #test when s2 (once made a supercell) is a subset of s1 s2_missing_site = s2.copy() del s2_missing_site[1] result = sm.get_s2_like_s1(s1, s2_missing_site) for a, b in zip((s1[i] for i in (0, 2, 4, 5)), result): self.assertTrue(a.distance(b) < 0.08) self.assertEqual(a.species_and_occu, b.species_and_occu) self.assertTrue(sm.fit(s1, s2_missing_site)) self.assertTrue(sm.fit(s2_missing_site, s1)) self.assertFalse(sm_no_s.fit(s1, s2_missing_site)) self.assertFalse(sm_no_s.fit(s2_missing_site, s1)) rms = (0.029763769724403633, 0.029763769724403987) self.assertTrue(np.allclose(sm.get_rms_dist(s1, s2_missing_site), rms)) self.assertTrue(np.allclose(sm.get_rms_dist(s2_missing_site, s1), rms))
def tblg_nm(n=9, m=8): import numpy as np from pymatgen.core import Structure """Get the pymatgen structure of the twisted bilayer graphene for given n and m. angle is given by arccos[ 0.5*(n**2+4*n*m+m**2) / (n**2+n*m+m**2) ] Args: n (int, optional): sc 1 m (int, optional): sc 2 Returns: TYPE: pymatgen structure object """ def R(t): # Rotation matrix c, s = np.cos(t), np.sin(t) R = np.array(((c, -s), (s, c))) R = np.vstack([R, [0, 0]]) R = np.hstack([R, [[0], [0], [1]]]) return R t = np.arccos(0.5 * (n**2 + 4 * n * m + m**2) / (n**2 + n * m + m**2)) lattice_lower = [ 3 * R(t / 2) @ i for i in np.array([[1.0, 0.0, 0], [0.5, np.sqrt(3.0) / 2.0, 0], [0, 0, 10]]) ] # lower lattice lattice_upper = [ 3 * R(-t / 2) @ i for i in np.array([[1.0, 0.0, 0], [0.5, np.sqrt(3.0) / 2.0, 0], [0, 0, 10]]) ] # top lattice lower = Structure(lattice=lattice_lower, species=["C", "C"], coords=[[1. / 3., 1. / 3., 0.5], [2. / 3., 2. / 3., 0.5]]) upper = Structure(lattice=lattice_upper, species=["C", "C"], coords=[[1. / 3., 1. / 3., 0.5], [2. / 3., 2. / 3., 0.5]]) sc = np.eye(3) sc[0][0] = n sc[0][1] = m sc[1][0] = -m sc[1][1] = n + m # supercell transfornation matrix for lower system lower.make_supercell(sc) sc = np.eye(3) sc[0][0] = m sc[0][1] = n sc[1][0] = -n sc[1][1] = m + n # supercell transfornation matrix for upper system upper.make_supercell(sc) d = 1 # distance between layers pos = [] for i in upper: pos.append(i.coords + [0, 0, d]) for i in lower: pos.append(i.coords + [0, 0, -d]) species = ["C"] * len(pos) tblg = Structure(lattice=upper.lattice, coords=pos, species=species, coords_are_cartesian=True) print("angle of twist = {}".format( np.rad2deg( np.arccos(0.5 * (n**2 + 4 * n * m + m**2) / (n**2 + n * m + m**2))))) return tblg # return the twisted bilayer structure
def test_supercell_subsets(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=True, attempt_supercell=True, allow_subset=True, supercell_size='volume') sm_no_s = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=True, attempt_supercell=True, allow_subset=False, supercell_size='volume') l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ['Ag', 'Si', 'Si'], [[.7, .4, .5], [0, 0, 0.1], [0, 0, 0.2]]) s1.make_supercell([2, 1, 1]) s2 = Structure(l, ['Si', 'Si', 'Ag'], [[0, 0.1, -0.95], [0, 0.1, 0], [-.7, .5, .375]]) shuffle = [0, 2, 1, 3, 4, 5] s1 = Structure.from_sites([s1[i] for i in shuffle]) #test when s1 is exact supercell of s2 result = sm.get_s2_like_s1(s1, s2) for a, b in zip(s1, result): self.assertTrue(a.distance(b) < 0.08) self.assertEqual(a.species_and_occu, b.species_and_occu) self.assertTrue(sm.fit(s1, s2)) self.assertTrue(sm.fit(s2, s1)) self.assertTrue(sm_no_s.fit(s1, s2)) self.assertTrue(sm_no_s.fit(s2, s1)) rms = (0.048604032430991401, 0.059527539448807391) self.assertTrue(np.allclose(sm.get_rms_dist(s1, s2), rms)) self.assertTrue(np.allclose(sm.get_rms_dist(s2, s1), rms)) #test when the supercell is a subset of s2 subset_supercell = s1.copy() del subset_supercell[0] result = sm.get_s2_like_s1(subset_supercell, s2) self.assertEqual(len(result), 6) for a, b in zip(subset_supercell, result): self.assertTrue(a.distance(b) < 0.08) self.assertEqual(a.species_and_occu, b.species_and_occu) self.assertTrue(sm.fit(subset_supercell, s2)) self.assertTrue(sm.fit(s2, subset_supercell)) self.assertFalse(sm_no_s.fit(subset_supercell, s2)) self.assertFalse(sm_no_s.fit(s2, subset_supercell)) rms = (0.053243049896333279, 0.059527539448807336) self.assertTrue(np.allclose(sm.get_rms_dist(subset_supercell, s2), rms)) self.assertTrue(np.allclose(sm.get_rms_dist(s2, subset_supercell), rms)) #test when s2 (once made a supercell) is a subset of s1 s2_missing_site = s2.copy() del s2_missing_site[1] result = sm.get_s2_like_s1(s1, s2_missing_site) for a, b in zip((s1[i] for i in (0, 2, 4, 5)), result): self.assertTrue(a.distance(b) < 0.08) self.assertEqual(a.species_and_occu, b.species_and_occu) self.assertTrue(sm.fit(s1, s2_missing_site)) self.assertTrue(sm.fit(s2_missing_site, s1)) self.assertFalse(sm_no_s.fit(s1, s2_missing_site)) self.assertFalse(sm_no_s.fit(s2_missing_site, s1)) rms = (0.029763769724403633, 0.029763769724403987) self.assertTrue(np.allclose(sm.get_rms_dist(s1, s2_missing_site), rms)) self.assertTrue(np.allclose(sm.get_rms_dist(s2_missing_site, s1), rms))