def get_fractional_positions_from_neighbor_list( structure: Structure, neighbor_list: List) -> List[Vector]: """ Returns the fractional positions of the lattice sites in structure from a neighbor list. Parameters ---------- structure input atomic structure neighbor_list list of lattice neighbors of the input structure """ neighbor_positions = [] fractional_positions = [] lattice_site = LatticeSite(0, [0, 0, 0]) for i in range(len(neighbor_list)): lattice_site.index = i position = structure.get_position(lattice_site) neighbor_positions.append(position) for neighbor in neighbor_list[i]: position = structure.get_position(neighbor) neighbor_positions.append(position) if len(neighbor_positions) > 0: fractional_positions = get_scaled_positions( np.array(neighbor_positions), structure.cell, wrap=False, pbc=structure.pbc) return fractional_positions
def test_add_operator(self): """Tests adding operator.""" lattice_site = LatticeSite(0, [0, 0, 0]) lattice_site2 = LatticeSite(0, [-1, -1, 3]) lattice_site.unitcell_offset = \ lattice_site.unitcell_offset + [-1, -1, 3] self.assertEqual(lattice_site, lattice_site2)
def test_count_list_lattice_sites(self): """ Tests whether cluster_counts returns the correct number of pairs given a list of lattice neighbors. """ lattice_sites = [] lattice_sites.append(LatticeSite(0, [0., 0., 0.])) lattice_sites.append(LatticeSite(1, [0., 0., 0.])) lattice_sites2 = [] lattice_sites2.append(LatticeSite(0, [0., 0., 0.])) lattice_sites2.append(LatticeSite(2, [0., 0., 0.])) # The tag is set to -1 in order not to collide with an existing # cluster-tag as the latter is used to generate a hash (and defaults to # 0, which is certainly already taken). cluster = Cluster(self.icet_structure, lattice_sites, tag=-1) lattice_neighbors = [lattice_sites, lattice_sites2] self.cluster_counts.count(self.icet_structure, lattice_neighbors, cluster, True) cluster_map = self.cluster_counts.get_cluster_counts() count = cluster_map[cluster] self.assertEqual(count, {('Ni', 'Fe'): 1, ('Ni', 'Ni'): 1})
def test_get_permuted_cluster_by_index(self): """Tests the get sites with permutation functionality.""" target = [LatticeSite(0, [0., 0., 0.]), LatticeSite(1, [0., 0., 0.])] self.orbit_pair.equivalent_clusters = self.lattice_sites_pairs self.orbit_pair.permutations_to_representative = [[ i for i in range(self.orbit_pair.order) ]] * len(self.orbit_pair) retval = self.orbit_pair.get_permuted_cluster_by_index(0) self.assertEqual(retval, target)
def test_eq(self): """Tests eq operator.""" index = 152453453 unitcell_offset = [-234234., 32423423., 235567567.] lattice_site = LatticeSite(index, unitcell_offset) lattice_site_other = LatticeSite(index, unitcell_offset) self.assertEqual(lattice_site, lattice_site_other) self.assertNotEqual(lattice_site, self.lattice_sites[0]) self.assertNotEqual(self.lattice_sites[1], self.lattice_sites[0])
def test_get_all_columns_from_sites(self): """Tests get_all_columns_from_sites functionality.""" # These sites are first and last elements in column1 sites = [LatticeSite(0, [0., 0., 0.]), LatticeSite(0, [1., 0., 0.])] pm = self.orbit_list.matrix_of_equivalent_positions columns = self.orbit_list._get_all_columns_from_sites(sites) for i in range(len(pm[0])): perm_sites = [pm[0][i], pm[-1][i]] translated_sites = \ self.orbit_list._get_sites_translated_to_unitcell(perm_sites, False) for k, sites in enumerate(translated_sites): self.assertEqual(columns[k + 2 * i], sites)
def test_find_lattice_site_by_position_simple(self): """ Tests finding lattice site by position, simple version using only one atom cell. 1. Create a bunch of lattice sites all with index 0 and integer unitcell offsets 2. convert these to x,y,z positions. Nothing strange so far 3. Find lattice site from the position and assert that it should be equivalent to the original lattice site. """ lattice_sites = [] noise_position = [] unit_cell_range = 1000 for j in range(5000): offset = [ random.randint(-unit_cell_range, unit_cell_range) for i in range(3) ] noise_position.append( [self.noise * random.uniform(-1, 1) for i in range(3)]) lattice_sites.append(LatticeSite(0, offset)) positions = [] for i, site in enumerate(lattice_sites): # Get position with a little noise pos = self.icet_structure.get_position(site) pos = pos + np.array(noise_position[i]) positions.append(pos) for site, pos in zip(lattice_sites, positions): found_site = self.icet_structure.find_lattice_site_by_position( pos, self.fractional_position_tolerance) self.assertEqual(site, found_site)
def test_singlets(self): """ Tests that every singlet lattice site is listed in the many-body neighbor list. """ for index in range(len(self.structure)): target = tuple(([LatticeSite(index, [0., 0., 0.])], [])) singlet = self.mbnl.build(self.neighbor_lists, index, False)[0] self.assertEqual(singlet, target)
def __init__(self, *args, **kwargs): super(TestOrbitList, self).__init__(*args, **kwargs) self.cutoffs = [4.2] self.symprec = 1e-5 self.position_tolerance = 1e-5 self.fractional_position_tolerance = 1e-6 self.structure = bulk('Ag', 'sc', a=4.09) # representative clusters for testing # for singlet self.cluster_singlet = Cluster( Structure.from_atoms(self.structure), [LatticeSite(0, [0, 0, 0])]) # for pair lattice_sites = [LatticeSite(0, [i, 0, 0]) for i in range(3)] self.cluster_pair = Cluster(Structure.from_atoms(self.structure), [lattice_sites[0], lattice_sites[1]], True)
def test_pairs(self): """ Tests that many-body_neighbor list includes all the pairs returned by neighbor_list for a specific lattice site. """ index = 0 nl_neighbors = self.neighbor_lists[0][0] target = tuple(([LatticeSite(index, [0., 0., 0.])], nl_neighbors)) pairs = self.mbnl.build(self.neighbor_lists, index, True)[1] self.assertEqual(pairs, target)
def __init__(self, *args, **kwargs): super(TestOrbit, self).__init__(*args, **kwargs) self.lattice_sites_pairs = [] indices = [i for i in range(8)] unitcell_offsets = [] cartesian_product_lists = [[0., 1.], [0., 1.], [0., 1.]] for element in itertools.product(*cartesian_product_lists): unitcell_offsets.append(list(element)) self.lattice_sites_pairs = [[ LatticeSite(index, unitcell_offset), LatticeSite(index + 1, unitcell_offset) ] for index, unitcell_offset in zip(indices, unitcell_offsets)] self.lattice_sites_triplets = [[ LatticeSite(index, unitcell_offset), LatticeSite(index + 1, unitcell_offset), LatticeSite(index + 3, unitcell_offset) ] for index, unitcell_offset in zip(indices, unitcell_offsets)]
def test_unique_primcell_offsets(self): """ Tests primitive offsets are unique and take to positions that match atoms positions in the supercell. """ unique_offsets = self.lolg._get_unique_primcell_offsets() super_pos = self.supercell.positions for k, offset in enumerate(unique_offsets): pos_prim = self.primitive.get_position(LatticeSite(0, offset)) self.assertTrue( np.any(np.isclose(pos_prim, pos) for pos in super_pos)) for i in range(k + 1, len(unique_offsets)): self.assertFalse(np.all(np.isclose(offset, unique_offsets[i])))
def generate_list_of_lattice_site(amount): """ Generates a list of lattice sites. amount : int size of list of lattice sites """ sites = [] indices = range(amount) offsets = [[x, y, z] for x, y, z in zip(range(amount), range(amount), range(amount))] for index, offset in zip(indices, offsets): sites.append(LatticeSite(index, offset)) return sites
def test_hash(self): """Tests that lattice site is hashable (check).""" index = 152453453 unitcell_offset = [-234234., 32423423., 235567567.] lattice_site = LatticeSite(index, unitcell_offset) lattice_site_other = LatticeSite(index, unitcell_offset) self.assertEqual(lattice_site.__hash__(), lattice_site_other.__hash__())
def setUp(self): """Instantiates class before each test.""" structure = Structure.from_atoms(bulk('Al')) lattice_site_for_cluster = [ LatticeSite(0, [i, 0, 0]) for i in range(3) ] self.pair_cluster = Cluster( structure, [lattice_site_for_cluster[0], lattice_site_for_cluster[1]], True) self.triplet_cluster = Cluster(structure, lattice_site_for_cluster, True) self.orbit_pair = Orbit(self.pair_cluster) self.orbit_triplet = Orbit(self.triplet_cluster)
def test_calculate_intersections(self): """Tests intersection between two list of neighbors.""" lattice_sites = [] lattice_sites.append(LatticeSite(0, [0, 0, 0])) lattice_sites.append(LatticeSite(0, [1, 0, 0])) lattice_sites.append(LatticeSite(1, [0, 0, 0])) lattice_sites.append(LatticeSite(3, [0, 0, 0])) lattice_sites2 = [] lattice_sites2.append(LatticeSite(0, [0, 0, 0])) lattice_sites2.append(LatticeSite(0, [1, 0, 0])) intersection = self.mbnl.calculate_intersection( lattice_sites, lattice_sites2) self.assertEqual( sorted(intersection), [LatticeSite(0, [0, 0, 0]), LatticeSite(0, [1, 0, 0])])
def test_higher_order_neighbors(self): """ Tests higher order neighbors in many-body neighbor list for a specific lattice site. """ index = 0 high_order_neighbors = \ self.mbnl.build(self.neighbor_lists, index, False)[2] target = ([LatticeSite(0, [0, 0, 0]), LatticeSite(0, [0, 0, 1])], [ LatticeSite(1, [0, 0, 0]), LatticeSite(3, [0, -1, 0]), LatticeSite(5, [-1, -1, 0]), LatticeSite(5, [-1, 0, 0]), LatticeSite(5, [0, 0, 0]), LatticeSite(7, [-1, -1, 0]) ]) self.assertEqual(target, high_order_neighbors)
def test_find_lattice_site_by_position_hard(self): """ Tests finding lattice site by position, hard version tests against hcp, many atoms in the basis AND pbc = [True, True, False] ! 1. Create a bunch of lattice sites all with index 0 and integer unitcell offsets 2. convert these to x,y,z positions. Nothing strange so far 3. Find lattice site from the position and assert that it should be equivalent to the original lattice site. """ ase_atoms = self.ase_atoms.repeat([3, 5, 5]) # Set pbc false in Z-direction and add vacuum ase_atoms.pbc = [True, True, False] ase_atoms.center(30, axis=[2]) icet_structure = Structure.from_atoms(ase_atoms) noise_position = [] lattice_sites = [] unit_cell_range = 100 for j in range(500): offset = [ random.randint(-unit_cell_range, unit_cell_range) for i in range(3) ] offset[2] = 0 index = random.randint(0, len(ase_atoms) - 1) noise_position.append( [self.noise * random.uniform(-1, 1) for i in range(3)]) lattice_sites.append(LatticeSite(index, offset)) positions = [] for i, site in enumerate(lattice_sites): pos = icet_structure.get_position(site) pos += np.array(noise_position[i]) positions.append(pos) for site, pos in zip(lattice_sites, positions): found_site = icet_structure.find_lattice_site_by_position( pos, self.fractional_position_tolerance) self.assertEqual(site, found_site)
def _from_python(ase_structure: Atoms, lattice_sites: List[LatticeSite], cluster_index: int = -1): """ Constructs a cluster from an ASE Atoms object and Python lattice sites. Parameters ---------- ase_structure structure as ASE Atoms object lattice_sites lattice site objects cluster_index index used to identify cluster """ structure = Structure.from_atoms(ase_structure) lattice_sites_cpp = [ LatticeSite(ls.index, ls.unitcell_offset) for ls in lattice_sites ] return Cluster(structure, lattice_sites_cpp, cluster_index)
def test_find_lattice_site_by_position_medium(self): """ Tests finding lattice site by position, medium version tests against hcp and user more than one atom in the basis 1. Create a bunch of lattice sites all with index 0 and integer unitcell offsets 2. convert these to x,y,z positions. Nothing strange so far 3. Find lattice site from the position and assert that it should be equivalent to the original lattice site. """ ase_atoms = self.ase_atoms.repeat([3, 2, 5]) icet_structure = Structure.from_atoms(ase_atoms) lattice_sites = [] unit_cell_range = 1000 noise_position = [] for j in range(5000): offset = [ random.randint(-unit_cell_range, unit_cell_range) for i in range(3) ] index = random.randint(0, len(ase_atoms) - 1) noise_position.append( [self.noise * random.uniform(-1, 1) for i in range(3)]) lattice_sites.append(LatticeSite(index, offset)) positions = [] for i, site in enumerate(lattice_sites): pos = icet_structure.get_position(site) pos = pos + np.array(noise_position[i]) positions.append(pos) for site, pos in zip(lattice_sites, positions): found_site = icet_structure.find_lattice_site_by_position( pos, self.fractional_position_tolerance) self.assertEqual(site, found_site)
def init_cpp_orbit(number_of_sites): """ Returns a pair and triplet C++ orbit with a size equal to number_of_sites. Parameters ---------- number_of_sites : int number of equivalent sites in the orbit """ indices = [i for i in range(number_of_sites)] unitcell_offsets = [] cartesian_product_lists = [[i for i in range(number_of_sites // 3)], [0, 2], [-number_of_sites, number_of_sites]] for element in itertools.product(*cartesian_product_lists): unitcell_offsets.append(list(element)) lattice_sites_pairs_cpp = [[ LatticeSite(index, unitcell_offset), LatticeSite(index + 1, unitcell_offset) ] for index, unitcell_offset in zip(indices, unitcell_offsets)] lattice_sites_triplets_cpp = [[ LatticeSite(index, unitcell_offset), LatticeSite(index + 1, unitcell_offset), LatticeSite(index + 3, unitcell_offset) ] for index, unitcell_offset in zip(indices, unitcell_offsets)] lattice_site_for_cluster = [LatticeSite(0, [i, 0, 0]) for i in range(3)] structure = bulk('Al') pair_cluster = Cluster.from_python( structure, [lattice_site_for_cluster[0], lattice_site_for_cluster[1]], True) triplet_cluster = Cluster.from_python(structure, lattice_site_for_cluster, True) orbit_pair_cpp = Orbit(pair_cluster) orbit_pair_cpp.equivalent_clusters = lattice_sites_pairs_cpp orbit_triplet_cpp = Orbit(triplet_cluster) orbit_triplet_cpp.equivalent_clusters = lattice_sites_triplets_cpp return orbit_pair_cpp, orbit_triplet_cpp
def test_get_position(self): """Tests get_position functionality.""" retval = self.icet_structure.get_position(LatticeSite(1, [0, 0, 0])) self.assertListEqual(retval.tolist(), self.positions[1])
def test_add_assigment_operator(self): """Tests adding and assignment operator.""" lattice_site = LatticeSite(0, [0, 0, 0]) lattice_site2 = LatticeSite(0, [-1, -1, 3]) lattice_site2.unitcell_offset += [1, 1, -3] self.assertEqual(lattice_site, lattice_site2)
def test_substraction_operator(self): """Tests substraction operator.""" lattice_site = LatticeSite(0, [-1, -1, 3]) lattice_site.unitcell_offset = \ lattice_site.unitcell_offset - [-1, -1, 3] self.assertEqual(lattice_site, LatticeSite(0, [0, 0, 0]))
def test_mbnl_non_pbc(self): """Tests many-body neighbor list for non-pbc structure.""" structure = self.structure.copy() structure.set_pbc([False]) neighbor_lists = get_neighbor_lists(Structure.from_atoms(structure), self.cutoffs, self.position_tolerance) mbnl = ManyBodyNeighborList() target = [([LatticeSite(0, [0, 0, 0])], []), ([LatticeSite(0, [0, 0, 0])], [ LatticeSite(1, [0, 0, 0]), LatticeSite(2, [0, 0, 0]), LatticeSite(4, [0, 0, 0]), LatticeSite(5, [0, 0, 0]), LatticeSite(6, [0, 0, 0]) ]), ([LatticeSite(0, [0, 0, 0]), LatticeSite(1, [0, 0, 0])], [ LatticeSite(2, [0, 0, 0]), LatticeSite(4, [0, 0, 0]), LatticeSite(5, [0, 0, 0]), LatticeSite(6, [0, 0, 0]) ]), ([LatticeSite(0, [0, 0, 0]), LatticeSite(2, [0, 0, 0])], [LatticeSite(6, [0, 0, 0])]), ([LatticeSite(0, [0, 0, 0]), LatticeSite(4, [0, 0, 0])], [LatticeSite(5, [0, 0, 0]), LatticeSite(6, [0, 0, 0])]), ([LatticeSite(0, [0, 0, 0]), LatticeSite(5, [0, 0, 0])], [LatticeSite(6, [0, 0, 0])])] neighbors_non_pbc = mbnl.build(neighbor_lists, 0, False) for k, latt_neighbors in enumerate(neighbors_non_pbc): self.assertEqual(target[k], latt_neighbors)
def setUp(self): """Setup before each test.""" self.lattice_sites = [] for index, unitcell_offset in zip(self.indices, self.unitcell_offsets): lattice_site = LatticeSite(index, unitcell_offset) self.lattice_sites.append(lattice_site)
def test_translate_sites_to_unitcell(self): """Tests the get all translated sites functionality.""" # no offset site shoud get itself as translated sites = [LatticeSite(0, [0, 0, 0])] target = [[LatticeSite(0, [0, 0, 0])]] self.assertListEqual( self.orbit_list._get_sites_translated_to_unitcell(sites, False), target) # test a singlet site with offset sites = [LatticeSite(3, [0, 0, -1])] target = [[LatticeSite(3, [0, 0, -1])], [LatticeSite(3, [0, 0, 0])]] self.assertListEqual( self.orbit_list._get_sites_translated_to_unitcell(sites, False), target) # sort output self.assertListEqual( self.orbit_list._get_sites_translated_to_unitcell(sites, True), sorted(target)) # Does it break when the offset is floats? sites = [LatticeSite(0, [0.0, 0.0, 0.0])] target = [[LatticeSite(0, [0.0, 0.0, 0.0])]] self.assertListEqual( self.orbit_list._get_sites_translated_to_unitcell(sites, False), target) # Test two sites with floats sites = [LatticeSite(0, [1.0, 0.0, 0.0]), LatticeSite(0, [0.0, 0.0, 0.0])] target = [[LatticeSite(0, [0.0, 0.0, 0.0]), LatticeSite(0, [-1., 0.0, 0.0])], sites] self.assertListEqual( self.orbit_list._get_sites_translated_to_unitcell(sites, False), target) # Test sites where none is inside unit cell sites = [LatticeSite(0, [1.0, 2.0, -1.0]), LatticeSite(2, [2.0, 0.0, 0.0])] target = [[LatticeSite(0, [-1.0, 2.0, -1.0]), LatticeSite(2, [0.0, 0.0, 0.0])], [LatticeSite(0, [0.0, 0.0, 0.0]), LatticeSite(2, [1.0, -2.0, 1.0])], sites] self.assertListEqual( self.orbit_list._get_sites_translated_to_unitcell(sites, False), target)