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 get_min_distance(self, connected_nodes, loc): str_formula = str(self.structure.species_and_occu[loc].formula) nodes = np.array([node for node in connected_nodes \ if self.structure.species_and_occu[node] == self.structure.species_and_occu[loc]]) #get nearest magnetic_metal angle neighbors with a tolerance of 0.1 A. lattice_species = [ self.structure.species_and_occu[node] for node in nodes ] s = Structure(self.structure.lattice, lattice_species, self.frac_coords[nodes]) s.make_supercell([3, 3, 3]) new_frac_coords = np.round(s.frac_coords, decimals=3) new_frac_coords[new_frac_coords == 1.] = 0. distances = [] for i in range(len(new_frac_coords)): distances.append( np.linalg.norm( s.lattice.get_cartesian_coords(new_frac_coords[i]) - s.lattice.get_cartesian_coords([0.5, 0.5, 0.5]))) new_loc = np.argmin(distances) loc_cart_coords = s.lattice.get_cartesian_coords( new_frac_coords[new_loc]) #identify the two closest same species to the specie under consideration (new_loc) nodes = np.arange(len(s)) distances = [s.distance_matrix[node, new_loc] for node in nodes] nodes = nodes[np.argsort(distances)] distances = np.sort(distances) return distances[1]
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 to_xyz(self): u = Universe('reduced.xyz') name = [] for a in u.atoms: name.append(a.name) a = [ float(r) for r in '8.0136733451350004 2.7785351250530002 0.0000007466930000'. split() ] b = [ float(r) for r in '-1.6027324335730000 8.3356053751600001 0.0000022400790000'. split() ] c = [ float(r) for r in '0.0000000000000000 0.0000000000000000 25.3395087497430005'. split() ] lat = Lattice([a, b, c]) s = Structure(lat, name, u.trajectory[0], coords_are_cartesian=True) s.make_supercell([2, 2, 1]) print(s)
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_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 create_TiAlN_structure(shuffle=True): ''' Attributes: number_of_lattice > maximum Total number of atoms in structure a > lattice parameter Returns: Pymatgen structure TiAlN. Creates possible largest square supercell ''' lattice = Lattice.cubic(a=4.16) coords = [ [0, 0, 0], [0.5, 0.5, 0], [0.5, 0, 0.5], [0, 0.5, 0.5], [0, 0, 0.5], [0.5, 0, 0], [0, 0.5, 0], [0.5, 0.5, 0.5], ] matrix = [[1, 0, 0], [0, 5, 0], [0, 0, 5]] struct = Structure(lattice, ["Ti", "Ti", "Al", "Al", "N", "N", "N", "N"], coords) struct.make_supercell(matrix) site_size = len(struct) element_number = int(site_size / 4) Al_Ti_array = ['Al'] * element_number + ['Ti'] * element_number if shuffle == True: random.shuffle(Al_Ti_array) for e, i in enumerate(Al_Ti_array): struct.replace(e, i) return struct
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, s2[i].species) del s1[0] # s1 is subset of s2 for i, x in enumerate(sm.get_mapping(s2, s1)): self.assertEqual(s1[i].species, s2[x].species) # s2 is smaller than s1 del s2[0] del s2[1] self.assertRaises(ValueError, sm.get_mapping, s2, s1)
def test_apply_transformation_mult(self): # Test returning multiple structures from each transformation. disord = Structure(np.eye(3) * 4.209, [{"Cs+": 0.5, "K+": 0.5}, "Cl-"], [[0, 0, 0], [0.5, 0.5, 0.5]]) disord.make_supercell([2, 2, 1]) tl = [EnumerateStructureTransformation(), OrderDisorderedStructureTransformation()] t = SuperTransformation(tl, nstructures_per_trans=10) self.assertEqual(len(t.apply_transformation(disord, return_ranked_list=20)), 8) t = SuperTransformation(tl) self.assertEqual(len(t.apply_transformation(disord, return_ranked_list=20)), 2)
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) % 1, 0.3) self.assertAlmostEqual(np.sum(s2.frac_coords[:, :2]) % 1, 0)
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_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 getFccEquilibrium(): # alat = 1.0 alat = math.sqrt(2.0) fcc = Structure( Lattice.cubic(alat), ["Co", "Co", "Co", "Co"], [[0.0, 0.0, 0.0], [0.0, 0.5, 0.5], [0.5, 0.0, 0.5], [0.5, 0.5, 0.0]]) # fcc = Structure( Lattice.cubic(alat), ["Co"], # [[0.0, 0.0, 0.0]] # ) # Find the primitive unit cell: from pymatgen.symmetry.analyzer import SpacegroupAnalyzer sym_finder = SpacegroupAnalyzer(fcc) fcc = sym_finder.get_primitive_standard_structure() # new_structure.to(fmt='poscar', filename='POSCAR_test_2') # Make a supercell n = 3 #3 fcc.make_supercell([n, n, n]) return fcc
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 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 get_elem_info( structure: mg.Structure, makesupercell: bool = True) -> Tuple[Dict, Dict, mg.Structure]: """ Helper function for calc_mx/mm/xx_distances() Get information on the element composition and the site indices for all element of a structure :param structure: Pymatgen Structure, the structure of a compound :param makesupercell: Boolean, whether or not to make a supercell :return: Tuple, (a dictionary with key-value pair - element: [list of indices], a dictionary with key-value pair - element_type: [list of elements], Pymatgen Structure) """ # create a copy of the original structure structure = structure.copy() # create a list with all the elements elem_lst = structure.composition.element_composition.elements # initialize a dictionary with each element as the key and an empty list as the value elem_indices = {element: [] for element in elem_lst} # classify all elements into a metal group and a non-metal group elem_group = parse_element(structure) # iterate over all sites for i, site in enumerate(structure.sites): # record the site index for the all the element(s) on this site for element in site.species.element_composition.elements: elem_indices[element].append(i) # in the case that an element only appears in one site, make a supercell (inplace) if makesupercell and (np.sum( [len(lst) == 1 for lst in elem_indices.values()]) > 0): # make a supercell of a'=2a, b'=b, c'=c structure.make_supercell(scaling_matrix=[2, 1, 1]) elem_indices, elem_group, structure = get_elem_info(structure) return elem_indices, elem_group, structure
class Test2D(unittest.TestCase): def setUp(self): ## simple toy structure for preliminary testing self.a0 = 3.0 self.c = 20.0 self.structure = Structure( Lattice.from_parameters(a=self.a0, b=self.a0, c=self.c, alpha=90, beta=90, gamma=90), ["O", "O"], [[0.0, 0.0, 0.1], [0.5, 0.5, 0.3]]) self.nvecs = [3, 3, 1] self.vacuum = 20 self.q = 0 self.structure.make_supercell(self.nvecs) self.structure_bulk = self.structure.copy() self.initdef_list = [] self.initdef_list.append( {"def1": { "type": "vac", "species": "O", "index": 0 }}) self.initdef_list.append({ "def1": { "type": "sub", "index": -1, "species": "O", "species_new": "N" } }) self.initdef_list.append({ "def1": { "type": "sub", "index": -1, "species": "O", "species_new": "N" }, "def2": { "type": "vac", "index": -1, "species": "O", "index_offset_n1n2": -1 } }) self.initdef_list.append({ "def1": { "type": "ad", "index": [-1], "species": ["O"], "species_new": "N", "shift_z": "3.0" } }) self.initdef_list.append({ "def1": { "type": "int", "index": [0, 0, 0, 0], "index_offset_n1": [0, 1, 0, 0], "index_offset_n2": [0, 0, 0, 2], "index_offset_n1n2": [0, 0, 1, 1], "species": 4 * ["O"], "species_new": "N" } }) self.create_defects() self.siteinds_list = [[0], [17], [17, 8], [[17]], [[0, 3, 9, 11]]] self.defcoords_list = [[[0.0, 0.0, 0.1]], [[0.833333, 0.833333, 0.3]], [[0.833333, 0.833333, 0.3], [0.666667, 0.666667, 0.1]], [[0.833333, 0.833333, 0.45]], [[0.166667, 0.0, 0.2]]] self.natoms_list = [17, 18, 17, 19, 19] def create_defects(self): ## create defects self.defects_list = [] for initdef in self.initdef_list: ## initialize defect object defect = gen_defect_supercells.Defect(self.structure_bulk, self.structure.copy(), self.nvecs, self.vacuum, self.q) ## set the defect info (type, site, species) for each defect for d in initdef: initdef[d]["index_offset_n1"] = initdef[d].get( "index_offset_n1", 0) initdef[d]["index_offset_n2"] = initdef[d].get( "index_offset_n2", 0) initdef[d]["index_offset_n1n2"] = initdef[d].get( "index_offset_n1n2", 0) defect_site, siteinds = defect.get_defect_site(initdef[d]) defect.add_defect_info(initdef[d], defect_site) ## create defect(s) defect.remove_atom() defect.replace_atom() defect.add_atom() self.defects_list.append(defect) def test_get_site_index(self): ## test get_site_index returns the correct absolute site indices ## initialize dummy "defect" object defect = gen_defect_supercells.Defect(self.structure_bulk, self.structure.copy(), self.nvecs, self.vacuum, self.q) for initdef, siteinds in zip(self.initdef_list, self.siteinds_list): for d, siteind_ref in zip(initdef, siteinds): if initdef[d]["type"][0] == "v" or initdef[d]["type"][0] == "s": siteind = defect.get_site_ind( initdef[d]["index"], initdef[d]["species"], initdef[d]["index_offset_n1"], initdef[d]["index_offset_n2"], initdef[d]["index_offset_n1n2"]) self.assertEqual(siteind, siteind_ref) if initdef[d]["type"][0] == "a" or initdef[d]["type"][0] == "i": for siteindi_ref,ind,sp,offset_n1,offset_n2,offset_n1n2 \ in zip(siteind_ref, initdef[d]["index"], initdef[d]["species"], initdef[d]["index_offset_n1"], initdef[d]["index_offset_n2"], initdef[d]["index_offset_n1n2"]): siteind = defect.get_site_ind(ind, sp, offset_n1, offset_n2, offset_n1n2) self.assertEqual(siteind, siteindi_ref) def test_defcoords(self): ## test that the defect(s) are created at the correct position ## essentially tests the get_defect_site function for defects, defcoords_ref in zip(self.defects_list, self.defcoords_list): for defect_site, defcoord_ref in zip(defects.defect_site, defcoords_ref): defcoord = defect_site.lattice.get_fractional_coords( defect_site.coords) # defcoord = defect_site.frac_coords for j in range(3): self.assertAlmostEqual(defcoord[j] % 1 % 1, defcoord_ref[j] % 1 % 1, places=6) def test_natoms(self): ## test that the defect creation results in the correct number of atoms for defect, natoms in zip(self.defects_list, self.natoms_list): self.assertEqual(defect.structure.num_sites, natoms)
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))
#%% import math from pymatgen import Structure, Molecule, Lattice import os os.chdir( '/home/jinho93/oxides/perobskite/lanthanum-aluminate/slab/gulp/nonstochio/La-vac/two' ) m = Molecule.from_file('tail.xyz') l = Lattice.from_lengths_and_angles([11.46615, 15.2882, 50], [90, 90, 90]) s = Structure(l, m.species, m.cart_coords, coords_are_cartesian=True) s.make_supercell([[4, 0, 0], [0, 3, 0], [0, 0, 1]]) s.make_supercell([[1, 1, 0], [1, -1, 0], [0, 0, 1]]) s.sort() # ll = Lattice.from_lengths_and_angles([s.lattice.a / 2, s.lattice.b / 2, s.lattice.c], s.lattice.angles) ll = Lattice.from_lengths_and_angles(s.lattice.abc, s.lattice.angles) s = Structure(ll, s.species, s.cart_coords, coords_are_cartesian=True) indi = [] for i, site in enumerate(s.sites): if site.x + site.y < ll.b / math.sqrt(2): indi.append(i) # s.remove_sites(indi) # s = Structure(ll, s.species, s.cart_coords, coords_are_cartesian=True) # s.to('POSCAR', 'POSCAR')
def angle_calculation(self, connected_nodes, loc): angle = [] nn_coords = [] str_formula = str(self.structure.species_and_occu[loc].formula) nodes = np.array([node for node in connected_nodes \ if self.structure.species_and_occu[node] == self.structure.species_and_occu[loc]]) #get nearest magnetic_metal angle neighbors with a tolerance of 0.1 A. lattice_species = [ self.structure.species_and_occu[node] for node in nodes ] s = Structure(self.structure.lattice, lattice_species, self.frac_coords[nodes]) s.make_supercell([3, 3, 3]) new_frac_coords = np.round(s.frac_coords, decimals=3) new_frac_coords[new_frac_coords == 1.] = 0. distances = [] for i in range(len(new_frac_coords)): distances.append( np.linalg.norm( s.lattice.get_cartesian_coords(new_frac_coords[i]) - s.lattice.get_cartesian_coords([0.5, 0.5, 0.5]))) new_loc = np.argmin(distances) loc_cart_coords = s.lattice.get_cartesian_coords( new_frac_coords[new_loc]) #identify the two closest same species to the specie under consideration (new_loc) nodes = np.arange(len(s)) distances = [s.distance_matrix[node, new_loc] for node in nodes] nodes = nodes[np.argsort(distances)] distances = np.sort(distances) #identify other potential second closest atoms. Useful if there are multiple such atoms. min_dist_node1 = nodes[1] try: #for 1D compounds. Not applicable now. min_dist_node2 = nodes[2] except IndexError: angle = '180.0' nn_coords = [ s.lattice.get_cartesian_coords(new_frac_coords[nodes[1]]) - loc_cart_coords ] return angle, nn_coords nnn_list = [ nodes[i] for i in range(2, len(nodes)) if distances[i] < distances[2] + 0.1 ] #get the image of the neighbors if they are closer than the one inside the cell nnn_coords = [] for node in nnn_list: nnn_coords.append( s.lattice.get_cartesian_coords(new_frac_coords[node])) #get the angles between the atoms and take the non-zero minimum value. angles = [] v1 = s.lattice.get_cartesian_coords( new_frac_coords[min_dist_node1]) - loc_cart_coords for coords in nnn_coords: v2 = coords - loc_cart_coords cos_theta = np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2)) if np.round(cos_theta, decimals=1) == -1.0: angles.append(180.0) else: angles.append(np.arccos(cos_theta) * 180 / np.pi) try: angle.append(min(i for i in angles if i > 0.1)) except ValueError: angle.append(0.0) angle = str(np.round(min(angle), decimals=2)) nn_list = [ nodes[i] for i in range(1, len(nodes)) if distances[i] <= distances[1] + 0.1 ] for node in nn_list: nn_coords.append( s.lattice.get_cartesian_coords(new_frac_coords[node])) nn_coords = [coord - loc_cart_coords for coord in nn_coords] return angle, nn_coords
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, b.species) 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, b.species) 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, b.species) 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))
class Test2D_WSe2(Test2D): def setUp(self): ## hexagonal WSe2 unitcell self.a0 = 3.287596 self.c = 23.360843 self.structure = Structure( Lattice.from_parameters(a=self.a0, b=self.a0, c=self.c, alpha=90, beta=90, gamma=120), ["W", "Se", "Se"], [[0.0, 0.0, 0.5], [0.333333, 0.666667, 0.571091], [0.333333, 0.666667, 0.428909]]) self.nvecs = [4, 4, 1] self.vacuum = 20 self.q = 0 self.structure.make_supercell(self.nvecs) self.structure_bulk = self.structure.copy() self.initdef_list = [] self.initdef_list.append( {"def1": { "type": "vac", "species": "Se", "index": 0 }}) self.initdef_list.append({ "def1": { "type": "sub", "index": -1, "species": "W", "species_new": "Re" } }) self.initdef_list.append({ "def1": { "type": "sub", "index": -1, "species": "W", "species_new": "Re" }, "def2": { "type": "vac", "index": -1, "species": "Se", "index_offset_n1n2": -1 } }) self.initdef_list.append({ "def1": { "type": "ad-W", "index": [-1], "species": ["W"], "species_new": "Re", "shift_z": "3.36" } }) self.initdef_list.append({ "def1": { "type": "int-hex", "index": [0, 1, 0], "index_offset_n1": [1, 1, 0], "species": 3 * ["W"], "species_new": "Re" } }) self.create_defects() self.siteinds_list = [[16], [15], [15, 31], [[15]], [[4, 5, 0]]] self.defcoords_list = [[[0.083333, 0.166667, 0.571091]], [[0.75, 0.75, 0.5]], [[0.75, 0.75, 0.5], [0.833333, 0.916667, 0.571091]], [[0.75, 0.75, 0.643830]], [[0.166667, 0.083333, 0.5]]] self.natoms_list = [47, 48, 47, 49, 49]