Beispiel #1
0
def compare_cells(cell1, cell2, prec=1e-5):
    '''Compare two spglib cell if they are the same'''
    lattice_diff = np.linalg.norm(np.asarray(cell1[0]) - np.asarray(cell2[0]))

    same = False
    if lattice_diff < prec:
        pos1 = np.asarray(cell1[1])
        pos2 = np.asarray(cell2[1])
        if pos1.shape[0] == pos2.shape[0]:
            if len(cell1[2]) == len(cell2[2]):
                atom_type = (cell1[2] == cell2[2]).all()
                if atom_type == True:
                    sym1 = spglib.get_symmetry(cell1, prec)
                    sym2 = spglib.get_symmetry(cell2, prec)
                    rota1 = np.asarray(sym1['rotations'])
                    trans1 = np.asarray(sym1['translations'])
                    rota2 = np.asarray(sym2['rotations'])
                    trans2 = np.asarray(sym2['translations'])
                    equi1 = np.asarray(sym1['equivalent_atoms'])
                    equi2 = np.asarray(sym2['equivalent_atoms'])
                    if rota1.shape[0] == rota2.shape[0]:
                        diff_rotation = np.linalg.norm(rota1 - rota2) < prec
                        if diff_rotation and (trans1.shape[0]
                                              == trans2.shape[0]):
                            diff_translation = np.linalg.norm(trans1 -
                                                              trans2) < prec
                            if diff_translation and (equi1.shape[0]
                                                     == equi2.shape[0]):
                                diff_equi = np.linalg.norm(equi1 -
                                                           equi2) < prec
                                if diff_equi:
                                    same = True

    return same
Beispiel #2
0
def read_operation(poscar):
    import spglib
    [axis, atom_pos] = read_poscar(poscar)

    L = np.mat(axis)
    pos = []
    atom_type = []
    atom_dic = {}
    type_dic = {}
    index = 0
    for line in atom_pos:
        pos.append(line[0:3])
        if not line[4] in list(atom_dic.keys()):
            atom_dic[line[4]] = index
            type_dic[index] = [line[3], line[4]]
            index = index + 1
        atom_type.append(atom_dic[line[4]])
    D = np.mat(pos)
    Cell = (L, D, atom_type)

    rot_oper = np.ndarray.tolist(
        spglib.get_symmetry(Cell, symprec=1e-5)['rotations'])
    trans_oper = np.ndarray.tolist(
        spglib.get_symmetry(Cell, symprec=1e-5)['translations'])
    oper = []
    for i in range(len(rot_oper)):
        if sum([abs(x - 0.5) for x in trans_oper[i]
                ]) > 1.5 - 0.0000001:  # considering the PBC (1.0 = 0.0)
            oper.append(rot_oper[i])
    # symmetry opperator according to a,b,c axis (not x,y,z axis)
    return oper
Beispiel #3
0
def test_supercell_replica():
    total_path = os.path.dirname(os.path.abspath(__file__))
    os.chdir(total_path)

    # Load the structure
    struct = CC.Structure.Structure()
    struct.read_scf("unit_cell_structure.scf")

    # Generate a supercell
    super_struct = struct.generate_supercell((2, 2, 1))
    print("Space group before:")
    print(spglib.get_spacegroup(super_struct.get_ase_atoms()), )
    print(
        len(spglib.get_symmetry(super_struct.get_ase_atoms())["translations"]))

    # Get the symmetries in the supercell using spglib
    spglib_syms = spglib.get_symmetry(super_struct.get_ase_atoms())
    syms = CC.symmetries.GetSymmetriesFromSPGLIB(spglib_syms, False)
    nsyms = len(syms)

    # Generate a random distorted super structure
    d_structure = super_struct.copy()
    d_structure.coords += np.random.normal(scale=0.1,
                                           size=np.shape(d_structure.coords))

    # Get the new pool of structures
    new_d_structures = []
    for i in range(nsyms):
        # Get irt
        irt = CC.symmetries.GetIRT(super_struct, syms[i])
        #print "Symmetry ", i
        #print len(set(irt))

        u_disp = d_structure.coords - super_struct.coords
        new_u_disp = CC.symmetries.ApplySymmetryToVector(
            syms[i], u_disp, super_struct.unit_cell, irt[:])
        tmp = super_struct.copy()
        tmp.coords += new_u_disp
        tmp.save_scf("replica_%d.scf" % i)
        new_d_structures.append(tmp)

    # Average all the displacements to see if the symmetries are recovered correctly
    new_structure = super_struct.copy()
    new_structure.coords = np.sum([x.coords
                                   for x in new_d_structures], axis=0) / nsyms

    # Get again the symmetries
    print("Symmetries after the sum:")
    print(spglib.get_spacegroup(new_structure.get_ase_atoms()), )
    print(
        len(
            spglib.get_symmetry(
                new_structure.get_ase_atoms())["translations"]))

    # Lets check if the structure is the same as before
    # Should be 0 only if the symmeties are enaugh to have 0 force.
    print("Difference from the first one:")
    print(np.sqrt(np.sum((new_structure.coords - super_struct.coords)**2)))
Beispiel #4
0
 def test_get_symmetry(self):
     for fname in self._filenames:
         cell = read_vasp(fname)
         if 'distorted' in fname:
             num_sym_dataset = len(
                 get_symmetry_dataset(cell, symprec=1e-1)['rotations'])
             num_sym = len(get_symmetry(cell, symprec=1e-1)['rotations'])
         else:
             num_sym_dataset = len(
                 get_symmetry_dataset(cell, symprec=1e-5)['rotations'])
             num_sym = len(get_symmetry(cell, symprec=1e-5)['rotations'])
         self.assertEqual(num_sym_dataset, num_sym)
Beispiel #5
0
    def test_gen_nodup_cstru(self):
        c = Specie("Cu")
        t = Specie("Ti")
        m = [[-0.5, -0.5, -0.5],
             [-0.5,  0.5,  0.5],
             [ 0.5, -0.5,  0.5]]
        ele_sea = SitesGrid.sea(2, 2, 2, c)
        cell_mother_stru = CStru(m, ele_sea).get_cell()
        sym = get_symmetry(cell_mother_stru, symprec=1e-3)
        ops = [(r, t) for r, t in zip(sym['rotations'], sym['translations'])]

        sites_0 = [[[c, c],
                    [c, c]],

                   [[c, c],
                    [t, c]]]
        sg_0 = SitesGrid(sites_0)
        cstru01 = CStru(m, sg_0)

        gen_01 = sogen.gen_nodup_cstru(m, c, (2,2,2), t, 1)
        nodup_01 = [stru for stru in gen_01]
        self.assertEqual(len(nodup_01), 1)

        gen_02 = sogen.gen_nodup_cstru(m, c, (1,2,8), t, 4)
        nodup_02 = [stru for stru in gen_02]
        # eq_(len(nodup_02), 51)

        m_tri = [[0, 0, 20],
                        [1, 0, 0],
                        [0.5, 0.8660254, 0]]
        ele_sea = SitesGrid.sea(1, 3, 3, c)
        cell_mother_stru = CStru(m, ele_sea).get_cell()
        sym = get_symmetry(cell_mother_stru, symprec=1e-3)
        ops = [(r, t) for r, t in zip(sym['rotations'], sym['translations'])]

        sites_0 = [[[c, c, c],
                    [c, c, c],
                    [c, c, c]]]
        sg_0 = SitesGrid(sites_0)
        cstru01 = CStru(m, sg_0)

        gen_01 = sogen.gen_nodup_cstru(m_tri, c, (1,3,3), t, 2)
        nodup_01 = [stru for stru in gen_01]
        self.assertEqual(len(nodup_01), 2)

        gen_02 = sogen.gen_nodup_cstru(m_tri, c, (1,3,3), t, 3)
        nodup_02 = [stru for stru in gen_02]
        self.assertEqual(len(nodup_02), 4)

        gen_03 = sogen.gen_nodup_cstru(m_tri, c, (1,5,5), t, 2)
        nodup_03 = [stru for stru in gen_03]
        self.assertEqual(len(nodup_03), 4)
Beispiel #6
0
 def test_get_symmetry(self):
     for fname in self._filenames:
         spgnum = int(fname.split('-')[1])
         cell = read_vasp("./data/%s" % fname)
         if 'distorted' in fname:
             num_sym_dataset = len(
                 get_symmetry_dataset(cell, symprec=1e-1)['rotations'])
             num_sym = len(get_symmetry(cell, symprec=1e-1)['rotations'])
         else:
             num_sym_dataset = len(
                 get_symmetry_dataset(cell, symprec=1e-5)['rotations'])
             num_sym = len(get_symmetry(cell, symprec=1e-5)['rotations'])
         self.assertEqual(num_sym_dataset, num_sym)
Beispiel #7
0
 def test_get_symmetry(self):
     for fname in self._filenames:
         spgnum = int(fname.split('-')[1])
         cell = read_vasp("./data/%s" % fname)
         if 'distorted' in fname:
             num_sym_dataset = len(
                 get_symmetry_dataset(cell, symprec=1e-1)['rotations'])
             num_sym = len(get_symmetry(cell, symprec=1e-1)['rotations'])
         else:
             num_sym_dataset = len(
                 get_symmetry_dataset(cell, symprec=1e-5)['rotations'])
             num_sym = len(get_symmetry(cell, symprec=1e-5)['rotations'])
         self.assertEqual(num_sym_dataset, num_sym)
def symmetrically_inequivalent_indices(structure, center=None, species=None, symprec=0.01):
    cell = trans_pylada_stru_to_ase(structure)
    symmetry = spg.get_symmetry(cell, symprec=symprec)
    equivalent_atoms = symmetry['equivalent_atoms']
    inequivalent_sites = np.unique(equivalent_atoms)
    if center is None:
        if species is None:
            return inequivalent_sites
        else:
            indices = []
            for index in inequivalent_sites:
                if structure[index].type in species:
                    print(structure[index].type)
                    indices.append(index)
            return np.array(indices)
    else:
        center = np.dot(center, structure.cell.T)
        indices = []
        equivalent = {}
        for index in inequivalent_sites:
            equivalent[index] = [index, 9999999]
        for i in range(len(equivalent_atoms)):
            index = equivalent_atoms[i]
            atom = structure[i]
            distance = np.linalg.norm(atom.pos - center)
            if equivalent[index][1] > distance:
                equivalent[index][0] = i
                equivalent[index][1] = distance
        for index in inequivalent_sites:
            if species is None:
                indices.append(equivalent[index][0])
            else:
                if structure[index].type in species:
                    indices.append(equivalent[index][0])
        return np.array(indices)
Beispiel #9
0
 def get_rotations(self, symprec=1e-5):
     """
     dependent on spglib https://atztogo.github.io/spglib/
     """
     return spglib.get_symmetry(
         (self._lattice, self._positions, self._atoms),
         symprec)['rotations']
Beispiel #10
0
    def _test_get_symmetry(self):
        """
        ***************************************************************
        This test must be executed with spglib compiled with -DSPGTEST.
        ***************************************************************
        """

        for fname, dataset, cell, symprec in zip(
                self._filenames, self._datasets, self._cells, self._symprecs):
            cell_spin = cell + ([1, ] * len(cell[2]),)
            symmetry = get_symmetry(cell_spin, symprec=symprec)

            self.assertEqual(len(dataset['rotations']),
                             len(symmetry['rotations']),
                             msg=("%s" % fname))

            for r, t in zip(dataset['rotations'], dataset['translations']):
                found = False
                for r_, t_ in zip(symmetry['rotations'],
                                  symmetry['translations']):
                    if (r == r_).all():
                        diff = t - t_
                        diff -= np.rint(diff)
                        if (abs(diff) < symprec).all():
                            found = True
                            break
                self.assertTrue(found, msg="%s" % fname)
Beispiel #11
0
    def symmetry_operations(self, symprec=1e-2):
        """
        Get the symmetry operations that the crystal unit cell respects. These symmetry operations
        are expressed in fractional coordinates.

        Parameters
        ----------
        symprec : float, optional
            Symmetry-search distance tolerance in Cartesian coordinates [Angstroms].
        
        Returns
        -------
        sym_ops : iterable of 2-tuples
            Each symmetry operations is a tuple of ``(rotation, translation)``.
            A rotation matrix is an array of shape (3,3), while ``translation`` is an array
            of shape (3,).

        Raises
        ------
        RuntimeError : if symmetry-determination has not succeeded.

        See also
        --------
        Crystal.reciprocal_symmetry_operations : symmetry operations in reciprocal basis
        """
        dataset = get_symmetry(cell=self._spglib_cell(), symprec=symprec)

        return [
            SymmetryOperation(r, t)
            for r, t in zip(dataset["rotations"], dataset["translations"])
        ]
Beispiel #12
0
def space_group_analyse(lattice, pos):
    numbers = [1, 2]
    cell = (lattice, pos, numbers)
    sp = spglib.get_spacegroup(cell, symprec=1e-5)
    symm = spglib.get_symmetry(cell, symprec=1e-5)
    #print(spglib.niggli_reduce(lattice, eps=1e-5))

    #mesh = [8, 8, 8]
    #mapping, grid = spglib.get_ir_reciprocal_mesh(mesh, cell, is_shift=[0, 0, 0])
    ## All k-points and mapping to ir-grid points
    #for i, (ir_gp_id, gp) in enumerate(zip(mapping, grid)):
    #	print("%3d ->%3d %s" % (i, ir_gp_id, gp.astype(float) / mesh))
    #
    ## Irreducible k-points
    #print("Number of ir-kpoints: %d" % len(np.unique(mapping)))
    #print(grid[np.unique(mapping)] / np.array(mesh, dtype=float))
    #
    ##
    ## With shift
    ##
    #mapping, grid = spglib.get_ir_reciprocal_mesh(mesh, cell, is_shift=[1, 1, 1])
    #
    ## All k-points and mapping to ir-grid points
    #for i, (ir_gp_id, gp) in enumerate(zip(mapping, grid)):
    #	print("%3d ->%3d %s" % (i, ir_gp_id, (gp + [0.5, 0.5, 0.5]) / mesh))
    #
    ## Irreducible k-points
    #print("Number of ir-kpoints: %d" % len(np.unique(mapping)))
    #print((grid[np.unique(mapping)] + [0.5, 0.5, 0.5]) / mesh)
    return sp, symm
Beispiel #13
0
def test_impose_symmetry():
    total_path = os.path.dirname(os.path.abspath(__file__))
    os.chdir(total_path)


    # initialize the dynamical matrix
    dyn = CC.Phonons.Phonons("old_dyn", full_name=True)

    # Print the symmetry group at high threshold
    GROUP = spglib.get_spacegroup(dyn.structure.get_ase_atoms(), 0.05)
    s_group_expected = spglib.get_spacegroup(dyn.structure.get_ase_atoms())
    print ("Space group with high threshold:", s_group_expected)
    print ("Space group with low threshold:", GROUP)

    # Get the symmetries from the new spacegroup
    symmetries = spglib.get_symmetry(dyn.structure.get_ase_atoms(), symprec = 0.05)
    print("Number of symmetries: {}".format(len(symmetries["rotations"])))

    # Transform the spglib symmetries into the CellConstructor data type
    sym_mats = CC.symmetries.GetSymmetriesFromSPGLIB(symmetries, True)
    # Force the symmetrization
    dyn.structure.impose_symmetries(sym_mats)

    # Check once again the symetry
    s_group_after = spglib.get_spacegroup(dyn.structure.get_ase_atoms())
    print ("New space group with high threshold:", s_group_after)

    assert s_group_after == GROUP
def gulp_opt(stru):
    gulp_inp = 'opt.gin'
    tp_inp = 'tp_inp'
    out = 'out'
    cif_out = 'final.cif'
    symprec = 0.01

    ccell = standardize_cell((stru.cell, stru.get_scaled_positions(), stru.numbers), symprec=symprec)
    if ccell:
        symmetry = get_symmetry(ccell, symprec=symprec)
        spacegroup = get_spacegroup(ccell, symprec=symprec)
    else:
        symmetry = get_symmetry((stru.cell, stru.get_scaled_positions(), stru.numbers), symprec=symprec)
        spacegroup = get_spacegroup((stru.cell, stru.get_scaled_positions(), stru.numbers), symprec=symprec)
    asymmetric_atoms = np.unique(symmetry.equivalent_atoms)
    pass
Beispiel #15
0
    def get_max_rot_angle(self) -> None:
        ''' Get the maximum angle of rotation for a given slab that will
        generate all symmetrically distinct TS estimates.

        Returns
        ________
        max_rot_angle : float
            a maximum angle of rotation of TS adducts on the given slab that
            would generate symmetrically dostinct configurations
            i.e. once the TS adduct is rotated by bigger angle than
            max_rot_angle, some of the generated structures will be
            symetrically equivalent to the others

        '''
        # convert slab to ASE's Atom object
        slab = read(self.slab)
        # get all symmetry operations
        symm = get_symmetry(slab)
        # count rotations operations
        nrot = len(symm['rotations'])
        # the angle of rotation is 360 devided by nrot/2 as thera are equal
        # number of symmetry operations around the z axis
        # (e.g. for Cu_111 therea are 6 z and 6 -z operations)
        max_rot_angle = 360 / (nrot / 2)
        # max_rot_angle = 360/(nrot/4) # lets try 120 angle
        return max_rot_angle
Beispiel #16
0
    def _test_get_symmetry(self):
        """
        ***************************************************************
        This test must be executed with spglib compiled with -DSPGTEST.
        ***************************************************************
        """

        for fname, dataset, cell, symprec in zip(self._filenames,
                                                 self._datasets, self._cells,
                                                 self._symprecs):
            cell_spin = cell + ([
                1,
            ] * len(cell[2]), )
            symmetry = get_symmetry(cell_spin, symprec=symprec)

            self.assertEqual(len(dataset['rotations']),
                             len(symmetry['rotations']),
                             msg=("%s" % fname))

            for r, t in zip(dataset['rotations'], dataset['translations']):
                found = False
                for r_, t_ in zip(symmetry['rotations'],
                                  symmetry['translations']):
                    if (r == r_).all():
                        diff = t - t_
                        diff -= np.rint(diff)
                        if (abs(diff) < symprec).all():
                            found = True
                            break
                self.assertTrue(found, msg="%s" % fname)
Beispiel #17
0
def test_diag_symmetries():
    total_path = os.path.dirname(os.path.abspath(__file__))
    os.chdir(total_path)

    # Diagonalize the dynamical matrix in the supercell
    dyn = CC.Phonons.Phonons("../TestDiagonalizeSupercell/prova", 4)
    w, p = dyn.DiagonalizeSupercell()

    view(dyn.structure.get_ase_atoms())

    # Get the symmetries
    supercell_s = dyn.structure.generate_supercell(dyn.GetSupercell())
    spglib_syms = spglib.get_symmetry(dyn.structure.get_ase_atoms())
    syms = CC.symmetries.GetSymmetriesFromSPGLIB(spglib_syms)

    # Get the symmetries on the polarization vectors
    pols_syms = CC.symmetries.GetSymmetriesOnModes(syms, supercell_s, p)

    # Now complete the diagonalization of the polarization vectors
    # To fully exploit symmetries
    new_pols, syms_character = CC.symmetries.get_diagonal_symmetry_polarization_vectors(p, w, pols_syms)

    # TODO: Test if these new polarization vectors really rebuild the dynamical matrix

    # write the symmetry character
    n_modes, n_syms = syms_character.shape

    for i in range(n_modes):
        print("Mode {} | ".format(i), np.angle(syms_character[i,:], deg = True))
Beispiel #18
0
def analyse_phonopy_equivalent_atoms(atoms,
                                     symprec=1e-5,
                                     angle_tolerance=-1.0):
    """
    Args: (read phonopy.structure.spglib for more details)
        symprec:
            float: Symmetry search tolerance in the unit of length.
        angle_tolerance:
            float: Symmetry search tolerance in the unit of angle deg.
                If the value is negative, an internally optimized routine
                is used to judge symmetry.

    """
    state.publications.add(publication())
    positions = atoms.get_scaled_positions()
    cell = atoms.cell
    types = atoms.get_chemical_symbols()
    types = list(types)
    natom = len(types)
    positions = np.reshape(np.array(positions), (natom, 3))
    cell = np.reshape(np.array(cell), (3, 3))
    unitcell = PhonopyAtoms(symbols=types,
                            cell=cell,
                            scaled_positions=positions)
    ops = spg.get_symmetry(unitcell,
                           symprec=symprec,
                           angle_tolerance=angle_tolerance)
    return ops["equivalent_atoms"]
Beispiel #19
0
    def test_update_isoset(self):
        c = Specie("Cu")
        t = Specie("Ti")
        m = [[-0.5, -0.5, -0.5],
             [-0.5,  0.5,  0.5],
             [ 0.5, -0.5,  0.5]]
        ele_sea = SitesGrid.sea(2, 2, 2, c)
        cell_mother_stru = CStru(m, ele_sea).get_cell()
        sym = get_symmetry(cell_mother_stru, symprec=1e-5)
        ops = [(r, t) for r, t in zip(sym['rotations'], sym['translations'])]
        sym_perm = sogen.get_permutation_cell(cell_mother_stru)

        sites_0 = [[[c, c],
                    [c, c]],

                   [[c, c],
                    [t, c]]]
        sg_0 = SitesGrid(sites_0)
        cstru01 = CStru(m, sg_0)
        number01 = cstru01.get_cell()[2]

        isoset_init = set()
        isoset_init_copy = isoset_init.copy()
        isoset_a01 = sogen._update_isoset(isoset_init, number01, sym_perm)
        self.assertNotEqual(isoset_a01, isoset_init_copy)
        self.assertIsInstance(isoset_a01, set)

        isoset_a01_copy = isoset_a01.copy()
        isoset_a02 = sogen._update_isoset(isoset_a01, number01, sym_perm)
        self.assertEqual(isoset_a02, isoset_a01_copy)
        self.assertLessEqual(len(isoset_a01), len(ops))
Beispiel #20
0
def get_symmetry(atoms, tol=1e-8):
    """Atoms object interface with spglib symmetry finder:
    https://atztogo.github.io/spglib/python-spglib.html#python-spglib

    Parameters
    ----------
    atoms : object
        Atoms object to search for symmetric structures of.
    tol : float
        Tolerance for floating point rounding errors.

    Returns
    -------
    symmetry operations: ndarray (n, n)
        Symmetry operations from spglib.
    """
    lattice = atoms.cell
    positions = atoms.get_scaled_positions()
    numbers = atoms.get_atomic_numbers()

    cell = (lattice, positions, numbers)

    symmetry = spglib.get_symmetry(cell, symprec=tol)

    rotations, translations = symmetry['rotations'], symmetry['translations']

    return rotations, translations
Beispiel #21
0
def matrix_of_equivalent_positions_from_structure(structure: Atoms,
                                                  cutoff: float,
                                                  position_tolerance: float,
                                                  symprec: float,
                                                  find_primitive: bool = True) \
        -> Tuple[np.ndarray, Structure, List]:
    """Sets up a list of permutation maps from an Atoms object.

    Parameters
    ----------
    structure
        input structure
    cutoff
        cutoff radius
    find_primitive
        if True the symmetries of the primitive structure will be employed
    symprec
        tolerance imposed when analyzing the symmetry using spglib
    position_tolerance
        tolerance applied when comparing positions in Cartesian coordinates

    Returns
    -------
    The tuple that is returned comprises the permutation matrix, the
    primitive structure, and the neighbor list.
    """

    structure = structure.copy()
    structure_prim = structure
    if find_primitive:
        structure_prim = get_primitive_structure(structure, symprec=symprec)
    logger.debug('Size of primitive structure: {}'.format(len(structure_prim)))

    # get symmetry information
    structure_as_tuple = ase_atoms_to_spglib_cell(structure_prim)
    symmetry = spglib.get_symmetry(structure_as_tuple, symprec=symprec)
    translations = symmetry['translations']
    rotations = symmetry['rotations']

    # set up a permutation map object
    matrix_of_equivalent_positions = MatrixOfEquivalentPositions(
        translations, rotations)

    # create neighbor_lists from the different cutoffs
    prim_icet_structure = Structure.from_atoms(structure_prim)

    neighbor_list = get_neighbor_lists(
        prim_icet_structure, [cutoff],
        position_tolerance=position_tolerance)[0]

    # get fractional positions for neighbor_list
    frac_positions = get_fractional_positions_from_neighbor_list(
        prim_icet_structure, neighbor_list)

    logger.debug('Number of fractional positions: {}'.format(
        len(frac_positions)))
    if frac_positions is not None:
        matrix_of_equivalent_positions.build(frac_positions)

    return matrix_of_equivalent_positions, prim_icet_structure, neighbor_list
Beispiel #22
0
    def __init__(self, unit_gcell, lat_coeff):
        self.ub = unit_gcell.lattice
        self.upositions = unit_gcell.positions
        self.unumbers = unit_gcell.numbers
        self.lat_coeff = lat_coeff
        self.unit_cell = unit_gcell.spg_cell

        self.sym = spglib.get_symmetry(self.unit_cell, symprec=1e-3)
Beispiel #23
0
def test_check_fc_symmetry():

    total_path = os.path.dirname(os.path.abspath(__file__))
    os.chdir(total_path)
    """
    This script check the symmetries of a dynamical matrix.
    In the end the symmetry is constrained.
    """
    RyToCm = 109691.40235

    # Read the dynamical matrix
    PH = CC.Phonons.Phonons("hydrogen_dyn", nqirr=1)

    print("Loaded hydrogen_dyn1")
    print("Symmetry group:",
          spglib.get_spacegroup(PH.structure.get_ase_atoms(), 0.01))

    # Get info about the symmetries of the structure
    symmetries = spglib.get_symmetry(PH.structure.get_ase_atoms(), 0.01)
    print("Number of symmetries:", len(symmetries["rotations"]))

    # Convert the spglib symmetries into the cellconstructor format
    sym_mats = CC.symmetries.GetSymmetriesFromSPGLIB(symmetries)

    # Impose the symmetries on the structure
    PH.structure.fix_coords_in_unit_cell()
    PH.structure.impose_symmetries(sym_mats)

    # get a random matrix
    nat = PH.structure.N_atoms
    #PH.dynmats[0][:,:] = np.random.uniform(size = (3 * nat, 3*nat))
    #PH.dynmats[0] += PH.dynmats[0].T

    # Get frequencies of the original matrix
    w, pols = PH.DyagDinQ(0)
    PH_new = PH.Copy()

    # Force the symmetrization
    #PH_new.SymmetrizeSupercell((1,1,1))
    qe_sym = CC.symmetries.QE_Symmetry(PH.structure)
    #qe_sym.SetupQPoint(verbose = True)
    qe_sym.SetupFromSPGLIB()
    #qe_sym.SymmetrizeDynQ(PH_new.dynmats[0], np.array([0,0,0]))
    qe_sym.ApplySymmetriesToV2(PH_new.dynmats[0])
    CC.symmetries.CustomASR(PH_new.dynmats[0])

    new_w, new_pols = PH_new.DyagDinQ(0)

    # Symmetrize using the quantum espresso
    PH.Symmetrize()
    w_qe, p_qe = PH.DyagDinQ(0)

    print("Old Matrix | Python Symmetries | QE Symmetries | ")
    print("\n".join([
        "%12.2f\t%12.2f\t%12.2f  cm-1" %
        (w[k] * RyToCm, new_w[k] * RyToCm, w_qe[k] * RyToCm)
        for k in range(0, len(w))
    ]))
Beispiel #24
0
def get_sym(cell, symprec=1e-5, print_atom=False, print_analysis=True):
    '''Giving a cell, return symmetry analysis'''

    # spglib only work with tuple
    cell = tuple(cell)

    #Space group info
    spg_label, spg_number = spglib.get_spacegroup(cell, symprec).split(' ')
    spg_number = spg_number.split("(")[1].split(")")[0]
    Schoenflies_label = spglib.get_spacegroup(cell, symprec,
                                              symbol_type=1).split(' ')[0]
    sym = spglib.get_symmetry(cell, symprec)
    rotations = sym['rotations']
    translations = sym['translations']
    equi_atoms = sym['equivalent_atoms']

    is_std = is_prim = False
    std_cell = spglib.refine_cell(cell, symprec)
    prim_cell = spglib.find_primitive(cell, symprec)
    if compare_cells(cell, std_cell): is_std = True
    if compare_cells(cell, prim_cell): is_prim = True

    atoms = utils.convert_atomtype(cell[2])
    if print_analysis == True:
        #Cell info
        std_cell = spglib.refine_cell(cell, symprec)
        prim_cell = spglib.find_primitive(cell, symprec)

        #Print
        misc.print_msg("Spacegroup  number           : %s" % (spg_number))
        misc.print_msg("Short International symbol   : %s" % (spg_label))
        misc.print_msg("Schoenflies symbol           : %s" %
                       (Schoenflies_label))
        if print_atom == True:
            misc.print_msg("Atoms list (No. - Sym - Symbol):")
            for i, atom in enumerate(atoms):
                misc.print_msg("%3d   %3d   %s" %
                               (i + 1, equi_atoms[i] + 1, atom))
            misc.print_msg("Irreducible atoms:")
            for i, index in enumerate(np.unique(equi_atoms)):
                coord = cell[1][index]
                misc.print_msg(
                    "%3d  %3s    %7f5 %7f5 %7f5" %
                    (i + 1, atoms[index], coord[0], coord[1], coord[2]))
        misc.print_msg("Number of irreducible atoms  : %d" %
                       (np.unique(equi_atoms).shape[0]))
        misc.print_msg("Standard cell                : %r" % (is_std))
        misc.print_msg("Primitive cell               : %r" % (is_prim))
    else:
        # Return an standard cell object with irreducible atoms
        irred_idx = np.unique(equi_atoms)
        lattice = cell[0]
        irred_coord = cell[1][irred_idx, :]
        irred_label = np.array(cell[2])[irred_idx]
        irred_cell = (lattice, irred_coord, irred_label)

        return irred_cell, int(spg_number), spg_label, rotations, translations
Beispiel #25
0
 def get_symmetry(self):
     """
     Symmetry operations are obtained as a dictionary.
     The key rotation contains a numpy array of integer,
     which is “number of symmetry operations” x “3x3 matrices”.
     The key translation contains a numpy array of float,
     which is “number of symmetry operations” x “vectors”.
     """
     symmetry = spglib.get_symmetry(self._spg_cell, symprec=self.symprec)
     return symmetry
    def setUp(self):
        """Setup before each test."""
        symmetry = spglib.get_symmetry(
            ase_atoms_to_spglib_cell(self.structure_prim))
        self.translations = symmetry['translations']
        self.rotations = symmetry['rotations']

        self.pm = MatrixOfEquivalentPositions(self.translations,
                                              self.rotations)
        self.pm.build(self.frac_positions)
Beispiel #27
0
def get_unique_wyckoff(ats_in):
    """ Function to find unique wyckoff sites in the primitive cell

    Args:
      ats_in(:ase:class:`Atoms`): Atoms object of interface.

    Returns
      unique list of lattice sites in primitive cell [[position,"chem_abbrev"],...]
    """
    # compute space group for the given primitive cell using spglib
    ats = ats_in.copy()
    #sym = spglib.get_symmetry(ats, 0.1)
    sym = spglib.get_symmetry(ats)

    # compute inverce cell of the primitive cell
    inverse_cell = np.linalg.inv(ats.cell)

    dummy_list = []
    wyckoff_list = []
    #args = np.argsort(ats.positions[:, 0])
    #ats = ats[args]
    for i, at in enumerate(ats):
        print i, '/', len(ats)
        a = at.position
        a3 = get_pos_in_prim_cell(ats.copy(), a)
        frac_a = np.dot(inverse_cell, a3)
        symm_list = []
        for j in range(len(sym['rotations'])):
            # rotation matrix from sym
            R = sym['rotations'][j]
            # translation vector from sym
            Tt = sym['translations'][j]
            frac_symm_a = np.dot(R, frac_a) + Tt
            symm_a = np.dot(ats.cell, frac_symm_a)
            symm_list.append(symm_a)
            symm_a2 = get_pos_in_prim_cell(ats.copy(), symm_a)
            symm_list.append(symm_a2)
        # loop to find symmetrical equivalent positions
        for k in range(i + 1, len(ats)):
            b = ats[k].position
            b2 = get_pos_in_prim_cell(ats, b)
            # check distance between positions in pos and symm_list
            if any(distance.euclidean(b, c) < 0.1 for c in symm_list):
                ats[k].position = ats[i].position
        dummy_list = a.tolist()
        dummy_list.append(ats[i].symbol)
        wyckoff_list.append(dummy_list)

    ### getting unique array of positions
    unique_list = [list(t) for t in set(map(tuple, wyckoff_list))]

    return unique_list
Beispiel #28
0
def spginfo(self):
    cell = (self.a, self.frac, self.charges)
    print("[get_spacegroup]")
    print("  Spacegroup of cell is %s" % spg.get_spacegroup(cell))
    print("[get_symmetry]")
    print("  Symmetry operations of unitcell are")
    symmetry = spg.get_symmetry(cell)
    show_symmetry(symmetry)
    print("[get_pointgroup]")
    print("  Pointgroup of cell is %s" %
          spg.get_pointgroup(symmetry['rotations'])[0])
    dataset = spg.get_symmetry_dataset(cell)
    print("[get_symmetry_dataset] ['international']")
    print("  Spacegroup of cell is %s (%d)" %
          (dataset['international'], dataset['number']))
    print("[get_symmetry_dataset] ['pointgroup']")
    print("  Pointgroup of cell is %s" % (dataset['pointgroup']))
    print("[get_symmetry_dataset] ['hall']")
    print("  Hall symbol of cell is %s (%d)." %
          (dataset['hall'], dataset['hall_number']))
    print("[get_symmetry_dataset] ['wyckoffs']")
    alphabet = "abcdefghijklmnopqrstuvwxyz"
    print("  Wyckoff letters of cell are ", dataset['wyckoffs'])
    print("[get_symmetry_dataset] ['equivalent_atoms']")
    print("  Mapping to equivalent atoms of cell ")
    for i, x in enumerate(dataset['equivalent_atoms']):
        print("  %d -> %d" % (i + 1, x + 1))
    print("[get_symmetry_dataset] ['rotations'], ['translations']")
    print("  Symmetry operations of unitcell are:")
    for i, (rot, trans) in enumerate(
            zip(dataset['rotations'], dataset['translations'])):
        print("  --------------- %4d ---------------" % (i + 1))
    print("  rotation:")
    for x in rot:
        print("     [%2d %2d %2d]" % (x[0], x[1], x[2]))
    print("  translation:")
    print("     (%8.5f %8.5f %8.5f)" % (trans[0], trans[1], trans[2]))
    reduced_lattice = spg.niggli_reduce(self.a)
    print("[niggli_reduce]")
    print("  Original lattice")
    show_lattice(self.a)
    print("  Reduced lattice")
    show_lattice(reduced_lattice)
    mapping, grid = spg.get_ir_reciprocal_mesh([11, 11, 11],
                                               cell,
                                               is_shift=[0, 0, 0])
    num_ir_kpt = len(numpy.unique(mapping))
    print("[get_ir_reciprocal_mesh]")
    print("  Number of irreducible k-points of primitive")
    print("  11x11x11 Monkhorst-Pack mesh is %d " % num_ir_kpt)

    return self
Beispiel #29
0
def get_permutation_cell(cell):
    lat, pos, num = cell
    atom_num = len(cell[2])
    numbers = [i for i in range(atom_num)]
    sym = get_symmetry(cell, symprec=1e-3)
    ops = [(r, t) for r, t in zip(sym['rotations'], sym['translations'])]
    sym_perm = []
    for r, t in ops:
        pos_new = np.transpose(np.matmul(r, np.transpose(pos))) + t
        perm = get_new_id_seq(pos_new, numbers)
        sym_perm.append(perm)

    return sym_perm
Beispiel #30
0
    def get_symmetry(
            self,
            symprec: float = 1e-5,
            angle_tolerance: float = -1) -> Union[Dict[str, np.ndarray], None]:
        """Return dictionary of symmetry operations

        :params symprec: distance tolerance in Cartesian coordinates to find crystal symmetry. Default: 1e-5
        :params angle_tolerance: tolerance of angle between basis vectors in degrees to be tolerated in the symmetry finding. Default: -1
        :return dictionary with keys "rotation", "translation" and "equivalent_atoms"
        """

        import spglib
        return spglib.get_symmetry(self.spgcell, symprec, angle_tolerance)
Beispiel #31
0
    def _get_symmetry(self):
        """
        Get the symmetry operations associated with the structure.

        Returns:
            Symmetry operations as a tuple of two equal length sequences.
            (rotations, translations). "rotations" is the numpy integer array
            of the rotation matrices for scaled positions
            "translations" gives the numpy float64 array of the translation
            vectors in scaled positions.
        """
        d = spglib.get_symmetry(self._cell, symprec=self._symprec,
                                angle_tolerance=self._angle_tol)
        return d["rotations"], d["translations"]
Beispiel #32
0
    def _get_symmetry(self):
        """
        Get the symmetry operations associated with the structure.

        Returns:
            Symmetry operations as a tuple of two equal length sequences.
            (rotations, translations). "rotations" is the numpy integer array
            of the rotation matrices for scaled positions
            "translations" gives the numpy float64 array of the translation
            vectors in scaled positions.
        """
        d = spglib.get_symmetry(self._cell, symprec=self._symprec,
                                angle_tolerance=self._angle_tol)
        return d["rotations"], d["translations"]
Beispiel #33
0
def writeCIF(cell, prec, basename):

    # Find spacegroup name and number
    sg = spglib.get_spacegroup(cell, symprec=prec)
    sg, sgid = sg.split(' (')
    sgid = sgid.replace(')', '')

    # Find detailed info about the refined cell
    lattice, scaled_positions, numbers = spglib.refine_cell(cell, prec)
    if len(numbers) != len(cell):
        # create new cell
        ncell = (lattice, scaled_positions, numbers)
    else:
        ncell = copy.deepcopy(cell)
    sym = spglib.get_symmetry(ncell, prec)
    uniques = np.unique(sym['equivalent_atoms'])
    a, b, c, alpha, beta, gamma = cellParameters(lattice)

    f = open((basename + '_' + sgid + '.cif').replace('/', '|'), 'w')

    f.write(f'# Symmetrized structure with precision = {prec}\n')

    f.write(f'data_{basename}{sg}\n'.replace(' ', '_'))
    f.write('_cell_length_a                  %.7g\n' % a)
    f.write('_cell_length_b                  %.7g\n' % b)
    f.write('_cell_length_c                  %.7g\n' % c)
    f.write('_cell_angle_alpha               %.7g\n' % alpha)
    f.write('_cell_angle_beta                %.7g\n' % beta)
    f.write('_cell_angle_gamma               %.7g\n' % gamma)
    f.write("_symmetry_space_group_name_H-M  '" + sg + "'\n")
    f.write('_symmetry_Int_Tables_number     ' + str(sgid) + '\n')

    # Write out atomic positions
    f.write('''
loop_
_atom_site_label
_atom_site_type_symbol
_atom_site_occupancy
_atom_site_fract_x
_atom_site_fract_y
_atom_site_fract_z
''')

    for pos, at in zip(scaled_positions[uniques], numbers[uniques]):
        sym = element_symbols[at]
        f.write('%s %s 1.0 %.7f %.7f %.7f\n' %
                (sym, sym, pos[0], pos[1], pos[2]))

    f.close()
Beispiel #34
0
def writeCIF(cell, prec, basename):

    # Find spacegroup name and number
    sg = spglib.get_spacegroup(cell, symprec=prec)
    sg, sgid = sg.split(' (')
    sgid = sgid.replace(')', '')

    # Find detailed info about the refined cell
    lattice, scaled_positions, numbers = spglib.refine_cell(cell, prec)
    if len(numbers) != len(cell):
        # create new cell
        ncell = (lattice, scaled_positions, numbers)
    else:
        ncell = copy.deepcopy(cell)
    sym = spglib.get_symmetry(ncell, prec)
    uniques = np.unique(sym['equivalent_atoms'])
    a, b, c, alpha, beta, gamma = cellParameters(lattice)

    f = open((basename + '_' + sgid + '.cif').replace('/', '|'), 'w')

    f.write(f'# Symmetrized structure with precision = {prec}\n')

    f.write(f'data_{basename}{sg}\n'.replace(' ', '_'))
    f.write('_cell_length_a                  %.7g\n' % a)
    f.write('_cell_length_b                  %.7g\n' % b)
    f.write('_cell_length_c                  %.7g\n' % c)
    f.write('_cell_angle_alpha               %.7g\n' % alpha)
    f.write('_cell_angle_beta                %.7g\n' % beta)
    f.write('_cell_angle_gamma               %.7g\n' % gamma)
    f.write("_symmetry_space_group_name_H-M  '" + sg + "'\n")
    f.write('_symmetry_Int_Tables_number     ' + str(sgid) + '\n')

    # Write out atomic positions
    f.write('''
loop_
_atom_site_label
_atom_site_type_symbol
_atom_site_occupancy
_atom_site_fract_x
_atom_site_fract_y
_atom_site_fract_z
''')

    for pos, at in zip(scaled_positions[uniques], numbers[uniques]):
        sym = element_symbols[at]
        f.write('%s %s 1.0 %.7f %.7f %.7f\n' % (sym, sym, pos[0], pos[1], pos[2]))

    f.close()
Beispiel #35
0
print("  Spacegroup of Silicon is %s." % spglib.get_spacegroup(silicon))
print('')
print("[get_spacegroup]")
print("  Spacegroup of Silicon (ASE Atoms-like format) is %s." %
      spglib.get_spacegroup(silicon_ase))
print('')
print("[get_spacegroup]")
print("  Spacegroup of Rutile is %s." % spglib.get_spacegroup(rutile))
print('')
print("[get_spacegroup]")
print("  Spacegroup of MgB2 is %s." % spglib.get_spacegroup(MgB2))
print('')
print("[get_symmetry]")
print("  Symmetry operations of Rutile unitcell are:")
print('')
symmetry = spglib.get_symmetry(rutile)
show_symmetry(symmetry)
print('')
print("[get_symmetry]")
print("  Symmetry operations of MgB2 are:")
print('')
symmetry = spglib.get_symmetry(MgB2)
show_symmetry(symmetry)
print('')
print("[get_pointgroup]")
print("  Pointgroup of Rutile is %s." %
      spglib.get_pointgroup(symmetry['rotations'])[0])
print('')

dataset = spglib.get_symmetry_dataset( rutile )
print("[get_symmetry_dataset] ['international']")
Beispiel #36
0
 def test_get_symmetry_broken_magmoms(self):
     self._cell[3][0] = 1
     self._cell[3][1] = 2
     sym = get_symmetry(self._cell)
     self.assertEqual(48, len(sym['rotations']))
     self.assertTrue((sym['equivalent_atoms'] == [0, 1]).all())
Beispiel #37
0
 def test_get_symmetry_anti_ferro(self):
     self._cell[3][0] = 1
     self._cell[3][1] = -1
     sym = get_symmetry(self._cell)
     self.assertEqual(96, len(sym['rotations']))
     self.assertTrue((sym['equivalent_atoms'] == [0, 0]).all())
Beispiel #38
0
 def get_symmetry(self, symprec=1e-5):
     return spg.get_symmetry(cell=self.spglib_cell, symprec=symprec)