def test_get_interstitials_fcc(self): fcc = StructureFactory().ase.bulk('Al', cubic=True) a_0 = fcc.cell[0, 0] x_tetra_ref = 0.25 * a_0 * np.ones(3) * np.array( [[1], [-1]]) + fcc.positions[:, None, :] x_tetra_ref = fcc.get_wrapped_coordinates(x_tetra_ref).reshape(-1, 3) int_tetra = fcc.analyse.get_interstitials(num_neighbors=4) self.assertEqual(len(int_tetra.positions), len(x_tetra_ref)) self.assertAlmostEqual( np.linalg.norm(x_tetra_ref[:, None, :] - int_tetra.positions[None, :, :], axis=-1).min(axis=0).sum(), 0) x_octa_ref = 0.5 * a_0 * np.array([1, 0, 0]) + fcc.positions x_octa_ref = fcc.get_wrapped_coordinates(x_octa_ref) int_octa = fcc.analyse.get_interstitials(num_neighbors=6) self.assertEqual(len(int_octa.positions), len(x_octa_ref)) self.assertAlmostEqual( np.linalg.norm(x_octa_ref[:, None, :] - int_octa.positions[None, :, :], axis=-1).min(axis=0).sum(), 0) self.assertTrue( np.allclose(int_octa.get_areas(), a_0**2 * np.sqrt(3)), msg='Convex hull area comparison with analytical value failed') self.assertTrue( np.allclose(int_octa.get_volumes(), a_0**3 / 6), msg='Convex hull volume comparison with analytical value failed') self.assertTrue(np.allclose(int_octa.get_distances(), a_0 / 2), msg='Distance comparison with analytical value failed') self.assertTrue(np.all(int_octa.get_steinhardt_parameters(4) > 0), msg='Illegal Steinhardt parameter') self.assertAlmostEqual(int_octa.get_variances().sum(), 0, msg='Distance variance in FCC must be 0')
def test_generate_equivalent_points(self): a_0 = 4 structure = StructureFactory().ase.bulk('Al', cubic=True, a=a_0) self.assertEqual( len(structure), len(structure.get_symmetry().generate_equivalent_points([0, 0, 0.5 * a_0])) )
def test_numbers_of_neighbors(self): basis = StructureFactory().ase.bulk('Al', cubic=True).repeat(2) del basis[0] neigh = basis.get_neighbors(num_neighbors=None, cutoff_radius=0.45 * basis.cell[0, 0]) n, c = np.unique(neigh.numbers_of_neighbors, return_counts=True) self.assertEqual(n.tolist(), [11, 12]) self.assertEqual(c.tolist(), [12, 19])
def test_arg_equivalent_vectors(self): structure = StructureFactory().ase.bulk('Al', cubic=True).repeat(2) self.assertEqual(np.unique(structure.get_symmetry().arg_equivalent_vectors).squeeze(), 0) x_v = structure.positions[0] del structure[0] arg_v = structure.get_symmetry().arg_equivalent_vectors dx = structure.get_distances_array(structure.positions, x_v, vectors=True) dx_round = np.round(np.absolute(dx), decimals=3) self.assertEqual(len(np.unique(dx_round + arg_v)), len(np.unique(arg_v)))
def setUpClass(cls): cls.canonical = StructureStorage() cls.grandcanonical = StructureStorage() bulk = StructureFactory().bulk("Fe") for n in range(3): bulk.positions += np.random.normal(scale=.1, size=bulk.positions.shape) cls.canonical.add_structure(bulk) cls.grandcanonical.add_structure(bulk.repeat((n + 1, 1, 1)))
def test_centrosymmetry(self): structure = StructureFactory().ase_bulk('Fe').repeat(4) cs = structure.get_neighbors(num_neighbors=8).centrosymmetry self.assertAlmostEqual(cs.max(), 0) self.assertAlmostEqual(cs.min(), 0) structure.positions += 0.01 * ( 2 * np.random.random(structure.positions.shape) - 1) neigh = structure.get_neighbors(num_neighbors=8) self.assertGreater(neigh.centrosymmetry.min(), 0) self.assertTrue( np.allclose( neigh.centrosymmetry, structure.analyse.pyscal_centro_symmetry(num_neighbors=8)))
def test_permutations(self): structure = StructureFactory().ase.bulk('Al', cubic=True).repeat(2) x_vacancy = structure.positions[0] del structure[0] neigh = structure.get_neighborhood(x_vacancy) vec = np.zeros_like(structure.positions) vec[neigh.indices[0]] = neigh.vecs[0] sym = structure.get_symmetry() all_vectors = np.einsum('ijk,ink->inj', sym.rotations, vec[sym.permutations]) for i, v in zip(neigh.indices, neigh.vecs): vec = np.zeros_like(structure.positions) vec[i] = v self.assertAlmostEqual(np.linalg.norm(all_vectors - vec, axis=(-1, -2)).min(), 0,)
def test_get_distances_flattened(self): structure = StructureFactory().ase.bulk('Al', cubic=True).repeat(2) del structure[0] r = structure.cell[0, 0] * 0.49 neigh = structure.get_neighbors(cutoff_radius=r, num_neighbors=None, mode='flattened') self.assertAlmostEqual(np.std(neigh.distances), 0) self.assertEqual(len(neigh.distances), 360) self.assertEqual(neigh.vecs.shape, ( 360, 3, ))
def test_get_all_pairs(self): structure = StructureFactory().ase_bulk('Fe').repeat(4) neigh = structure.get_neighbors(num_neighbors=8) for n in [2, 4, 6]: pairs = neigh._get_all_possible_pairs(n) self.assertEqual( (np.prod(np.arange(int(n / 2)) * 2 + 1), int(n / 2), 2), pairs.shape) for i in range(2**(n - 2)): a = np.sort(np.random.choice(np.arange(n), 2, replace=False)) self.assertEqual(np.sum(np.all(a == pairs, axis=-1)), np.prod(np.arange(int((n - 1) / 2)) * 2 + 1)) self.assertEqual( np.ptp( np.unique(neigh._get_all_possible_pairs(6), return_counts=True)[1]), 0)
def test_get_shells_flattened(self): structure = StructureFactory().ase.bulk('Al', cubic=True).repeat(2) del structure[0] r = structure.cell[0, 0] * 0.49 neigh = structure.get_neighbors(cutoff_radius=r, num_neighbors=None, mode='flattened') self.assertEqual(len(np.unique(neigh.shells)), 1) self.assertEqual(len(neigh.shells), 360) self.assertEqual(len(np.unique(neigh.get_local_shells())), 1) self.assertEqual(len(neigh.get_local_shells()), 360) self.assertEqual(len(np.unique(neigh.get_global_shells())), 1) self.assertEqual(len(neigh.get_global_shells()), 360) neigh = structure.get_neighbors(cutoff_radius=r, num_neighbors=None) self.assertEqual(len(np.unique(neigh.flattened.shells)), 1) self.assertEqual(len(neigh.flattened.shells), 360)
def test_strain(self): bulk = StructureFactory().ase.bulk('Fe', cubic=True) a_0 = bulk.cell[0, 0] b = 0.5 * np.sqrt(3) * a_0 structure = ase_to_pyiron( BodyCenteredCubic(symbol='Fe', directions=[[-1, 0, 1], [1, -2, 1], [1, 1, 1]], latticeconstant=a_0)) L = 100 structure = structure.repeat( (*np.rint(L / structure.cell.diagonal()[:2]).astype(int), 1)) voro = Voronoi(structure.positions[:, :2]) center = voro.vertices[np.linalg.norm( voro.vertices - structure.cell.diagonal()[:2] * 0.5, axis=-1).argmin()] structure.positions[:, 2] += b / (2 * np.pi) * np.arctan2( *(structure.positions[:, :2] - center).T[::-1]) structure.center_coordinates_in_unit_cell() r_0 = 0.9 * L / 2 r = np.linalg.norm(structure.positions[:, :2] - center, axis=-1) core_region = (r < r_0) * (r > 10) strain = structure.analyse.get_strain(bulk, num_neighbors=8) strain = strain[core_region] positions = structure.positions[core_region, :2] x = positions - center eps_yz = b / (4 * np.pi) * x[:, 0] / np.linalg.norm(x, axis=-1)**2 eps_xz = -b / (4 * np.pi) * x[:, 1] / np.linalg.norm(x, axis=-1)**2 self.assertLess(np.absolute(eps_yz - strain[:, 1, 2]).max(), 0.01) self.assertLess(np.absolute(eps_xz - strain[:, 0, 2]).max(), 0.01)
def test_tessellations(self): bulk = StructureFactory().ase.bulk('Fe', cubic=True) a_0 = bulk.cell[0, 0] structure = bulk.repeat(3) self.assertAlmostEqual( np.linalg.norm(structure.find_mic( np.diff(structure.positions[ structure.analyse.get_delaunay_neighbors()], axis=-2)), axis=-1).flatten().max(), a_0) self.assertAlmostEqual( np.linalg.norm(structure.find_mic( np.diff(structure.positions[ structure.analyse.get_voronoi_neighbors()], axis=-2)), axis=-1).flatten().max(), a_0)
def test_get_interstitials_bcc(self): bcc = StructureFactory().ase.bulk('Fe', cubic=True) x_octa_ref = bcc.positions[:, None, :] + 0.5 * bcc.cell[None, :, :] x_octa_ref = x_octa_ref.reshape(-1, 3) x_octa_ref = bcc.get_wrapped_coordinates(x_octa_ref) int_octa = bcc.analyse.get_interstitials(num_neighbors=6) self.assertEqual(len(int_octa.positions), len(x_octa_ref)) self.assertAlmostEqual( np.linalg.norm(x_octa_ref[:, None, :] - int_octa.positions[None, :, :], axis=-1).min(axis=0).sum(), 0) int_tetra = bcc.analyse.get_interstitials(num_neighbors=4) x_tetra_ref = bcc.get_wrapped_coordinates( bcc.analyse.get_voronoi_vertices()) self.assertEqual(len(int_tetra.positions), len(x_tetra_ref)) self.assertAlmostEqual( np.linalg.norm(x_tetra_ref[:, None, :] - int_tetra.positions[None, :, :], axis=-1).min(axis=0).sum(), 0)
def test_cluster_positions(self): bulk = StructureFactory().ase.bulk('Fe', cubic=True) self.assertEqual(len(bulk.analyse.cluster_positions()), len(bulk)) positions = np.append(bulk.positions, bulk.positions, axis=0) self.assertEqual(len(bulk.analyse.cluster_positions(positions)), len(bulk)) self.assertEqual( bulk.analyse.cluster_positions(np.zeros((2, 3)), return_labels=True)[1].tolist(), [0, 0])
def test_C15(self): """ Tests based on Xie et al., JMR 2021 (DOI:10.1557/s43578-021-00237-y). """ a_type = 'Mg' b_type = 'Cu' structure = self.compound.C15(a_type, b_type) self.assertEqual(len(structure), 24, "Wrong number of atoms in C15 structure.") self.assertEqual(structure.get_chemical_formula(), "Cu16Mg8", "Wrong chemical formula.") a_type_nn_distance = StructureFactory().bulk(a_type).get_neighbors( num_neighbors=1).distances[0, 0] self.assertAlmostEqual( (4 / np.sqrt(3)) * a_type_nn_distance, structure.cell.array[0, 0], msg= "Default lattice constant should relate to NN distance of A-type element." ) unique_ids = np.unique(structure.get_symmetry()['equivalent_atoms']) self.assertEqual(2, len(unique_ids), msg="Expected only A- and B1-type sites.") symbols = structure.get_chemical_symbols() a_id = unique_ids[np.argwhere(symbols[unique_ids] == a_type)[0, 0]] b_id = unique_ids[np.argwhere(symbols[unique_ids] == b_type)[0, 0]] unique_ids = [a_id, b_id] # Now with guaranteed ordering csa = structure.analyse.pyscal_centro_symmetry()[unique_ids] self.assertLess( 1, csa[0], msg= "A site for AB_2 C15 should be significantly non-centro-symmetric." ) self.assertAlmostEqual( 0, csa[1], msg="B site for AB_2 C15 should be nearly centro-symmetric.") num_a_neighs = 16 num_b_neighs = 12 neigh = structure.get_neighbors(num_neighbors=num_a_neighs) a_neighs = neigh.indices[unique_ids[0]] b_neighs = neigh.indices[unique_ids[1], :num_b_neighs] symbols = structure.get_chemical_symbols() self.assertEqual(4, np.sum(symbols[a_neighs] == a_type)) self.assertEqual(12, np.sum(symbols[a_neighs] == b_type)) self.assertEqual(6, np.sum(symbols[b_neighs] == a_type)) self.assertEqual(6, np.sum(symbols[b_neighs] == b_type))
def test_high_index_surface(self): slab = StructureFactory().high_index_surface(element='Ni', crystal_structure='fcc', lattice_constant=3.526, terrace_orientation=[1, 1, 1], step_orientation=[1, 1, 0], kink_orientation=[1, 0, 1], step_down_vector=[1, 1, 0], length_step=2, length_terrace=3, length_kink=1, layers=60, vacuum=10) self.assertEqual(len(slab), 60)
def test_atom_numbers(self): structure = StructureFactory().ase.bulk('Al', cubic=True).repeat(2) del structure[0] r = structure.cell[0, 0] * 0.49 neigh = structure.get_neighbors(cutoff_radius=r, num_neighbors=None, mode='filled') n = len(structure) self.assertEqual(neigh.atom_numbers.sum(), int(n * (n - 1) / 2 * 12)) neigh = structure.get_neighbors(cutoff_radius=r, num_neighbors=None, mode='ragged') for i, (a, d) in enumerate(zip(neigh.atom_numbers, neigh.distances)): self.assertEqual(np.sum(a - len(d) * [i]), 0) neigh = structure.get_neighbors(cutoff_radius=r, num_neighbors=None, mode='flattened') labels, counts = np.unique(np.unique(neigh.atom_numbers, return_counts=True)[1], return_counts=True) self.assertEqual(labels.tolist(), [11, 12]) self.assertEqual(counts.tolist(), [12, 19])
def test_high_index_surface_info(self): h, s, k = StructureFactory().high_index_surface_info(element='Ni', crystal_structure='fcc', lattice_constant=3.526, terrace_orientation=[1, 1, 1], step_orientation=[1, 1, 0], kink_orientation=[1, 0, 1], step_down_vector=[1, 1, 0], length_step=2, length_terrace=3, length_kink=1) self.assertEqual(len(h), 3) self.assertEqual(h[0], -9) self.assertEqual(len(k), 3) self.assertEqual(len(s), 3) with self.assertRaises(ValueError): StructureFactory().high_index_surface_info(element='Ni', crystal_structure='fcc', lattice_constant=3.526, terrace_orientation=[1, 1, 1], step_orientation=[1, 0, 0], kink_orientation=[1, 0, 0], step_down_vector=[1, 1, 0], length_step=2, length_terrace=3, length_kink=1)
def test_chemical_symbols(self): basis = StructureFactory().ase_bulk('Fe', cubic=True) basis[0] = 'Ni' neigh = basis.get_neighbors(num_neighbors=1) self.assertEqual(neigh.chemical_symbols[0, 0], 'Fe') self.assertEqual(neigh.chemical_symbols[1, 0], 'Ni') vacancy = StructureFactory().ase_bulk('Fe', cubic=True).repeat(4) del vacancy[0] neigh = vacancy.get_neighbors(num_neighbors=None, cutoff_radius=3) self.assertEqual(neigh.chemical_symbols[0, -1], 'v')
def test_get_arg_equivalent_sites(self): a_0 = 4.0 structure = StructureFactory().ase.bulk('Al', cubic=True, a=a_0).repeat(2) sites = structure.get_wrapped_coordinates(structure.positions + np.array([0, 0, 0.5 * a_0])) v_position = structure.positions[0] del structure[0] pairs = np.stack(( structure.get_symmetry().get_arg_equivalent_sites(sites), np.unique(np.round(structure.get_distances_array(v_position, sites), decimals=2), return_inverse=True)[1] ), axis=-1) unique_pairs = np.unique(pairs, axis=0) self.assertEqual(len(unique_pairs), len(np.unique(unique_pairs[:, 0]))) with self.assertRaises(ValueError): structure.get_symmetry().get_arg_equivalent_sites([0, 0, 0])
def __init__(self, project: Project): super().__init__(project) self._structure = StructureFactory() self._job = JobFactory(project)
def setUpClass(cls): cls.execution_path = os.path.dirname(os.path.abspath(__file__)) cls.data_dict = dict() cls.data_dict["cubic"] = np.ones((100, 100, 100)) cls.data_dict["non_cubic"] = np.zeros((200, 50, 100)) cls.structure_factory = StructureFactory()
def test_steinhardt_parameters(self): neigh = StructureFactory().ase_bulk('Al').get_neighbors( num_neighbors=12) # values obtained with pyscal self.assertAlmostEqual(0, neigh.get_steinhardt_parameter(2)[0]) self.assertAlmostEqual(0.19094065395649323, neigh.get_steinhardt_parameter(4)[0]) self.assertAlmostEqual(0.5745242597140696, neigh.get_steinhardt_parameter(6)[0]) neigh = StructureFactory().ase_bulk('Mg', a=1, c=np.sqrt( 8 / 3)).get_neighbors(num_neighbors=12) self.assertAlmostEqual(0, neigh.get_steinhardt_parameter(2)[0]) self.assertAlmostEqual(0.097222222, neigh.get_steinhardt_parameter(4)[0]) self.assertAlmostEqual(0.484761685, neigh.get_steinhardt_parameter(6)[0]) neigh = StructureFactory().ase_bulk('Fe').get_neighbors( num_neighbors=14) self.assertAlmostEqual(0.03636964837266537, neigh.get_steinhardt_parameter(4)[0]) self.assertAlmostEqual(0.5106882308569508, neigh.get_steinhardt_parameter(6)[0]) self.assertRaises(ValueError, neigh.get_steinhardt_parameter, 2, 2)
def test_modes(self): basis = StructureFactory().ase.bulk('Al', cubic=True) neigh = basis.get_neighbors() self.assertTrue(neigh.mode == 'filled') with self.assertRaises(KeyError): neigh = basis.get_neighbors(mode='random_key')
def test_number_of_neighbors(self): self.assertEqual(self.strain.num_neighbors, 8) bulk = StructureFactory().ase.bulk('Al', cubic=True) strain = Strain(bulk, bulk) self.assertEqual(strain.num_neighbors, 12)
def setUpClass(cls): bulk = StructureFactory().ase.bulk('Fe', cubic=True) cls.strain = Strain(bulk, bulk)
def setUpClass(cls): cls.sf = StructureFactory() cls.compound = CompoundFactory()