def cons_max_volume(self, sites, max_volume, min_volume=1, dimension=3, symprec=1e-5): """ parameters: pcell: Cell object, The primitive cell to be extended sites: disorderd sites infomation. yield: Cell object, a list of non-redundant configurations to max volume supercells. """ # 该函数产生所有构型用于确定基态相图 for volume in range(min_volume, max_volume + 1): hnfs = non_dup_hnfs(self._pcell, volume, dimension, symprec) dict_trans = {} # 记录已经产生过的snf,相同snf的平移操作相同。 for h in hnfs: hfpg = PermutationGroup(self._pcell, h) # 此处的平移操作不必每次重新计算,因为相同snf平移操作相同 # 可以用字典来标记查询。若没有这样的操作,那么就没有snf带来的效率提升。 # quotient = hfpg.get_quotient() # if not quotient in dict_trans: # dict_trans[quotient] = hfpg.get_pure_translations(symprec) # trans = dict_trans[quotient] # rots = hfpg.get_pure_rotations(symprec) perms = hfpg.get_symmetry_perms(symprec) supercell = self._pcell.extend(h) _sites = numpy.repeat(sites, volume, axis=0) for mol, _ in remove_redundant(supercell.positions, _sites, perms): c = Cell(supercell.lattice, mol[0], mol[1]) if c.is_primitive(symprec): yield c
def test_check(self): lattice = numpy.array([0.0, 2.75, 2.75, 2.75, 0.0, 2.75, 2.75, 2.75, 0.0]) si_pos = [-0.125, -0.125, -0.125, 0.125, 0.125, 0.125] si_atoms = [14, 14] cell = Cell(lattice, si_pos, si_atoms) self.assertTrue(cell.check(limit=0.1)) si_pos = [-0.125, -0.125, -0.125, 0.125, 0.125, 0.125, 0.13, 0.125, 0.125] si_atoms = [14, 14, 8] cell = Cell(lattice, si_pos, si_atoms) self.assertFalse(cell.check(limit=0.1)) # 测试元素 self.assertTrue(cell.check(limit=0.1, elements=['O'])) lattice = numpy.array([1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]) si_pos = [-0.01, 0.0, 0.0, 0.01, 0.0, 0.0] si_atoms = [14, 14] # 两点之间的距离为0.02<0.05, 但在没有考虑边界条件时距离是0.98 cell = Cell(lattice, si_pos, si_atoms) self.assertFalse(cell.check(limit=0.05))
def test_get_primitive(self): fcc_latt = [5, 0, 0, 0, 5, 0, 0, 0, 5] fcc_pos = [(0, 0, 0), (0, 0.5, 0.5), (0.5, 0, 0.5), (0.5, 0.5, 0)] fcc_atoms = [0, 0, 0, 0] con_cell = Cell(fcc_latt, fcc_pos, fcc_atoms) pcell = con_cell.get_primitive_cell() self.assertEqual(pcell.atoms, [0])
def test_extend_not_hnf(self): fcc_latt = [0, 5, 5, 5, 0, 5, 5, 5, 0] fcc_pos = [(0, 0, 0), (0.5, 0.5, 0.5)] fcc_atoms = [1, 2] fcc_pcell = Cell(fcc_latt, fcc_pos, fcc_atoms) op_ext = numpy.array([-1, 1, 1, 1, -1, 1, 1, 1, -1]).reshape((3, 3)) ext_fcc = fcc_pcell.extend(op_ext) wanted_latt = numpy.array([10, 0, 0, 0, 10, 0, 0, 0, 10]).reshape((3, 3)) wanted_pos = numpy.array([(0, 0, 0), (0.5, 0.5, 0), (0.5, 0, 0.5), (0, 0.5, 0.5), (0.5, 0.5, 0.5), (0, 0, 0.5), (0, 0.5, 0), (0.5, 0, 0)]) wanted_atoms = numpy.array([1, 1, 1, 1, 2, 2, 2, 2]) numpy.testing.assert_almost_equal(ext_fcc.lattice, wanted_latt) numpy.testing.assert_almost_equal(ext_fcc.positions, wanted_pos) numpy.testing.assert_almost_equal(ext_fcc.atoms, wanted_atoms)
def test_extend_bug(self): sc_latt = [4, 0, 0, 0, 4, 0, 0, 0, 4] sc_pos = [(0, 0, 0)] sc_atoms = [1] sc_pcell = Cell(sc_latt, sc_pos, sc_atoms) op_ext = numpy.array([1, 0, 0, 0, 1, 0, 0, 0, 5]).reshape((3, 3)) ext_sc = sc_pcell.extend(op_ext) # raise ValueError pass
def test_is_primitive(self): bcc_latt = [0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5] bcc_pos = [(0, 0, 0)] bcc_atoms = [0] bcc_pcell = Cell(bcc_latt, bcc_pos, bcc_atoms) self.assertTrue(bcc_pcell.is_primitive())
def setUp(self): # BCC bcc_latt = [0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5] bcc_pos = [(0, 0, 0)] bcc_atoms = [0] self.bcc_pcell = Cell(bcc_latt, bcc_pos, bcc_atoms) # FCC fcc_latt = [0, 5, 5, 5, 0, 5, 5, 5, 0] fcc_pos = [(0, 0, 0)] fcc_atoms = [0] self.fcc_pcell = Cell(fcc_latt, fcc_pos, fcc_atoms)
def cons_specific_volume(self, sites, volume=2, e_num=None, dimension=3, symprec=1e-5): """ parameters: sites: 2D list, disorderd sites infomation. volume: int, certain volume with subperiodic. symprec: float, precision for symmetry find. yield: a tuple tuple[0]: Cell object, a list of non-redundant configurations of certain volume supercell. tuple[1]: int object, degeneracy of the configuration in all configurations of this volume. """ # 该函数产生特定体积下所有构型(包括超胞)和简并度,用于统计平均 hnfs = non_dup_hnfs(self._pcell, volume, dimension, symprec) dict_trans = {} for h in hnfs: hfpg = PermutationGroup(self._pcell, h) # 此处的平移操作不必每次重新计算,因为相同snf平移操作相同 # 可以用字典来标记查询。若没有这样的操作,那么就没有snf带来的效率提升。 # For hnf with same snf, translations are same. # quotient = hfpg.get_quotient() # if not quotient in dict_trans: # dict_trans[quotient] = hfpg.get_pure_translations(symprec) # trans = dict_trans[quotient] # rots = hfpg.get_pure_rotations(symprec) perms = hfpg.get_symmetry_perms(symprec) supercell = self._pcell.extend(h) _sites = numpy.repeat(sites, volume, axis=0) for mol, d in remove_redundant(supercell.positions, _sites, perms, e_num): c = Cell(supercell.lattice, mol[0], mol[1]) yield (c, d)
def test_Cart_string(self): data = '''C2 1.0 4.9208798409 0.0000000000 0.0000000000 -2.4604404879 4.2616066235 0.0000000000 0.0000000000 0.0000000000 10.0000000000 C 8 Cartesian 0.000000000 0.000000000 0.000000000 -1.230220199 2.130803347 0.000000000 2.460439920 0.000000000 0.000000000 1.230219722 2.130803347 0.000000000 1.230232477 0.710260868 0.000000000 0.000012159 2.841064692 0.000000000 3.690671921 0.710260868 0.000000000 2.460451603 2.841064692 0.000000000 ''' latt = [[4.9208798409, 0.0000000000, 0.0000000000], [-2.4604404879, 4.2616066235, 0.0000000000], [0.0000000000, 0.0000000000, 10.0000000000]] positions = [[0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [1.32703105e-08, 5.00000008e-01, 0.00000000e+00], [5.00000000e-01, 0.00000000e+00, 0.00000000e+00], [5.00000013e-01, 5.00000008e-01, 0.00000000e+00], [3.33335086e-01, 1.66665047e-01, 0.00000000e+00], [3.33335131e-01, 6.66665167e-01, 0.00000000e+00], [8.33334989e-01, 1.66665047e-01, 0.00000000e+00], [8.33335035e-01, 6.66665167e-01, 0.00000000e+00]] atoms = ['C' for i in range(8)] wanted = Cell(latt, positions, atoms) got = _read_string(data) self.assertLess(numpy.sum(abs(got.positions - wanted.positions)), 1e-4)
def setUp(self): lattice = numpy.array([7.1, 0, 0, 0, 7.1, 0, 0, 0, 7.1]).reshape( (3, 3)) positions = numpy.array([ 0.00, 0.00, 0.00, 0.00, 0.00, 0.50, 0.00, 0.50, 0.00, 0.00, 0.50, 0.50, 0.50, 0.00, 0.00, 0.50, 0.00, 0.50, 0.50, 0.50, 0.00, 0.50, 0.50, 0.50, 0.00, 0.25, 0.25, 0.00, 0.25, 0.75, 0.00, 0.75, 0.25, 0.00, 0.75, 0.75, 0.50, 0.25, 0.25, 0.50, 0.25, 0.75, 0.50, 0.75, 0.25, 0.50, 0.75, 0.75, 0.25, 0.00, 0.25, 0.25, 0.00, 0.75, 0.25, 0.50, 0.25, 0.25, 0.50, 0.75, 0.75, 0.00, 0.25, 0.75, 0.00, 0.75, 0.75, 0.50, 0.25, 0.75, 0.50, 0.75, 0.25, 0.25, 0.00, 0.25, 0.25, 0.50, 0.25, 0.75, 0.00, 0.25, 0.75, 0.50, 0.75, 0.25, 0.00, 0.75, 0.25, 0.50, 0.75, 0.75, 0.00, 0.75, 0.75, 0.50 ]) atoms = numpy.array([28] * 32) cell = Cell(lattice, positions, atoms) mcell = cell_to_mcell(cell) mcell.set_site(0, ([0, 0, 0], 'Co')) mcell.set_site(16, ([0.25, 0, 0.25], 'Co')) self.cell_nearest_1 = mcell.to_cell() mcell = cell_to_mcell(cell) mcell.set_site(0, ([0, 0, 0], 'Co')) mcell.set_site(21, ([0.75, 0, 0.75], 'Co')) self.cell_nearest_2 = mcell.to_cell() mcell = cell_to_mcell(cell) mcell.set_site(1, ([0, 0, 0.5], 'Co')) mcell.set_site(5, ([0.5, 0, 0.5], 'Co')) self.cell_far = mcell.to_cell()
def cons_specific_cell(self, sites, e_num=None, symprec=1e-5): """ cons_specific_cell_and_c generate configurations of specific cell and specific concentration. parameters: sites: list of (lists or tuples), represent element disorder of each sites e_num: tuple, number of atoms in disorderd sites. e_num 特指无序位点的浓度,也就是原子比,而不是整体构型的元素原子比。有可能其他位点存在相同构型。 !!限制,无序位点的组成必须是相同的,而上面几个函数的无序位点是可以不同的。!! """ lat_cell = self._cell.lattice lat_pcell = self._pcell.lattice mat = numpy.matmul(lat_cell, numpy.linalg.inv(lat_pcell)) if is_int_np_array(mat): mat = numpy.around(mat).astype('intc') else: print("cell:\n", lat_cell) print("primitive cell:\n", lat_pcell) raise ValueError( "cell lattice and its primitive cell lattice not convertable") hfpg = PermutationGroup(self._pcell, mat) perms = hfpg.get_symmetry_perms(symprec) supercell = self._pcell.extend(mat) for mol, d in remove_redundant(supercell.positions, sites, perms, e_num=e_num): c = Cell(supercell.lattice, mol[0], mol[1]) yield (c, d)
def get_max_volume(pcell, sites, max_volume, min_volume=1, dimension=3, symprec=1e-5): for volume in range(min_volume, max_volume + 1): hnfs = non_dup_hnfs(pcell, volume, dimension, symprec) dict_trans = {} # 记录已经产生过的snf,相同snf的平移操作相同。 for h in hnfs: hfpg = PG(pcell, h) perms = hfpg.get_symmetry_perms(symprec) if dimension == 2: supercell = pcell.extend(h)._get_niggli_2D() else: supercell = pcell.extend(h)._get_niggli_3D() _sites = np.repeat(sites, volume, axis=0) for mol, _ in remove_redundant(supercell.positions, _sites, perms): c = Cell(supercell.lattice, mol[0], mol[1]) if c.is_primitive(symprec): yield c
def setUp(self): fcc_latt = [0, 5, 5, 5, 0, 5, 5, 5, 0] fcc_pos = [(0, 0, 0), (0.5, 0.5, 0.5)] fcc_atoms = [1, 2] self.fcc_pcell = Cell(fcc_latt, fcc_pos, fcc_atoms)
def read(ase_atoms): if isinstance(ase_atoms, Atoms): lattice = ase_atoms.get_cell(complete=False) positions = ase_atoms.get_positions(wrap=False) atoms = ase_atoms.get_atomic_numbers() return Cell(lattice, positions, atoms) else: raise TypeError("The value is not an ase.Atoms object")
def setUp(self): lattice = numpy.array([5.5, 0, 0, 0, 5.5, 0, 0, 0, 5.5]).reshape( (3, 3)) positions = numpy.array([ 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 0.0, 0.5, 0.5, 0.5, 0.0, 0.5, 0.5, 0.5, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5 ]) atoms = numpy.array([11, 11, 11, 11, 17, 17, 17, 17]) self.cell = Cell(lattice, positions, atoms)
def test_cons_specific_cell_and_c(self): # FCC conventional cell fcc_latt = [5, 0, 0, 0, 5, 0, 0, 0, 5] fcc_pos = [(0, 0, 0), (0, 0.5, 0.5), (0.5, 0, 0.5), (0.5, 0.5, 0)] fcc_atoms = [0, 0, 0, 0] con_cell = Cell(fcc_latt, fcc_pos, fcc_atoms) cg = CG(con_cell) con = cg.cons_specific_cell( [(2, 3, 4), (2, 3, 4), (2, 3, 4), (2, 3, 4)], e_num=(2, 1, 1)) # number of all configurations wanted = 1 got = len([i for i in con]) self.assertEqual(got, wanted) # Zinc-blende conventional cell fcc_latt = [5, 0, 0, 0, 5, 0, 0, 0, 5] fcc_pos = [(0, 0, 0), (0, 0.5, 0.5), (0.5, 0, 0.5), (0.5, 0.5, 0), (0.25, 0.25, 0.25), (0.75, 0.75, 0.25), (0.75, 0.25, 0.75), (0.25, 0.75, 0.75)] fcc_atoms = [0, 0, 0, 0, 1, 1, 1, 1] con_cell = Cell(fcc_latt, fcc_pos, fcc_atoms) cg = CG(con_cell) con = cg.cons_specific_cell( [(2, 3, 4), (2, 3, 4), (2, 3, 4), (2, 3, 4), (1, ), (1, ), (1, ), (1,)], e_num=(2, 1, 1)) # number of all configurations wanted = 1 got = len([i for i in con]) self.assertEqual(got, wanted)
def setUp(self): lattice = [3.0, 0, 0, 0, 2.0, 0, 0, 0, 1.0] positions = [(0.00000, 0.00000, 0.00000), (0.00000, 0.50000, 0.00000), (0.33333, 0.00000, 0.00000), (0.33333, 0.50000, 0.00000), (0.66666, 0.00000, 0.00000), (0.66666, 0.50000, 0.00000), (0.16666, 0.25000, 0.50000), (0.16666, 0.75000, 0.50000), (0.50000, 0.25000, 0.50000), (0.50000, 0.75000, 0.50000), (0.83333, 0.25000, 0.50000), (0.83333, 0.75000, 0.50000)] atoms = ['C'] * 12 self.cell = Cell(lattice, positions, atoms)
def setUp(self): # BCC bcc_latt = [1, 1, -1, -1, 1, 1, 1, -1, 1] bcc_pos = [(0, 0, 0)] bcc_atoms = [0] self.bcc_pcell = Cell(bcc_latt, bcc_pos, bcc_atoms) # FCC fcc_latt = [0, 5, 5, 5, 0, 5, 5, 5, 0] fcc_pos = [(0, 0, 0)] fcc_atoms = [0] self.fcc_pcell = Cell(fcc_latt, fcc_pos, fcc_atoms) # HCP hcp_b = [ 2.51900005, 0., 0., -1.25950003, 2.18151804, 0., 0., 0., 4.09100008 ] hcp_positions = [(0.33333334, 0.66666669, 0.25), (0.66666663, 0.33333331, 0.75)] hcp_numbers = [0, 0] self.hcp_pcell = Cell(hcp_b, hcp_positions, hcp_numbers)
def test_cell_to_mcell(self): si_pos = [(-0.125, -0.125, -0.125), (0.125, 0.125, 0.125)] si_atoms = [14, 14] c = Cell(self.lattice, si_pos, si_atoms) mc = cell_to_mcell(c) self.assertTrue(isinstance(mc, MutableCell)) # 转换回去,并测试返回后的数据结构 c = mc.to_cell() numpy.testing.assert_almost_equal( c.positions, numpy.array([0.875, 0.875, 0.875, 0.125, 0.125, 0.125]).reshape( (2, 3))) numpy.testing.assert_almost_equal(c.atoms, numpy.array([14, 14]))
def setUp(self): self.string = '''H1 He1 1.000000 0.000000 0.500000 0.533333 0.500000 0.000000 0.566667 0.500000 0.500000 0.000000 H He 1 1 Direct 0.000000 0.000000 0.000000 H 0.250000 0.250000 0.250000 He ''' latt = [0., 0.5, 0.53333333333, 0.5, 0., 0.56666666667, 0.5, 0.5, 0.] positions = [0., 0., 0., 0.25, 0.25, 0.25] atoms = ['H', 'He'] self.cell = Cell(latt, positions, atoms)
def test_cons_specific_cell(self): fcc_latt = [5, 0, 0, 0, 5, 0, 0, 0, 5] fcc_pos = [(0, 0, 0), (0, 0.5, 0.5), (0.5, 0, 0.5), (0.5, 0.5, 0)] fcc_atoms = [0, 0, 0, 0] con_cell = Cell(fcc_latt, fcc_pos, fcc_atoms) cg = CG(con_cell) con = cg.cons_specific_cell([(2, 3), (2, 3), (2, 3), (2, 3)]) # number of all configurations wanted = 5 got = len([i for i in con]) self.assertEqual(got, wanted)
def test_from_cell(self): lattice = numpy.copy(self.lattice) positions = numpy.array([0.0, 0.0, 0.0, 0.25, 0.25, 0.25]).reshape((2, 3)) atoms = numpy.array([6, 6]) origin_lattice = numpy.copy(lattice) origin_positions = numpy.copy(positions) origin_atoms = numpy.copy(atoms) cell = Cell(lattice, positions, atoms) mcell = MutableCell.from_cell(cell) self.assertTrue(isinstance(mcell, MutableCell)) # Make sure mcell modified not change the cell mcell.remove_site(0) numpy.testing.assert_almost_equal(cell.lattice, origin_lattice) numpy.testing.assert_almost_equal(cell.positions, origin_positions) numpy.testing.assert_almost_equal(cell.atoms, origin_atoms)
def test_write_string_vacc(self): wanted = '''H1 1.000000 0.000000 0.500000 0.533333 0.500000 0.000000 0.566667 0.500000 0.500000 0.000000 H 1 Direct 0.000000 0.000000 0.000000 H ''' latt = [0., 0.5, 0.53333333333, 0.5, 0., 0.56666666667, 0.5, 0.5, 0.] positions = [0., 0., 0., 0.25, 0.25, 0.25] atoms = ['H', 'Vacc'] cell = Cell(latt, positions, atoms) got = _write_string(cell, long_format=False) self.assertEqual(got, wanted)
def get_tetrahedral_defect(self, isunique=False, doped_in='H', min_d=1.5, folder='tetrahedral-defect'): all_basis = generate_all_basis(1, 1, 1) direct_lattice = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) extend_S = np.zeros((0, 3)) for basis in all_basis: new_basis = np.sum([(direct_lattice[ii] * basis[ii]).tolist() for ii in range(3)], axis=0) extend_S = np.vstack( (extend_S, self.positions + np.tile(new_basis, len(self.atoms)).reshape( (-1, 3)))) idx = np.sum((extend_S <= 1.2) & (extend_S >= -0.2), axis=1) idx = np.where(idx == 3)[0] extend_S = np.dot(extend_S[idx], self.lattice) n = extend_S.shape[0] d = np.zeros((n, n)) for ii in range(n): d[ii, ii + 1:] = np.linalg.norm(extend_S[ii] - extend_S[ii + 1:], axis=1) d = d + d.T first_tetra, sec_tetra, third_tetra = [], [], [] for ii in range(n): temp_d = sorted(d[ii]) idx = np.where(abs(d[ii] - temp_d[1]) < min_d)[0] if len(idx) < 3: continue for comb in combinations(idx, 3): comb_list = list(comb) tmp = d[comb_list][:, comb_list] comb_list.append(ii) if np.std(tmp[tmp > 0]) < 0.01: if abs(tmp[0, 1] - temp_d[1]) < 0.1: first_tetra.append(comb_list) else: sec_tetra.append(comb_list) else: tmp = d[comb_list][:, comb_list] tmp = np.triu(tmp) tmp = sorted(tmp[tmp > 0]) if (np.std(tmp[0:4]) < 0.1 or np.std(tmp[1:5]) < 0.1 or np.std(tmp[2:]) < 0.1) and np.std(tmp) < 0.5: third_tetra.append(comb_list) all_tetra = [] if len(first_tetra) != 0: first_tetra = np.unique(np.sort(first_tetra, axis=1), axis=0) first_tetra = refine_points(first_tetra, extend_S, self.lattice, min_d=min_d) all_tetra.append(first_tetra) if len(sec_tetra) != 0: sec_tetra = np.unique(np.sort(sec_tetra, axis=1), axis=0) sec_tetra = refine_points(sec_tetra, extend_S, self.lattice, min_d=min_d) all_tetra.append(sec_tetra) if len(third_tetra) != 0: third_tetra = np.unique(np.sort(third_tetra, axis=1), axis=0) third_tetra = refine_points(third_tetra, extend_S, self.lattice, min_d=min_d) all_tetra.append(third_tetra) if isunique: if not os.path.exists(folder): os.mkdir(folder) else: rmtree(folder) os.mkdir(folder) idx = 0 # deg = [] for tetra in all_tetra: if len(tetra) == 0: continue new_pos = np.vstack((self.positions, tetra)) new_atoms = np.hstack((self.atoms, s2n(doped_in) * np.ones( (tetra.shape[0], )))) new_cell = Cell(self.lattice, new_pos, new_atoms) equi_atoms = new_cell.get_symmetry()['equivalent_atoms'] purity_atom_type = np.unique(equi_atoms[-tetra.shape[0]:]) for atom_type in purity_atom_type: new_uniq_pos = np.vstack( (self.positions, new_pos[atom_type])) new_uniq_atoms = np.hstack( (self.atoms, s2n(doped_in) * np.ones((1, )))) new_uniq_cell = Cell(self.lattice, new_uniq_pos, new_uniq_atoms) # deg.append(len(np.where(equi_atoms == atom_type)[0])) write_poscar(new_uniq_cell, folder, idx) idx += 1 # np.savetxt(folder+'/deg.txt',deg,fmt='%d') else: if not os.path.exists(folder): os.mkdir(folder) else: rmtree(folder) os.mkdir(folder) idx = 0 for tetra in all_tetra: if len(tetra) == 0: continue new_pos = np.vstack((self.positions, tetra)) new_atoms = np.hstack((self.atoms, s2n(doped_in) * np.ones( (tetra.shape[0], )))) new_cell = Cell(self.lattice, new_pos, new_atoms) write_poscar(new_cell, folder, idx) idx += 1
neig_list = np.zeros((n, 6)) for ii in range(pos.shape[0]): d = np.linalg.norm(pos[ii] - extend_pos, axis=1) idx = np.where(abs(d - d[np.argsort(d)[1]]) < 0.01)[0] neig_list[ii] = idx % n pos = np.dot(pos, np.linalg.inv(latt)) vac_str = [np.array([0])] for vac in range(2, 6): last_vac_str = vac_str[-1] tmp_vac_str = [] n_prev = last_vac_str.shape[0] for i in range(n_prev): each_str = last_vac_str[i] idx = np.setdiff1d(np.setdiff1d(range(n), each_str), neig_list[each_str][:]) for ii in idx: tmp_vac_str.append(get_min_serial(perms, np.hstack( (each_str, ii)))) vac_str.append(np.unique(tmp_vac_str, axis=0)) idx = 0 os.makedirs('vac-' + str(vac)) for _str in vac_str[-1]: _pos = pos[np.setdiff1d(range(n), _str), :] _latt, _atoms = latt, np.ones((n - vac, )) * 5 write_vasp(Cell(_latt, _pos, _atoms), 'vac-' + str(vac) + '/POSCAR' + str(idx)) idx += 1 print(vac_str[-1].shape)
class TestHnf(unittest.TestCase): def test(self): pass def setUp(self): # BCC bcc_latt = [1, 1, -1, -1, 1, 1, 1, -1, 1] bcc_pos = [(0, 0, 0)] bcc_atoms = [0] self.bcc_pcell = Cell(bcc_latt, bcc_pos, bcc_atoms) # FCC fcc_latt = [0, 5, 5, 5, 0, 5, 5, 5, 0] fcc_pos = [(0, 0, 0)] fcc_atoms = [0] self.fcc_pcell = Cell(fcc_latt, fcc_pos, fcc_atoms) # HCP hcp_b = [ 2.51900005, 0., 0., -1.25950003, 2.18151804, 0., 0., 0., 4.09100008 ] hcp_positions = [(0.33333334, 0.66666669, 0.25), (0.66666663, 0.33333331, 0.75)] hcp_numbers = [0, 0] self.hcp_pcell = Cell(hcp_b, hcp_positions, hcp_numbers) def test_hnf_cells(self): # Results from <PHYSICAL REVIEW B 80, 014120 (2009)> # BCC wanted = [1, 2, 3, 7, 5, 10, 7] got = [len(non_dup_hnfs(self.bcc_pcell, i)) for i in range(1, 8)] # for h in non_dup_hnfs(self.bcc_pcell, 7): # print(h) self.assertEqual(got, wanted) # FCC wanted = [1, 2, 3, 7, 5, 10, 7] got = [len(non_dup_hnfs(self.fcc_pcell, i)) for i in range(1, 8)] self.assertEqual(got, wanted) # HCP wanted = [1, 3, 5, 11, 7, 19, 11, 34] got = [len(non_dup_hnfs(self.hcp_pcell, i)) for i in range(1, 9)] self.assertEqual(got, wanted) def test_is_hnf_dup(self): hnf_x = numpy.array([[1, 0, 0], [0, 1, 0], [0, 0, 2]]) hnf_y = numpy.array([[1, 0, 0], [0, 2, 0], [0, 0, 1]]) rot_syms = self.bcc_pcell.get_rotations(1e-3) is_dup = _is_hnf_dup(hnf_x, hnf_y, rot_syms, prec=1e-3) self.assertTrue(is_dup) # debug for compare method # numpy.mod problem! hnf_x = numpy.array([[1, 0, 0], [0, 1, 2], [0, 0, 5]]) hnf_y = numpy.array([[1, 0, 3], [0, 1, 3], [0, 0, 5]]) rot_syms = self.bcc_pcell.get_rotations(1e-3) is_dup = _is_hnf_dup(hnf_x, hnf_y, rot_syms, prec=1e-5) self.assertTrue(is_dup) # debug for compare method # numpy.astype problem! hnf_x = numpy.array([[1, 0, 6], [0, 1, 6], [0, 0, 7]]) hnf_y = numpy.array([[1, 0, 3], [0, 1, 6], [0, 0, 7]]) rot_syms = self.bcc_pcell.get_rotations(1e-3) is_dup = _is_hnf_dup(hnf_x, hnf_y, rot_syms, prec=1e-5) self.assertTrue(is_dup)
def _read_string(data): """ _read_string make io easy to be tested. parameter: string of vasp input return: Cell object """ lines = [l for l in data.split('\n') if l.rstrip()] name = lines[0] lattice_scale = float(lines[1].split()[0]) # lattice vectors lattice = [] for i in [2, 3, 4]: s = lines[i].split() vec = float(s[0]), float(s[1]), float(s[2]) lattice.append(vec) lattice = numpy.array(lattice) if lattice_scale < 0: # In vasp , a negative scale factor is treated as a volume. # http://pymatgen.org/_modules/pymatgen/io/vasp/inputs.html#POSCAR vol = abs(numpy.linalg.det(lattice)) lattice *= (-lattice_scale / vol)**(1 / 3) else: lattice *= lattice_scale # atoms vasp5 = False _fifth_line = lines[5].split() # VASP 5.x use the fifth line to represent atomic symbols try: for i in _fifth_line: int(i) numofatoms = _fifth_line except ValueError: vasp5 = True atomtypes = _fifth_line numofatoms = lines[6].split() # list of string here if not vasp5: warnings.warn( "symbols of elements in fifth line are missing, " "all atoms are init to NaN_i (i=0,1,2...)", UserWarning, stacklevel=2) atomtypes = [str("NaN_{:}".format(i)) for i in range(len(numofatoms))] atoms = [] for i, num in enumerate(numofatoms): # https://gitlab.com/ase/ase/blob/master/ase/io/vasp.py numofatoms[i] = int(num) [atoms.append(atomtypes[i]) for na in range(numofatoms[i])] if not vasp5: line_coortype = 6 else: line_coortype = 7 # TODO: Supporting Cartesian coordinates vasp input coortype = lines[line_coortype].split()[0] if coortype[0] in "sS": warnings.warn("Sorry! Selective dynamics " "are not supported now", FutureWarning, stacklevel=2) line_coortype += 1 coortype = lines[line_coortype].split()[0] if coortype[0] in "cCkK": line_first_pos = line_coortype + 1 iscart = True else: iscart = False if coortype[0] in "dD": line_first_pos = line_coortype + 1 positions = [] total_atoms = sum(numofatoms) for i in range(line_first_pos, line_first_pos + total_atoms): s = lines[i].split() vec = float(s[0]), float(s[1]), float(s[2]) positions.append(vec) if iscart: positions = numpy.dot(numpy.array(positions), numpy.linalg.inv(lattice)) return Cell(lattice, positions, atoms)
def test_init(self): lattice = [1.0, 0, 0, 0, 1.0, 0, 0, 0, 1.0] positions = [0, 0, 0] atoms = ['NaN_10'] cell = Cell(lattice, positions, atoms) self.assertEqual(cell.atoms.tolist(), [1010])