def test_big(self): # Number of atoms in each direction. n_atom = 4 structure = Cell() structure.set_basis(lengths=[2 * n_atom, 2 * n_atom, 2 * n_atom], angles=[90, 90, 90]) # Add a bunch of atoms. step_size = 1.0 / n_atom for x in range(n_atom): for y in range(n_atom): for z in range(n_atom): new_pos = np.array([x, y, z], dtype=float) + \ np.random.random(3) / n_atom new_pos *= step_size structure.add_atom(Atom(new_pos, 0)) # Compute the cells. cells = VoronoiTessellationCalculator.compute(structure, radical=True) total_vol = 0.0 for cell in cells: total_vol += cell.get_volume() self.assertTrue(cell.geometry_is_valid()) vol_error = (total_vol - structure.volume()) / structure.volume() self.assertAlmostEqual(0.0, vol_error, delta=1e-2)
def test_conversion(self): # Make an FCC cell. cell = Cell() cell.set_basis(lengths=[3.5, 3.6, 3.4], angles=[89, 90, 91]) cell.add_atom(Atom([0, 0, 0], 0)) cell.add_atom(Atom([0.5, 0.5, 0], 1)) cell.add_atom(Atom([0.5, 0, 0.5], 1)) cell.add_atom(Atom([0, 0.5, 0.5], 1)) cell.set_type_name(0, "Al") cell.set_type_name(1, "Ni") # Convert it to string. vio = VASP5IO() temp = vio.convert_structure_to_string(cell) # Convert it back. new_cell = vio.parse_file(list_of_lines=temp) # Check to make sure everything is good. self.assertAlmostEqual(cell.volume(), new_cell.volume(), delta=1e-4) self.assertEqual(cell.n_types(), new_cell.n_types()) np_tst.assert_array_almost_equal(cell.get_lattice_vectors()[1], new_cell.get_lattice_vectors()[1], decimal=4) new_temp = vio.convert_structure_to_string(new_cell) np_tst.assert_equal(temp, new_temp)
def test_matrix(self): # Make a simple structure. structure = Cell() structure.add_atom(Atom([0, 0, 0], 0)) structure.set_type_name(0, "Al") # Compute the sine matrix. mat = self.r.compute_coulomb_matrix(structure) self.assertEqual(1, mat.shape[0]) self.assertEqual(1, mat.shape[1]) self.assertAlmostEqual(0.5 * 13 ** 2.4, mat[0, 0],delta=1e-6) # Add another atom and repeat. structure.add_atom(Atom([0.5, 0.5, 0.5], 0)) mat = self.r.compute_coulomb_matrix(structure) self.assertEqual(2, mat.shape[0]) self.assertEqual(2, mat.shape[1]) # Test: Is it insensitive to basis changes. new_basis = structure.get_basis() new_basis[1, 0] = 12 structure.set_basis(basis=new_basis) self.assertAlmostEqual(1.0, structure.volume(), delta=1e-6) mat2 = self.r.compute_coulomb_matrix(structure) if np.linalg.norm(mat - mat2) > 1e-6: sys.stderr.write("WARNING: Not insensitive to basis changes\n")
def test_random_packing(self): # Number of atoms in each direction. n_atom = 4 structure = Cell() structure.set_basis(lengths=[2 * n_atom, 2 * n_atom, 2 * n_atom], angles=[90, 90, 90]) # Add a bunch of atoms. for x in range(n_atom): for y in range(n_atom): for z in range(n_atom): structure.add_atom(Atom(np.random.random(3), 0)) # Compute the cells. cells = VoronoiTessellationCalculator.compute(structure, radical=True) total_vol = 0.0 for cell in cells: total_vol += cell.get_volume() self.assertTrue(cell.geometry_is_valid()) vol_error = (total_vol - structure.volume()) / structure.volume() self.assertAlmostEqual(0.0, vol_error, delta=1e-2)
class testCell(unittest.TestCase): cell = None # Create one instance per test. def setUp(self): self.cell = Cell() # Destroy instance as soon as test is over. def tearDown(self): self.cell = None def test_set_basis(self): # Test using angles and lattice parameters as input. self.cell.set_basis(lengths=[5.643, 6.621,4.885], angles=[91.83, 93.58, 107.69]) self.assertAlmostEqual(173.30, self.cell.volume(), delta=1e-2) np_tst.assert_array_almost_equal([5.643, 6.621,4.885], self.cell.get_lattice_parameters()) np_tst.assert_array_almost_equal([91.83, 93.58, 107.69], self.cell.get_lattice_angles_radians(radians=False)) # Simple test with a primitive cell. basis = np.zeros((3, 3)) basis[0] = np.array([0, 2.986, 2.986]) basis[1] = np.array([2.986, 0, 2.986]) basis[2] = np.array([2.986, 2.986, 0]) self.cell.set_basis(basis=basis) self.assertAlmostEqual(13.312*4, self.cell.volume(), delta=1e-3) np_tst.assert_array_almost_equal([4.223, 4.223, 4.223], self.cell.get_lattice_parameters(), decimal=3) np_tst.assert_array_almost_equal([60, 60, 60], self.cell.get_lattice_angles_radians(radians=False)) def test_aligned_basis(self): # Simple test with a primitive cell. basis = np.zeros((3, 3)) basis[0] = np.array([0, 2.986, 2.986]) basis[1] = np.array([2.986, 0, 2.986]) basis[2] = np.array([2.986, 2.986, 0]) self.cell.set_basis(basis=basis) # Compute the aligned basis. aligned_basis = self.cell.get_aligned_basis() self.assertAlmostEqual(0, aligned_basis[1][0], delta=1e-6) self.assertAlmostEqual(0, aligned_basis[2][0], delta=1e-6) self.assertAlmostEqual(0, aligned_basis[2][1], delta=1e-6) def test_clone(self): self.cell.add_atom(Atom([0, 0, 0], 0)) self.cell.set_type_name(0, "A") # Test adding atoms. clone = self.cell.__copy__() self.assertEqual(clone, self.cell) clone.add_atom(Atom([0, 0.5, 0], 0)) self.assertFalse(clone.__eq__(self.cell)) # Test changing atom. clone = self.cell.__copy__() clone.get_atom(0).set_type(1) self.assertFalse(clone.__eq__(self.cell)) # Test changing basis. clone = self.cell.__copy__() clone.set_basis(lengths=[2, 1, 1], angles=[90, 90, 90]) self.assertFalse(clone.__eq__(self.cell)) def test_lattice_vectors(self): self.cell.set_basis(lengths=[1, 2, 3], angles=[80, 90, 70]) l_vec = self.cell.get_lattice_vectors() np_tst.assert_array_almost_equal([[1.0, 0.0, 0.0], [0.684, 1.879, 0.0], [0.0, 0.554, 2.948]], l_vec, decimal=3) # FCC primitive cell. self.cell.set_basis(lengths=[0.70710678118655, 0.70710678118655, 0.70710678118655], angles=[60, 60, 60]) self.assertAlmostEqual(0.25, self.cell.volume(), delta=1e-6) l_vec = self.cell.get_lattice_vectors() self.assertAlmostEqual(0.70710678118655, norm(l_vec[0]), delta=1e-2) def test_fractional_to_cartesian(self): self.cell.set_basis(lengths=[1, 2, 3], angles=[80, 90, 70]) np_tst.assert_array_almost_equal([0.2368, 0.5421, 0.8844], self.cell.convert_fractional_to_cartesian([0.1, 0.2, 0.3]), decimal=3) def test_cartesian_to_fractional(self): self.cell.set_basis(lengths=[1, 2, 3], angles=[80, 90, 70]) np_tst.assert_array_almost_equal([0.1, 0.2, 0.3], self.cell.convert_cartesian_to_fractional([0.2368, 0.5421, 0.8844]), decimal=3) def test_supercell_translation(self): self.cell.set_basis(lengths=[0.70710678118655, 0.70710678118655, 0.70710678118655], angles=[60, 60, 60]) self.assertAlmostEqual(0.25, self.cell.volume(), delta=1e-6) l_vec = self.cell.get_lattice_vectors() # Check a few. pos = self.cell.get_periodic_image([0, 0, 0], 1, 0, 0) np_tst.assert_array_almost_equal([0.70710678000000, 0, 0], pos, decimal=3) pos = self.cell.get_periodic_image([0, 0, 0], 1, 1, 0) np_tst.assert_array_almost_equal([1.06066017000000, 0.61237243466821, 0], pos, decimal=3) pos = self.cell.get_periodic_image([0, 0, 0], 1, 1, 1) np_tst.assert_array_almost_equal([1.41421356000000, 0.81649657955762, 0.57735026918963], pos, decimal=3) def test_equals(self): # Make other cell other = Cell() # First check. self.assertTrue(self.cell.__eq__(other)) # Adjust basis. self.cell.set_basis(lengths=[1, 2, 3], angles=[70, 80, 90]) self.assertFalse(self.cell.__eq__(other)) other.set_basis(lengths=[1, 2, 3], angles=[70, 80, 90]) self.assertTrue(self.cell.__eq__(other)) # Add an atom to 0,0,0 self.cell.add_atom(Atom([0, 0, 0], 0)) self.assertFalse(self.cell.__eq__(other)) other.add_atom(Atom([0, 0, 0], 0)) self.assertTrue(self.cell.__eq__(other)) # Changing names. self.cell.set_type_name(0, "Al") self.assertFalse(self.cell.__eq__(other)) other.set_type_name(0, "Al") self.assertTrue(self.cell.__eq__(other)) # Adding more atoms of different type. self.cell.add_atom(Atom([0.5, 0.5, 0], 1)) other.add_atom(Atom([0.5, 0.5, 0], 0)) self.assertFalse(self.cell.__eq__(other)) other.get_atom(1).set_type(1) self.assertTrue(self.cell.__eq__(other)) # Adding atoms with different positions. self.cell.add_atom(Atom([0.5, 0, 0.5], 1)) other.add_atom(Atom([0, 0.5, 0.5], 1)) self.assertFalse(self.cell.__eq__(other)) # Adding atoms out of sequence. other.add_atom(Atom([0.5, 0, 0.5], 1)) self.cell.add_atom(Atom([0, 0.5, 0.5], 1)) self.assertTrue(self.cell.__eq__(other)) def test_minimum_distance(self): # Simple case: orthogonal axes. # Origin. self.cell.add_atom(Atom([0, 0, 0], 1)) # C face center. self.cell.add_atom(Atom([0.5, 0.5, 0], 1)) dist = self.cell.get_minimum_distance(point1=[0, 0, 0], point2=[0.5, 0.5, 0]) self.assertAlmostEqual(math.sqrt(0.5), dist, delta=1e-6) dist = self.cell.get_minimum_distance(point1=[0, 0, 0], point2=[2.5, 0.5, -10]) self.assertAlmostEqual(math.sqrt(0.5), dist, delta=1e-6) # Difficult case: Non-conventional unit cell. basis = self.cell.get_basis() basis[1][0] = 108 self.cell.set_basis(basis=basis) dist = self.cell.get_minimum_distance(point1=[0, 0, 0], point2=[0.5, 0.5, 0]) self.assertAlmostEqual(math.sqrt(0.5), dist, delta=1e-6) dist = self.cell.get_minimum_distance(point1=[0, 0, 0], point2=[5.5, 0.5, 0]) self.assertAlmostEqual(math.sqrt(0.5), dist, delta=1e-6) dist = self.cell.get_minimum_distance(point1=[0, 0, 0], point2=[5.5, -10.5, 0]) self.assertAlmostEqual(math.sqrt(0.5), dist, delta=1e-6) def test_get_closest_image_simple(self): # Simple case: orthogonal axes. # Origin. self.cell.add_atom(Atom([0, 0, 0], 1)) # C face center. self.cell.add_atom(Atom([0.75, 0.75, 0.75], 1)) image = self.cell.get_minimum_distance(center=0, neighbor=1) np_tst.assert_array_almost_equal([-0.25, -0.25, -0.25], image.get_position(), decimal=6) np_tst.assert_array_equal([-1, -1, -1], image.get_supercell()) def test_get_closest_image_difficult(self): # Difficult case: Non-conventional unit cell. # Origin. self.cell.add_atom(Atom([0, 0, 0], 1)) # Body face center. self.cell.add_atom(Atom([0.5, 0.5, 0.5], 1)) basis = self.cell.get_basis() basis[1][0] = 108 self.cell.set_basis(basis=basis) image = self.cell.get_minimum_distance(center=0, neighbor=1) np_tst.assert_array_almost_equal([-0.5, -0.5, 0.5], image.get_position(), decimal=6) np_tst.assert_array_equal([-1, 53, 0], image.get_supercell()) def test_replacement(self): # Make the original cell B2-CuZr self.cell.add_atom(Atom([0, 0, 0], 0)) self.cell.add_atom(Atom([0.5, 0.5, 0.5], 1)) self.cell.set_type_name(0, "Cu") self.cell.set_type_name(1, "Zr") # Replace Cu with Ni. to_change = {"Cu":"Ni"} self.cell.replace_type_names(to_change) self.assertEqual("Ni", self.cell.get_type_name(0)) self.assertEqual("Zr", self.cell.get_type_name(1)) # Replace Ni with Cu and Zr with Ti. to_change = {"Ni": "Cu", "Zr":"Ti"} self.cell.replace_type_names(to_change) self.assertEqual("Cu", self.cell.get_type_name(0)) self.assertEqual("Ti", self.cell.get_type_name(1)) # Exchange Cu and Ti. to_change = {"Ti": "Cu", "Cu": "Ti"} self.cell.replace_type_names(to_change) self.assertEqual("Ti", self.cell.get_type_name(0)) self.assertEqual("Cu", self.cell.get_type_name(1)) # Make everything Cu. to_change = {"Ti": "Cu"} self.cell.replace_type_names(to_change) self.assertEqual("Cu", self.cell.get_type_name(0)) self.assertEqual("Cu", self.cell.get_type_name(1)) # Make everything W. to_change = {"Cu":"W"} self.cell.replace_type_names(to_change) self.assertEqual("W", self.cell.get_type_name(0)) self.assertEqual("W", self.cell.get_type_name(1)) # Merge types. self.cell.merge_like_types() self.assertEqual(1, self.cell.n_types())
def test_simple_cubic(self): # Create the simulation cell. structure = Cell() atom = Atom([0, 0, 0], 0) structure.add_atom(atom) # Run tessellation. result = VoronoiTessellationCalculator.compute(structure, radical=False) # Test results. self.assertEqual(structure.n_atoms(), len(result)) self.assertEqual(6, len(result[0].get_faces())) self.assertAlmostEqual(structure.volume(), result[0].get_volume(), delta=1e-6) poly_index = result[0].get_polyhedron_shape() self.assertEqual(6, poly_index[4]) poly_index = result[0].get_coordination_shell_shape(result) self.assertEqual(6, poly_index[0]) # Test out the nearest neighbor shells. # 1st NN shell. nns = result[0].get_neighbor_shell(result, 1) self.assertEqual(6, len(nns)) # 2nd NN shell. nns = result[0].get_neighbor_shell(result, 2) self.assertEqual(18, len(nns)) # 3rd - 5th NN shell. for s in range(3, 6): nns = result[0].get_neighbor_shell(result, s) for image in nns: cell = image.get_supercell() self.assertAlmostEqual(s, sum([abs(cell[i]) for i in range( 3)]), delta=1e-6) # Test path NNs. # 0th NN. paths = result[0].get_neighbors_by_walks(result, 0) self.assertEqual(1, len(paths)) total_weight = sum(list(paths.values())) self.assertAlmostEqual(1.0, total_weight, delta=1e-6) # 1st NN. paths = result[0].get_neighbors_by_walks(result, 1) self.assertEqual(6, len(paths)) total_weight = sum(list(paths.values())) np_tst.assert_array_almost_equal([1/6.0]*6, list(paths.values())) self.assertAlmostEqual(1.0, total_weight, delta=1e-6) # 2nd NN. paths = result[0].get_neighbors_by_walks(result, 2) self.assertEqual(18, len(paths)) total_weight = sum(list(paths.values())) for (k,v) in iteritems(paths): if 2 in k.get_supercell() or -2 in k.get_supercell(): self.assertAlmostEqual(1 / 30.0, v, delta=1e-6) else: self.assertAlmostEqual(2 / 30.0, v, delta=1e-6) self.assertAlmostEqual(1.0, total_weight, delta=1e-6)