Beispiel #1
0
    def test_get_ir_reciprocal_mesh_distortion(self):
        j = 0
        for is_shift in ([0, 0, 0], [0, 1, 0]):
            for i, mesh in enumerate(([3, 4, 4], [3, 5, 1])):
                ir_rec_mesh = get_ir_reciprocal_mesh(mesh,
                                                     self.cells[i],
                                                     is_shift=is_shift,
                                                     is_dense=False)
                (mapping_table, grid_address) = ir_rec_mesh
                # for gp, ga in zip(mapping_table, grid_address):
                #     print("%4d  %3d %3d %3d" % (gp, ga[0], ga[1], ga[2]))
                # print("")
                data = np.loadtxt(StringIO(result_ir_rec_mesh_distortion[j]),
                                  dtype='intc')
                np.testing.assert_equal(data[:, 0], mapping_table)
                np.testing.assert_equal(data[:, 1:4], grid_address)

                ir_rec_mesh = get_ir_reciprocal_mesh(mesh,
                                                     self.cells[i],
                                                     is_shift=is_shift,
                                                     is_dense=True)
                (mapping_table, grid_address) = ir_rec_mesh
                np.testing.assert_equal(data[:, 0], mapping_table)
                np.testing.assert_equal(data[:, 1:4], grid_address)

                j += 1
Beispiel #2
0
    def setGrid(self, mesh=3):
        """ Define the resolution of the reciprocal space
        
        :type  mesh: ndarray, list, int
        :param mesh: The number of point along a reciprocal latticevector
        """
        if isinstance(mesh, (float, int)):
            mesh = np.ones((3, ), dtype=np.int) * int(mesh)

        if isinstance(mesh, (list, tuple)):
            mesh = np.asarray(mesh)

        if isinstance(mesh, np.ndarray):
            self.crystal.brillouinZone.mesh = mesh
            mapping, grid = spg.get_ir_reciprocal_mesh(mesh,
                                                       self.spg,
                                                       is_shift=[0, 0, 0])

            if np.any(mesh == np.array([1, 1, 1])):
                mesh += (mesh == np.array([1, 1, 1])) * 1
            k_grid = grid[np.unique(mapping)] / (mesh - 1)

            k_list = []
            for i, map_id in enumerate(mapping[np.unique(mapping)]):
                k_list.append(
                    (grid[mapping == map_id] /
                     (mesh - 1)).tolist())  #np.dot(,self.cell.brillouinZone)
            self.k_grid = k_grid
            self.k_list = k_list
        else:
            _logger.warning("Unknown type {} for mesh, try ndarray.".format(
                type(mesh)))
Beispiel #3
0
    def get_ir_reciprocal_mesh(self, mesh=(10, 10, 10), shift=(0, 0, 0)):
        """
        k-point mesh of the Brillouin zone generated taken into account
        symmetry.The method returns the irreducible kpoints of the mesh
        and their weights

        Args:
            mesh (3x1 array): The number of kpoint for the mesh needed in
                each direction
            shift (3x1 array): A shift of the kpoint grid. For instance,
                Monkhorst-Pack is [0.5,0.5,0.5]
            is_time_reversal (bool): Set to True to impose time reversal
                symmetry.

        Returns:
            A list of irreducible kpoints and their weights as a list of
            tuples [(ir_kpoint, weight)], with ir_kpoint given
            in fractional coordinates
        """
        mapping, grid = spglib.get_ir_reciprocal_mesh(np.array(mesh),
                                                      self._cell,
                                                      is_shift=np.array(shift))

        results = []
        tmp_map = list(mapping)
        for i in np.unique(mapping):
            results.append((grid[i] / mesh, tmp_map.count(i)))
        return results
Beispiel #4
0
    def setGrid(self, mesh=3):
        """ Define the resolution of the reciprocal space
        
        :type  mesh: ndarray, list, int
        :param mesh: The number of point along a reciprocal latticevector
        """
        if isinstance(mesh, (float, int)):
            mesh = np.ones((3, ), dtype=np.int) * int(mesh)

        if isinstance(mesh, (list, tuple)):
            mesh = np.asarray(mesh)

        if isinstance(mesh, np.ndarray):
            for i in range(len(mesh)):
                if (mesh[i] % 2 == 0):
                    mesh[i] += 1

            self._crystal.brillouinzone.mesh = mesh
            mapping, grid = spg.get_ir_reciprocal_mesh(mesh,
                                                       self._spg,
                                                       is_shift=[0, 0, 0])

            if np.any(mesh == np.array([1, 1, 1])):
                mesh += (mesh == np.array([1, 1, 1])) * 1

            self._k_grid = grid / (mesh - 1)
        else:
            _logger.warning("Unknown type {} for mesh, try ndarray.".format(
                type(mesh)))
Beispiel #5
0
    def get_ir_reciprocal_mesh(self, mesh=(10, 10, 10), shift=(0, 0, 0)):
        """
        k-point mesh of the Brillouin zone generated taken into account
        symmetry.The method returns the irreducible kpoints of the mesh
        and their weights

        Args:
            mesh (3x1 array): The number of kpoint for the mesh needed in
                each direction
            shift (3x1 array): A shift of the kpoint grid. For instance,
                Monkhorst-Pack is [0.5,0.5,0.5]
            is_time_reversal (bool): Set to True to impose time reversal
                symmetry.

        Returns:
            A list of irreducible kpoints and their weights as a list of
            tuples [(ir_kpoint, weight)], with ir_kpoint given
            in fractional coordinates
        """
        mapping, grid = spglib.get_ir_reciprocal_mesh(
            np.array(mesh), self._cell, is_shift=np.array(shift))

        results = []
        tmp_map = list(mapping)
        for i in np.unique(mapping):
            results.append((grid[i] / mesh, tmp_map.count(i)))
        return results
Beispiel #6
0
    def __init__(self, structure, mesh, is_shift, has_timrev):
        """

        Args:
            structure
            mesh
            is_shift
            has_timrev
        """
        import spglib as spg
        self.mesh = np.array(mesh)
        self.is_shift = is_shift
        self.has_timrev = has_timrev
        cell = (structure.lattice.matrix, structure.frac_coords, structure.atomic_numbers)

        mapping, self.grid = spg.get_ir_reciprocal_mesh(self.mesh, cell,
            is_shift=self.is_shift, is_time_reversal=self.has_timrev, symprec=_SPGLIB_SYMPREC)

        uniq, self.weights = np.unique(mapping, return_counts=True)
        self.weights = np.asarray(self.weights, dtype=np.float) / len(self.grid)
        self.nibz = len(uniq)
        self.kshift = [0., 0., 0.] if is_shift is None else 0.5 * np.asarray(is_shift)
        self.ibz = (self.grid[uniq] + self.kshift) / self.mesh
        self.bz = (self.grid + self.kshift) / self.mesh
        self.nbz = len(self.bz)

        # All k-points and mapping to ir-grid points.
        # FIXME This is slow.
        self.bz2ibz = np.empty(len(self.bz), dtype=np.int)
        for ik_bz, ir_gp_id in enumerate(mapping):
            inds = np.where(uniq == ir_gp_id)
            assert len(inds) == 1
            self.bz2ibz[ik_bz] = inds[0]
Beispiel #7
0
    def ir_kpts_map(self, symprec=1E-5):
        '''
        Get irreducible k-points in BZ and the mapping between the mesh points
        and the ir kpoints.
        '''

        import spglib

        cell = (
            self.atoms.cell,
            self.atoms.get_scaled_positions(),
            self.atoms.get_atomic_numbers()
        )
        # mapping: a map between the grid points and ir k-points in grid
        mapping, grid = spglib.get_ir_reciprocal_mesh(self.kmesh, cell,
                                                      is_shift=[0, 0, 0], symprec=symprec)

        # the k-point grid in the primitive cell
        # [-0.5, 0.5)
        self.kgrid_uc = grid
        ir_kpts = grid[np.unique(mapping)] / self.kmesh.astype(float)
        assert (ir_kpts.shape == self.ir_kpath.shape) and \
               (np.allclose(self.ir_kpath, ir_kpts)), \
            "Irreducible k-points generated by Spglib and VASP inconsistent!\n Try to reduce symprec, e.g. 1E-4."

        uniq_grid_index = np.unique(mapping)
        dump = np.zeros((grid.shape[0]), dtype=int)
        dump[uniq_grid_index] = np.arange(uniq_grid_index.size, dtype=int)
        # mapping between the grid points and the ir k-points
        self.grid_to_ir_map = dump[mapping]
Beispiel #8
0
    def test_get_ir_reciprocal_mesh(self):
        for i in range(len(self.cells)):
            ir_rec_mesh = get_ir_reciprocal_mesh(self.meshes[i], self.cells[i],
                                                 is_dense=False)
            (mapping_table, grid_address) = ir_rec_mesh
            # for gp, ga in zip(mapping_table, grid_address):
            #     print("%4d  %3d %3d %3d" % (gp, ga[0], ga[1], ga[2]))
            # print("")
            data = np.loadtxt(StringIO(result_ir_rec_mesh[i]), dtype='intc')
            np.testing.assert_equal(data[:, 0], mapping_table)
            np.testing.assert_equal(data[:, 1:4], grid_address)

            ir_rec_mesh = get_ir_reciprocal_mesh(self.meshes[i], self.cells[i],
                                                 is_dense=True)
            (mapping_table, grid_address) = ir_rec_mesh
            np.testing.assert_equal(data[:, 0], mapping_table)
            np.testing.assert_equal(data[:, 1:4], grid_address)
Beispiel #9
0
 def test_get_ir_reciprocal_mesh(self):
     for fname in self._filenames:
         cell = read_vasp("./data/%s" % fname)
         ir_rec_mesh = get_ir_reciprocal_mesh(self._mesh, cell)
         (mapping_table, grid_address) = ir_rec_mesh
         # for gp, ga in zip(mapping_table, grid_address):
         #     print("%4d  %3d %3d %3d" % (gp, ga[0], ga[1], ga[2]))
         data = np.loadtxt(StringIO(result_ir_rec_mesh), dtype='intc')
         self.assertTrue((data[:, 0] == mapping_table).all())
         self.assertTrue((data[:, 1:4] == grid_address).all())
Beispiel #10
0
    def test_get_ir_reciprocal_mesh(self):
        for i in range(len(self.cells)):
            ir_rec_mesh = get_ir_reciprocal_mesh(self.meshes[i],
                                                 self.cells[i],
                                                 is_dense=False)
            (mapping_table, grid_address) = ir_rec_mesh
            # for gp, ga in zip(mapping_table, grid_address):
            #     print("%4d  %3d %3d %3d" % (gp, ga[0], ga[1], ga[2]))
            # print("")
            data = np.loadtxt(StringIO(result_ir_rec_mesh[i]), dtype='intc')
            np.testing.assert_equal(data[:, 0], mapping_table)
            np.testing.assert_equal(data[:, 1:4], grid_address)

            ir_rec_mesh = get_ir_reciprocal_mesh(self.meshes[i],
                                                 self.cells[i],
                                                 is_dense=True)
            (mapping_table, grid_address) = ir_rec_mesh
            np.testing.assert_equal(data[:, 0], mapping_table)
            np.testing.assert_equal(data[:, 1:4], grid_address)
Beispiel #11
0
    def test_get_ir_reciprocal_mesh_Si_shift_111(self):
        ir_rec_mesh = get_ir_reciprocal_mesh([3, 3, 3],
                                             self.cells[2],
                                             is_shift=[1, 1, 1],
                                             is_dense=False)
        (mapping_table, grid_address) = ir_rec_mesh
        # for gp, ga in zip(mapping_table, grid_address):
        #     print("%4d  %3d %3d %3d" % (gp, ga[0], ga[1], ga[2]))
        # print("")
        data = np.loadtxt(StringIO(result_ir_rec_mesh_silicon), dtype='intc')
        np.testing.assert_equal(data[:, 0], mapping_table)
        np.testing.assert_equal(data[:, 1:4], grid_address)

        ir_rec_mesh = get_ir_reciprocal_mesh([3, 3, 3],
                                             self.cells[2],
                                             is_shift=[1, 1, 1],
                                             is_dense=True)
        (mapping_table, grid_address) = ir_rec_mesh
        np.testing.assert_equal(data[:, 0], mapping_table)
        np.testing.assert_equal(data[:, 1:4], grid_address)
Beispiel #12
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 #13
0
 def get_ir_reciprocal_mesh(
         self,
         mesh,
         is_shift=np.zeros(3, dtype="intc"),
         is_time_reversal=True,
 ):
     return spglib.get_ir_reciprocal_mesh(
         mesh=mesh,
         cell=self._get_spglib_cell(),
         is_shift=is_shift,
         is_time_reversal=is_time_reversal,
         symprec=self._symprec,
     )
Beispiel #14
0
  def _spg_grid(self, k_old, b_old, kmesh):

    shift_ind = np.argmin(
      np.linalg.norm(np.abs(k_old[:,:3]), axis=1)
    )
    shift = k_old[shift_ind]
    
    lattice = self.lattice
    positions = self.molecule.R_scale
    numbers = self.molecule.Z
    cell = (lattice, positions, numbers)
    mapping, grid = spglib.get_ir_reciprocal_mesh(
      kmesh, cell, is_shift=shift)
    kgrid = grid.astype(float) / kmesh
    kgrid_shifted = kgrid + np.array([1,1,1])

    groups_dict = {}
    for i in range(len(mapping)):
      k_id = mapping[i]
      if k_id not in groups_dict:
        groups_dict[k_id] = [i]
      else:
        groups_dict[k_id].append(i)
    groups = list(groups_dict.values())
    
    
    new_band = np.zeros([len(kgrid), len(b_old[0])])
    
    for i in range(len(k_old[:,:3])):
      k = k_old[i,:3]
      norm = []
      for k_permute in permutations(k):
        norm.append(np.linalg.norm(kgrid - k_permute, axis=1))
        norm.append(np.linalg.norm(kgrid + k_permute, axis=1))
      for k_permute in permutations(k):
        norm.append(np.linalg.norm(kgrid - np.abs(k_permute), axis=1))
        norm.append(np.linalg.norm(kgrid + np.abs(k_permute), axis=1))
      norm = np.min(np.stack(norm), axis=0)
      try:
        key = np.where(norm < 1E-3)[0][0]
      except Exception as e:
        msg = 'kpoint miss match with error message: ' + str(e)
        msg = msg + '\ncurrtent kpoint: ' + str(k)
        qtk.exit(msg)
      for g in groups:
        if key in g:
          for key_g in g:
            new_band[key_g] = b_old[i]

    return kgrid, new_band
 def test_get_ir_reciprocal_mesh(self):
     file_and_mesh = (["cubic/POSCAR-217", [4, 4, 4]],
                      ["hexagonal/POSCAR-182", [4, 4, 2]])
     i = 0
     for fname, mesh in file_and_mesh:
         cell = read_vasp("./data/%s" % fname)
         ir_rec_mesh = get_ir_reciprocal_mesh(mesh, cell)
         (mapping_table, grid_address) = ir_rec_mesh
         # for gp, ga in zip(mapping_table, grid_address):
         #     print("%4d  %3d %3d %3d" % (gp, ga[0], ga[1], ga[2]))
         # print("")
         data = np.loadtxt(StringIO(result_ir_rec_mesh[i]), dtype='intc')
         np.testing.assert_equal(data[:, 0], mapping_table)
         np.testing.assert_equal(data[:, 1:4], grid_address)
         i += 1
Beispiel #16
0
    def test_get_ir_reciprocal_mesh_distortion(self):
        j = 0
        for is_shift in ([0, 0, 0], [0, 1, 0]):
            for i, mesh in enumerate(([3, 4, 4], [3, 5, 1])):
                ir_rec_mesh = get_ir_reciprocal_mesh(mesh, self.cells[i],
                                                     is_shift=is_shift,
                                                     is_dense=False)
                (mapping_table, grid_address) = ir_rec_mesh
                # for gp, ga in zip(mapping_table, grid_address):
                #     print("%4d  %3d %3d %3d" % (gp, ga[0], ga[1], ga[2]))
                # print("")
                data = np.loadtxt(StringIO(result_ir_rec_mesh_distortion[j]),
                                  dtype='intc')
                np.testing.assert_equal(data[:, 0], mapping_table)
                np.testing.assert_equal(data[:, 1:4], grid_address)

                ir_rec_mesh = get_ir_reciprocal_mesh(mesh, self.cells[i],
                                                     is_shift=is_shift,
                                                     is_dense=True)
                (mapping_table, grid_address) = ir_rec_mesh
                np.testing.assert_equal(data[:, 0], mapping_table)
                np.testing.assert_equal(data[:, 1:4], grid_address)

                j += 1
Beispiel #17
0
    def _spg_grid(self, k_old, b_old, kmesh):

        shift_ind = np.argmin(np.linalg.norm(np.abs(k_old[:, :3]), axis=1))
        shift = k_old[shift_ind]

        lattice = self.lattice
        positions = self.molecule.R_scale
        numbers = self.molecule.Z
        cell = (lattice, positions, numbers)
        mapping, grid = spglib.get_ir_reciprocal_mesh(kmesh,
                                                      cell,
                                                      is_shift=shift)
        kgrid = grid.astype(float) / kmesh
        kgrid_shifted = kgrid + np.array([1, 1, 1])

        groups_dict = {}
        for i in range(len(mapping)):
            k_id = mapping[i]
            if k_id not in groups_dict:
                groups_dict[k_id] = [i]
            else:
                groups_dict[k_id].append(i)
        groups = list(groups_dict.values())

        new_band = np.zeros([len(kgrid), len(b_old[0])])

        for i in range(len(k_old[:, :3])):
            k = k_old[i, :3]
            norm = []
            for k_permute in permutations(k):
                norm.append(np.linalg.norm(kgrid - k_permute, axis=1))
                norm.append(np.linalg.norm(kgrid + k_permute, axis=1))
            for k_permute in permutations(k):
                norm.append(np.linalg.norm(kgrid - np.abs(k_permute), axis=1))
                norm.append(np.linalg.norm(kgrid + np.abs(k_permute), axis=1))
            norm = np.min(np.stack(norm), axis=0)
            try:
                key = np.where(norm < 1E-3)[0][0]
            except Exception as e:
                msg = 'kpoint miss match with error message: ' + str(e)
                msg = msg + '\ncurrtent kpoint: ' + str(k)
                qtk.exit(msg)
            for g in groups:
                if key in g:
                    for key_g in g:
                        new_band[key_g] = b_old[i]

        return kgrid, new_band
Beispiel #18
0
def get_ir_kpts(atoms, mesh):
    """
    Gamma-centered IR kpoints. mesh : [nk1,nk2,nk3].
    """
    lattice = atoms.get_cell()
    positions = atoms.get_scaled_positions()
    numbers = atoms.get_atomic_numbers()

    cell = (lattice, positions, numbers)
    mapping, grid = spglib.get_ir_reciprocal_mesh(mesh,
                                                  cell,
                                                  is_shift=[0, 0, 0])
    #print("%3d ->%3d %s" % (1, mapping[0], grid[0].astype(float) / mesh))
    #print("Number of ir-kpoints: %d" % len(np.unique(mapping)))
    #print(grid[np.unique(mapping)] / np.array(mesh, dtype=float))
    return grid[np.unique(mapping)] / np.array(mesh, dtype=float)
Beispiel #19
0
def test_expand_kpoints(symmetry_structure, shift, mesh):
    def _kpoints_to_first_bz(kp):
        """helper function to map k-points to 1st BZ"""
        kp = np.array(kp)
        kp = kp - np.round(kp)
        kp[kp.round(8) == -0.5] = 0.5
        return kp

    def _sort_kpoints(kp):
        """Helper function to put k-points in a consistent order"""
        kp = kp.round(8)
        sort_idx = np.lexsort((kp[:, 2], kp[:, 1], kp[:, 0]))
        return kp[sort_idx]

    # generate true k-points and IR k-points using spglib
    atoms = AseAtomsAdaptor.get_atoms(symmetry_structure)
    mapping, addresses = get_ir_reciprocal_mesh(mesh, atoms, is_shift=shift)
    true_kpoints = addresses / mesh + shift / (mesh * 2)
    true_kpoints = _kpoints_to_first_bz(true_kpoints)
    true_kpoints_sort = _sort_kpoints(true_kpoints)

    ir_mapping = np.unique(mapping, return_index=False)
    ir_kpoints = true_kpoints[ir_mapping]

    # try to expand the irreducible k-points back  to the full BZ
    full_kpoints, rots, _, _, op_mapping, kp_mapping = expand_kpoints(
        symmetry_structure, ir_kpoints, return_mapping=True
    )
    full_kpoints = _kpoints_to_first_bz(full_kpoints)
    full_kpoints_sort = _sort_kpoints(full_kpoints)

    # assert final k-points match the expected true k-points
    diff = np.linalg.norm(full_kpoints_sort - true_kpoints_sort, axis=1)
    assert np.max(diff) == 0

    # now ensure that the rotation mapping actually works
    rotated_kpoints = []
    for r, k in zip(op_mapping, kp_mapping):
        rotated_kpoints.append(np.dot(rots[r], ir_kpoints[k]))
    rotated_kpoints = _kpoints_to_first_bz(rotated_kpoints)
    rotated_kpoints_sort = _sort_kpoints(rotated_kpoints)

    # assert rotated k-points match the expected true k-points
    diff = np.linalg.norm(rotated_kpoints_sort - true_kpoints_sort, axis=1)
    assert np.max(diff) == 0
Beispiel #20
0
    def MPMesh(self, mesh, shift=[0, 0, 0], return_count=False):

        lattice = self.celldm2lattice()
        cell = (lattice, self.molecule.R_scale, self.molecule.Z)
        mapping, grid = spglib.get_ir_reciprocal_mesh(mesh,
                                                      cell,
                                                      is_shift=shift)

        unique, counts = np.unique(mapping, return_counts=True)
        weights = counts.astype(float) / counts.sum()

        kpts = grid[np.unique(mapping)] / np.array(mesh, dtype=float)

        if return_count:
            kpts = np.hstack([kpts, np.atleast_2d(counts).T])
        else:
            kpts = np.hstack([kpts, np.atleast_2d(weights).T])

        return kpts
    def irreducible_kpoints(
        self,
        num_kpt_list: List[int],
        kpt_shift: List[float]  # vasp convention
    ) -> List[Tuple[List[float], int]]:
        # evaluated at a given Brillouin zone.
        mapping, integer_grid_points = spglib.get_ir_reciprocal_mesh(
            mesh=num_kpt_list,
            cell=self.cell,
            is_shift=np.array(kpt_shift) * 2,
            is_time_reversal=self.time_reversal,
            symprec=self.symprec)

        results = []
        shift_in_integer_grid = np.array(kpt_shift)
        for repr_index, count in zip(*np.unique(mapping, return_counts=True)):
            integer_grid_point = \
                integer_grid_points[repr_index] + shift_in_integer_grid
            normalized_grid_point = integer_grid_point / num_kpt_list
            results.append((normalized_grid_point.tolist(), count))

        return results  # [(irreducible kpoint in fractional coords, weight)]
Beispiel #22
0
 def test_get_ir_reciprocal_mesh_distortion(self):
     file_and_mesh = ([
         os.path.join(data_dir, "data", "cubic", "POSCAR-217"), [3, 4, 4]
     ], [
         os.path.join(data_dir, "data", "hexagonal", "POSCAR-182"),
         [3, 5, 1]
     ])
     i = 0
     for is_shift in ([0, 0, 0], [0, 1, 0]):
         for fname, mesh in file_and_mesh:
             cell = read_vasp(fname)
             ir_rec_mesh = get_ir_reciprocal_mesh(mesh,
                                                  cell,
                                                  is_shift=is_shift)
             (mapping_table, grid_address) = ir_rec_mesh
             # for gp, ga in zip(mapping_table, grid_address):
             #     print("%4d  %3d %3d %3d" % (gp, ga[0], ga[1], ga[2]))
             # print("")
             data = np.loadtxt(StringIO(result_ir_rec_mesh_distortion[i]),
                               dtype='intc')
             np.testing.assert_equal(data[:, 0], mapping_table)
             np.testing.assert_equal(data[:, 1:4], grid_address)
             i += 1
Beispiel #23
0
def ir_kpts(atoms, mp_grid, is_shift=[0, 0, 0], verbose=True, ir=True):
    """
    generate kpoints for structure
    Parameters:
    ------------------
    atoms: ase.Atoms
      structure
    mp_grid: [nk1,nk2,nk3]
    is_shift: shift of k points. default is Gamma centered.
    ir: bool
    Irreducible or not.
    """
    cell = (atoms.get_cell(), atoms.get_scaled_positions(),
            atoms.get_atomic_numbers())
    # print(spglib.get_spacegroup(cell, symprec=1e-5))
    mesh = mp_grid
    # Gamma centre mesh
    mapping, grid = spglib.get_ir_reciprocal_mesh(mesh,
                                                  cell,
                                                  is_shift=is_shift)
    if not ir:
        return (np.array(grid).astype(float) + np.asarray(is_shift) /
                2.0) / mesh, [1.0 / len(mapping)] * len(mapping)
    # 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))
    cnt = Counter(mapping)
    ids = list(cnt.keys())
    weight = list(cnt.values())
    weight = np.array(weight) * 1.0 / sum(weight)
    ird_kpts = [(grid[id].astype(float) + np.asarray(is_shift) / 2.0) / mesh
                for id in ids]

    # Irreducible k-points
    # print("Number of ir-kpoints: %d" % len(np.unique(mapping)))
    # print(grid[np.unique(mapping)] / np.array(mesh, dtype=float))
    return ird_kpts, weight
Beispiel #24
0
    def reciprocalGrid(self):
        if isinstance(self._pointDensity, type(None)):
            raise TypeError(
                "No meshgrid is defined, use meshgrid(pointDensity) to set meshgrid."
            )
        else:
            gridZone = np.max(np.abs(self.cell.brillouinZone), axis=0)
            gridPoints = np.round(gridZone * self._pointDensity).astype(int)
            for i in range(len(gridPoints)):
                if (gridPoints[i] % 2 == 0):
                    gridPoints[i] += 1

            mapping, grid = spg.get_ir_reciprocal_mesh(
                gridPoints, (self.cell.lattice, self.cell.getAtomPositons(),
                             self.cell.getAtomNumbers()),
                is_shift=[0, 0, 0])
            k_grid = grid[np.unique(mapping)] / (gridPoints - 1)

            k_list = []
            for i, map_id in enumerate(mapping[np.unique(mapping)]):
                k_list.append(
                    (grid[mapping == map_id] / (self._pointDensity - 1)
                     ).tolist())  #np.dot(,self.cell.brillouinZone)
            return k_grid, k_list
Beispiel #25
0
print("  Number of symmetry operations of silicon conventional")
print("  unit cell is %d (192)." % len(symmetry['rotations']))
show_symmetry(symmetry)
print('')

reduced_lattice = spglib.niggli_reduce(niggli_lattice)
print("[niggli_reduce]")
print("  Original lattice")
show_lattice(niggli_lattice)
print("  Reduced lattice")
show_lattice(reduced_lattice)
print('')


mapping, grid = spglib.get_ir_reciprocal_mesh([11, 11, 11],
                                              silicon_prim,
                                              is_shift=[0, 0, 0])
num_ir_kpt = len(np.unique(mapping))
print("[get_ir_reciprocal_mesh]")
print("  Number of irreducible k-points of primitive silicon with")
print("  11x11x11 Monkhorst-Pack mesh is %d (56)." % num_ir_kpt)
print('')

mapping, grid = spglib.get_ir_reciprocal_mesh([8, 8, 8],
                                              rutile,
                                              is_shift=[1, 1, 1])
num_ir_kpt = len(np.unique(mapping))
print("[get_ir_reciprocal_mesh]")
print("  Number of irreducible k-points of Rutile with")
print("  8x8x8 Monkhorst-Pack mesh is %d (40)." % num_ir_kpt)
print('')
Beispiel #26
0
    def write_KPOINTS(
        POSCAR_input: str = "POSCAR",
        KPOINTS_output="KPOINTS.lobster",
        reciprocal_density: int = 100,
        isym: int = -1,
        from_grid: bool = False,
        input_grid: list = [5, 5, 5],
        line_mode: bool = True,
        kpoints_line_density: int = 20,
        symprec: float = 0.01,
    ):
        """
        writes a KPOINT file for lobster (only ISYM=-1 and ISYM=0 are possible), grids are gamma centered
        Args:
            POSCAR_input (str): path to POSCAR
            KPOINTS_output (str): path to output KPOINTS
            reciprocal_density (int): Grid density
            isym (int): either -1 or 0. Current Lobster versions only allow -1.
            from_grid (bool): If True KPOINTS will be generated with the help of a grid given in input_grid. Otherwise,
                they will be generated from the reciprocal_density
            input_grid (list): grid to generate the KPOINTS file
            line_mode (bool): If True, band structure will be generated
            kpoints_line_density (int): density of the lines in the band structure
            symprec (float): precision to determine symmetry
        """
        structure = Structure.from_file(POSCAR_input)
        if not from_grid:
            kpointgrid = Kpoints.automatic_density_by_vol(
                structure, reciprocal_density).kpts
            mesh = kpointgrid[0]
        else:
            mesh = input_grid

        # The following code is taken from: SpacegroupAnalyzer
        # we need to switch off symmetry here
        latt = structure.lattice.matrix
        positions = structure.frac_coords
        unique_species = []  # type: List[Any]
        zs = []
        magmoms = []

        for species, g in itertools.groupby(structure,
                                            key=lambda s: s.species):
            if species in unique_species:
                ind = unique_species.index(species)
                zs.extend([ind + 1] * len(tuple(g)))
            else:
                unique_species.append(species)
                zs.extend([len(unique_species)] * len(tuple(g)))

        for site in structure:
            if hasattr(site, "magmom"):
                magmoms.append(site.magmom)
            elif site.is_ordered and hasattr(site.specie, "spin"):
                magmoms.append(site.specie.spin)
            else:
                magmoms.append(0)

        # For now, we are setting magmom to zero. (Taken from INCAR class)
        cell = latt, positions, zs, magmoms
        # TODO: what about this shift?
        mapping, grid = spglib.get_ir_reciprocal_mesh(mesh,
                                                      cell,
                                                      is_shift=[0, 0, 0])

        # exit()
        # get the kpoints for the grid
        if isym == -1:
            kpts = []
            weights = []
            all_labels = []
            for gp in grid:
                kpts.append(gp.astype(float) / mesh)
                weights.append(float(1))
                all_labels.append("")
        elif isym == 0:
            # time reversal symmetry: k and -k are equivalent
            kpts = []
            weights = []
            all_labels = []
            newlist = [list(gp) for gp in list(grid)]
            mapping = []
            for gp in newlist:
                minus_gp = [-k for k in gp]
                if minus_gp in newlist and minus_gp not in [[0, 0, 0]]:
                    mapping.append(newlist.index(minus_gp))
                else:
                    mapping.append(newlist.index(gp))

            for igp, gp in enumerate(newlist):
                if mapping[igp] > igp:
                    kpts.append(np.array(gp).astype(float) / mesh)
                    weights.append(float(2))
                    all_labels.append("")
                elif mapping[igp] == igp:
                    kpts.append(np.array(gp).astype(float) / mesh)
                    weights.append(float(1))
                    all_labels.append("")

        else:
            ValueError("Only isym=-1 and isym=0 are allowed.")
        # line mode
        if line_mode:
            kpath = HighSymmKpath(structure, symprec=symprec)
            if not np.allclose(kpath.prim.lattice.matrix,
                               structure.lattice.matrix):
                raise ValueError(
                    "You are not using the standard primitive cell. The k-path is not correct. Please generate a "
                    "standard primitive cell first.")

            frac_k_points, labels = kpath.get_kpoints(
                line_density=kpoints_line_density, coords_are_cartesian=False)

            for k, f in enumerate(frac_k_points):
                kpts.append(f)
                weights.append(0.0)
                all_labels.append(labels[k])
        if isym == -1:
            comment = ("ISYM=-1, grid: " +
                       str(mesh) if not line_mode else "ISYM=-1, grid: " +
                       str(mesh) + " plus kpoint path")
        elif isym == 0:
            comment = ("ISYM=0, grid: " +
                       str(mesh) if not line_mode else "ISYM=0, grid: " +
                       str(mesh) + " plus kpoint path")

        KpointObject = Kpoints(
            comment=comment,
            style=Kpoints.supported_modes.Reciprocal,
            num_kpts=len(kpts),
            kpts=kpts,
            kpts_weights=weights,
            labels=all_labels,
        )

        KpointObject.write_file(filename=KPOINTS_output)
    def create_phonon_input(self, scf_file, phonon_config_file):

        with open(phonon_config_file, 'r') as inf:
            phonon_config = literal_eval(inf.read())

        self.input_data['control'].update({'calculation': 'scf'})
        #change the position of psuedo_dir because the phonon job will be running in the lower directory
        self.input_data['control'].update({
            'pseudo_dir':
            os.path.join('../', self.input_data['control']['pseudo_dir'])
        })
        scf = read(scf_file, format='espresso-in')
        calc = Espresso(input_data=self.input_data,
                        psuedopotentials=self.pseudopotentials,
                        kpts=phonon_config['nscfkpts'],
                        label=self.config['formula'] + '-scf')
        calc.write_input(scf)
        scf_file_name = self.config['formula'] + "-scf.pwi"
        self.rename_psuedo(scf_file_name)

        #obtain the number of irreducible q-point
        #convert necessary information from ASE Atoms object
        lattice = list(scf.get_cell())
        #to use spglib, need to get scaled position in ASE!
        positions = scf.get_scaled_positions()
        numbers = scf.get_atomic_numbers()
        cell = (lattice, positions, numbers)

        print("symmetry of input structure:" +
              str(spglib.get_spacegroup(cell, symprec=1e-5)))
        mapping, grid = spglib.get_ir_reciprocal_mesh(phonon_config['nphmesh'],
                                                      cell,
                                                      is_shift=[0, 0, 0])
        irq = len(np.unique(mapping))
        print("number of irreducible q-point:" + str(irq))

        # split into several jobs
        # loadbarance with napsack method
        loadmin = []
        loadmax = []

        work = int(irq / phonon_config['njobs'])
        work2 = irq % phonon_config['njobs']
        for i in range(phonon_config['njobs']):
            minval = 1 + i * work + min(i, work2)
            loadmin.append(minval)
            loadmax.append(minval + work - 1)
            if (work2 > i):
                loadmax[i] = loadmax[i] + 1

        # making directory for each split job

        dirlist = []

        for i in range(phonon_config['njobs']):
            dirname = "phjob_" + str(i)
            dirlist.append(dirname)
            try:
                os.mkdir(dirname)
            except OSError:
                print('directry already exist')
            shutil.copy2(scf_file_name, dirname)

            os.chdir(dirname)
            phononInput = self.config['formula'] + ".phonon.in"

            fp = open(phononInput, "w")
            fp.write(self.config['formula'] + " phonon \n")
            fp.write('&inputph \n')
            fp.write("outdir=" + "\'" + self.input_data['control']['outdir'] +
                     "\' \n")
            fp.write("tr2_ph=" + str(phonon_config['tr2_ph']) + "\n")
            fp.write("fildvscf=" + "\'" + phonon_config['fildvscf'] + "\' \n")
            fp.write('alpha_mix(1)=0.2 \n')
            fp.write("trans=" + "." + str(phonon_config['trans']).lower() +
                     ". \n")
            fp.write("ldisp=" + "." + str(phonon_config['ldisp']).lower() +
                     ". \n")
            fp.write("epsil=" + "." + str(phonon_config['epsil']).lower() +
                     ". \n")
            #avoid symmetry error in hexagonal system
            fp.write("search_sym=" + "." +
                     str(phonon_config['search_sym']).lower() + ". \n")
            fp.write('nq1=' + str(phonon_config["nphmesh"][0]) + ',nq2=' +
                     str(phonon_config["nphmesh"][1]) + ',nq3=' +
                     str(phonon_config["nphmesh"][2]) + '\n')

            fp.write('start_q=' + str(loadmin[i]) + ' \n')
            fp.write('last_q=' + str(loadmax[i]) + ' \n')

            fp.write('/\n')
            fp.close()
            # generate run script
            with open("phrun.sh", "w") as f:
                f.write(self.PBS_header + '\n')
                # scf
                f.write(self.config['mpicommand'] + " " + self.config['path'] +
                        "/pw.x " + self.config['qeoption'] + " -input " +
                        scf_file_name + " > scf.out \n")
                # then band
                f.write(self.config['mpicommand'] + " " + self.config['path'] +
                        "/ph.x " + self.config['qeoption'] + " -input " +
                        phononInput + " > ph.out \n")

            os.chdir('../')

        # bash script for running job at once

        fallrun = open("runall.sh", "w")
        fallrun.write("#!/bin/sh \n")

        for i in dirlist:
            fallrun.write("cd " + i + "\n")
            fallrun.write(self.config['pbscommand'] + "  phrun.sh \n")
            fallrun.write("cd ../ \n")

        fallrun.close()

        # output directry list for post process purpose
        fdirlist = open("directoryList.txt", "w")

        for i in dirlist:
            fdirlist.write(i + "\n")

        fdirlist.close()
import spglib

lattice = [[2.9306368570142554, 0.0000000000000000, 0.0000000000000000],
           [-1.4653184285071277, 2.5380059674413284, 0.0000000000000000],
           [0.0000000000000000, 0.0000000000000000, 4.6381396667889572]]
numbers = [1, 1]

points = [[0.6666666666666665, 0.3333333333333333, 0.7500000000000000],
          [0.3333333333333334, 0.6666666666666667, 0.2500000000000000]]

cell = (lattice, points, numbers)

print("-----------")
print("Using 3x3x1 mesh")
mesh = [3, 3, 1]
mapping, grid = spglib.get_ir_reciprocal_mesh(mesh, cell, is_shift=[0, 0, 0])
for m, g in zip(mapping, grid):
    print(("%2d " * 4) % (g[0], g[1], g[2], m))

print("-----------")
print("Using 3x5x1 mesh")
mesh = [3, 5, 1]
mapping, grid = spglib.get_ir_reciprocal_mesh(mesh, cell, is_shift=[0, 0, 0])
for m, g in zip(mapping, grid):
    print(("%2d " * 4) % (g[0], g[1], g[2], m))

print("-----------")
print("Using 15x15x1 mesh")
mesh = [15, 15, 1]
mapping, grid = spglib.get_ir_reciprocal_mesh(mesh, cell, is_shift=[0, 0, 0])
Beispiel #29
0
def k_irr_BZ():
    '''
    Calculates the k-vectors of the irreducable/full BZ:qdel 
    '''
    MAT = np.zeros((3, 3))  # Matrix of reciprocal basis vectors
    MAT[:, 0] = np.array([-1., 1., 1.]) * 2. * np.pi / a
    MAT[:, 1] = np.array([1., -1., 1.]) * 2. * np.pi / a
    MAT[:, 2] = np.array([1., 1., -1.]) * 2. * np.pi / a

    lattice = np.array([
        [0.0, 0.5, 0.5],  # basis vectors of fcc lattice
        [0.5, 0.0, 0.5],
        [0.5, 0.5, 0.0]
    ]) * a

    positions = [
        [0.0, 0.0, 0.0],  # atomic basis in fractional coordinates
        [0.5, 0.0, 0.0],
        [0.0, 0.5, 0.0],
        [0.0, 0.0, 0.5]
    ]

    numbers = [1, 2, 3, 4]

    cell = (lattice, positions, numbers)

    print('spacegroup: ' + str(spglib.get_spacegroup(cell, symprec=1e-5)))
    print(spglib.get_symmetry(cell, symprec=1e-5))

    # caclulatio of irr. BZ vectors + weights
    mapping, grid = spglib.get_ir_reciprocal_mesh(mesh,
                                                  cell,
                                                  is_shift=[0, 0, 0])
    MAT_help = grid[np.unique(mapping)] / np.array(mesh, dtype=float)
    MAT_irr_BZ = np.zeros((np.size(MAT_help[:, 0]), 3))
    for k in range(1, np.size(MAT_help[:, 0])):
        MAT_irr_BZ[k, :] = MAT[:, 0] * MAT_help[k, 0] + MAT[:, 1] * MAT_help[
            k, 1] + MAT[:, 2] * MAT_help[
                k, 2]  # transform from fractional to cartesian coordinates

    print("Number of kpoints: %d (irr BZ)" % len(np.unique(mapping)))
    num_kpoints = np.size(MAT_irr_BZ[:, 0])

    weights = (np.unique(mapping, return_counts=True)[1])
    print("Number of kpoints: %d (full BZ, check of weights)" % weights.sum())

    #for i, (ir_gp_id, gp) in enumerate(zip(mapping, grid)):
    #    print("%3d ->%3d %s" % (i, ir_gp_id, gp.astype(float) / mesh))
    #print(grid[np.unique(mapping)]/np.array(mesh, dtype=float))
    #print(np.unique(mapping,return_counts=True))

    # caclulatio of full BZ vectors (weights = 1)
    MAT_BZ_full = np.array(grid, dtype=float)
    for k in range(1, np.size(MAT_BZ_full[:, 0])):
        MAT_BZ_full[
            k, :] = MAT[:, 0] * MAT_BZ_full[k, 0] + MAT[:, 1] * MAT_BZ_full[
                k, 1] + MAT[:, 2] * MAT_BZ_full[k, 2]
    print("Number of kpoints: %d (full BZ)" % np.size(MAT_BZ_full[:, 0]))

    file = open('k_BZ_irr.txt', 'w')
    for i in range(num_kpoints):
        for j in range(3):
            file.write("%s " % MAT_irr_BZ[i][j])
        file.write("\n")
    file.close()

    file = open('k_weights_irr.txt', 'w')
    for i in range(num_kpoints):
        file.write("%s " % (weights[i] * 1.0))
        file.write("\n")
    file.close()

    file = open('k_BZ_full.txt', 'w')
    for i in range(np.size(MAT_BZ_full[:, 0])):
        for j in range(3):
            file.write("%s " % (MAT_BZ_full[i][j] / mesh[0]))
        file.write("\n")
    file.close()

    file = open('k_weights_full.txt', 'w')
    for i in range(np.size(MAT_BZ_full[:, 0])):
        file.write("%s " % 1.0)
        file.write("\n")
    file.close()
    return MAT_irr_BZ, MAT_BZ_full / (mesh[0] * 1.0)
Beispiel #30
0
    def create_kmesh(  # pylint: disable=too-many-locals # noqa: MC0001
            self,
            ksampling=None,
            shift=np.array([0, 0, 0], dtype='intc'),
            halfscale=True,
            borderless=False):
        """
        Returns the k point mesh.

        Parameters
        ----------
        ksampling: ndarray, optional
            | Dimension: (3)

            Contains the k - point sampling points along each direction.
            If not supplied the `ksampling` of the current `Lattice()`
            object is used.
        shift: ndarray, optional
            | Dimension: (3)

            Contains the shift for the k - point mesh generation.
            If not supplied the default is set to[0.0, 0.0, 0.0]
        halfscale: boolean
            Selects if the BZ mesh should go from -0.5 to 0.5 or
            -1.0 to 1.0. If not supplied, the default is set to True.
        borderless: boolean
            Selects if the BZ border points should be included in
            the mesh generation. True selects borderless, e.g.
            -0.5, 0.5 etc. are excluded.

        Returns
        -------
        mapping_bz_to_ibz: ndarray
            | Dimension: (N, 3)

            Contains a mapping table such that it is possible to go
            from the BZ to the IBZ mesh. Stored in the current
            `Lattice()` object.
        mapping_ibz_to_bz: ndarray
            | Dimension: (M, 3)

            Contains a mapping table such that it is possible to go
            from the IBZ to the BZ mesh. Stored in the current
            `Lattice()` object.
        kmesh: ndarray
            | Dimension: (N, 3)

            The k - point mesh in the full BZ for N sampling points
            determined by the multiplication of the content of
            `ksampling`. Stored in the current `Lattice()` object.
        kmesh_ibz: ndarray
            | Dimension: (M, 3)

            The k - point mesh in the irreducible BZ. The number of
            points M is dependent on the symmetry. Usually M < N.
            Stored in the current `Lattice()` object.
        ksampling: ndarray
            | Dimension: (3)

            The full BZ k - point sampling in each direction.
            Stored in the current `Lattice()` object.

        Notes
        -----
        This routines use spglib, an excellent tool written by A. Togo.

        """

        # set logger
        logger = logging.getLogger(sys._getframe().f_code.co_name)  # pylint: disable=protected-access
        logger.debug("Running create_kmesh.")

        if ksampling is None:
            try:
                ksampling = self.ksampling
            except AttributeError:
                logger.error("No ksampling is set. Exiting.")
                sys.exit(1)
        # check for gamma only
        if self.param.gamma_center:
            # up even ksampling grid to odd number
            if utils.is_even(ksampling[0]):
                ksampling[0] = ksampling[0] + 1
            if utils.is_even(ksampling[1]):
                ksampling[1] = ksampling[1] + 1
            if utils.is_even(ksampling[2]):
                ksampling[2] = ksampling[2] + 1
        else:
            logger.info(
                "Please set gamma centered to True and supply/generate "
                "a gamma centered grid.")
            sys.exit(1)
        # make sure ksampling have correct dtype
        ksampling = np.ascontiguousarray(ksampling, dtype='intc')
        # same for the number of kpoints
        k = np.zeros((np.prod(ksampling), 3), dtype="intc")

        if not self.param.work_on_full_grid:
            # need the IBZ and the BZ-IBZ mappings
            # and the mappings
            spg_mapping = np.zeros(np.prod(ksampling), dtype="intc")
            logger.info(
                "Calling Spglib to set up the k-point grid with a "
                "sampling of %sx%sx%s.", str(ksampling[0]), str(ksampling[1]),
                str(ksampling[2]))
            if self.borderless:
                borderless = True
            # first create required tuple for Spglib
            cell = (self.unitcell, self.positions, self.species)
            # get the spacegroup
            self.spacegroup = spglib.get_spacegroup(cell,
                                                    symprec=self.param.symprec)
            # get the k-point mesh
            spg_mapping, k = spglib.get_ir_reciprocal_mesh(ksampling,
                                                           cell,
                                                           is_shift=shift)
            logger.info(
                "Spglib detected the symmetry %s with symprec set to %s",
                self.spacegroup, str(self.param.symprec))
            # build array for IBZ
            k_ired = k[np.unique(spg_mapping, return_index=True)[1]]
            # sort mesh
            k_sort_ired = utils.fetch_sorting_indexes(k_ired)
            k_sort_full = utils.fetch_sorting_indexes(k)
            kmesh_ired = k_ired[k_sort_ired]
            kmesh_full = k[k_sort_full]

            # store original SPGLIB mesh for use later
            # (e.g. tetrahedron method)
            self.spg_kmesh = k[k_sort_full]

            shuffle = np.zeros(spg_mapping.shape[0], dtype=np.intc)
            for index, value in enumerate(spg_mapping):
                shuffle[index] = np.where(k_sort_full == value)[0][0]
            # build ired and sort
            k_ired = kmesh_full[shuffle[np.sort(
                np.unique(shuffle, return_index=True)[1])]]
            k_sort_ired = utils.fetch_sorting_indexes(k_ired)
            k_ired = k_ired[k_sort_ired]

            mapping_ibz_to_bz = shuffle[k_sort_full]
            mapping_bz_to_ibz = np.zeros(mapping_ibz_to_bz.size, dtype=np.intc)
            for index, ibz_point in enumerate(np.unique(mapping_ibz_to_bz)):
                mask = np.in1d(mapping_ibz_to_bz, ibz_point)
                np.copyto(mapping_bz_to_ibz, index, where=mask)

            # scale the grid from integer to float (consider to postpone this
            # in the future...e.g. integers are nice because test for uniqueness
            # is exact etc.)
            if borderless:
                scaling = 1.0 / ksampling
                kmesh_full = kmesh_full * scaling
                kmesh_ired = kmesh_ired * scaling
            else:
                scaling = np.floor(ksampling / 2.0)
                kmesh_full = kmesh_full / scaling
                kmesh_ired = kmesh_ired / scaling
                if halfscale:
                    kmesh_full = 0.5 * kmesh_full
                    kmesh_ired = 0.5 * kmesh_ired

            # calculate ibz weights
            dummy, ibz_weights = np.unique(mapping_bz_to_ibz,
                                           return_counts=True)

        else:
            # here we only generate a full grid without fetching the IBZ or
            # related parameters
            logger.info(
                "Setting up the full k-point grid with a sampling "
                "of %sx%sx%s. No irreducible grid is determined.",
                str(ksampling[0]), str(ksampling[1]), str(ksampling[2]))
            if borderless:
                scaling = 1.0 / ksampling
                # in the future this needs to either be left or right adjusted
                # for non-gamma centered grids (right now this is not
                # supported)
                bzlimits = np.floor(ksampling / 2.0)
                k1 = np.linspace(-bzlimits[0], bzlimits[0], num=ksampling[0])
                k2 = np.linspace(-bzlimits[1], bzlimits[1], num=ksampling[1])
                k3 = np.linspace(-bzlimits[2], bzlimits[2], num=ksampling[2])
            else:
                logging.error(
                    "Inclusion of borders for the full grid method is"
                    "not supported. Exiting.")
                sys.exit(1)
            kx, ky, kz = np.array(np.meshgrid(k1, k2, k3, indexing='ij'))
            kmesh_full = np.array([kx.flatten(), ky.flatten(), kz.flatten()]).T
            # scale the grid
            kmesh_full = kmesh_full * scaling
            # set the IBZ and IBZ-BZ mapping to None as we now work on the full
            # grid
            kmesh_ired = None
            mapping_ibz_to_bz = None
            mapping_bz_to_ibz = None
            ibz_weights = None
        self.kmesh = kmesh_full
        self.kmesh_ired = kmesh_ired
        self.mapping_ibz_to_bz = np.unique(mapping_ibz_to_bz)
        self.mapping_bz_to_ibz = mapping_bz_to_ibz
        self.ksampling = ksampling
        self.ibz_weights = ibz_weights
Beispiel #31
0
print("  Number of symmetry operations of silicon conventional")
print("  unit cell is %d (192)." % len(symmetry['rotations']))
show_symmetry(symmetry)
print('')

reduced_lattice = spglib.niggli_reduce(niggli_lattice)
print("[niggli_reduce]")
print("  Original lattice")
show_lattice(niggli_lattice)
print("  Reduced lattice")
show_lattice(reduced_lattice)
print('')


mapping, grid = spglib.get_ir_reciprocal_mesh([11, 11, 11],
                                              silicon_prim,
                                              is_shift=[0, 0, 0])
num_ir_kpt = len(np.unique(mapping))
print("[get_ir_reciprocal_mesh]")
print("  Number of irreducible k-points of primitive silicon with")
print("  11x11x11 Monkhorst-Pack mesh is %d (56)." % num_ir_kpt)
print('')

mapping, grid = spglib.get_ir_reciprocal_mesh([8, 8, 8],
                                              rutile,
                                              is_shift=[1, 1, 1])
num_ir_kpt = len(np.unique(mapping))
print("[get_ir_reciprocal_mesh]")
print("  Number of irreducible k-points of Rutile with")
print("  8x8x8 Monkhorst-Pack mesh is %d (40)." % num_ir_kpt)
print('')
Beispiel #32
0
def k_irr_BZ():    
    '''
    Calculates the k-vectors of the irreducable/full BZ
    '''
    
    mesh = [Nmesh, Nmesh, 1]    
    lattice = np.array([A1, A2, A3])                                           #(lconst=1)             
    positions = [[0.0, 0.0, 0.0]]    
    numbers= [1]             
             
    cell = (lattice, positions, numbers)
    
    print('spacegroup: ' +str(spglib.get_spacegroup(cell, symprec=1e-5)))
    #print(spglib.get_symmetry(cell, symprec=1e-5))    
    
    # caclulatio of irr. BZ vectors + weights
    mapping, grid = spglib.get_ir_reciprocal_mesh(mesh, cell, is_shift=[0.,0.,0.])
    MAT_help = grid[np.unique(mapping)]/np.array(mesh, dtype=float)
    MAT_irr_BZ = np.zeros((np.size(MAT_help[:,0]),3))       
    for k in range(1,np.size(MAT_help[:,0])):
        MAT_irr_BZ[k,:] = B1*MAT_help[k,0] + B2*MAT_help[k,1] + B3*MAT_help[k,2] # transform from fractional to cartesian coordinates

    print("Number of kpoints: %d (irr BZ)" % len(np.unique(mapping)))
    num_kpoints = np.size(MAT_irr_BZ[:,0])

    weights = (np.unique(mapping,return_counts=True)[1])
    print("Number of kpoints: %d (full BZ, check of weights)" % weights.sum())           
           
    #for i, (ir_gp_id, gp) in enumerate(zip(mapping, grid)):
    #    print("%3d ->%3d %s" % (i, ir_gp_id, gp.astype(float) / mesh))
    #print(grid[np.unique(mapping)]/np.array(mesh, dtype=float))    
    #print(np.unique(mapping,return_counts=True))      
    
    # caclulatio of full BZ vectors (weights = 1) 
    MAT_BZ_full = np.array(grid, dtype=float)
    for k in range(1,np.size(MAT_BZ_full[:,0])):
        MAT_BZ_full[k,:] = B1*MAT_BZ_full[k,0] + B2*MAT_BZ_full[k,1] + B3*MAT_BZ_full[k,2]# + 0.5*(B1*mesh[0] + B2*mesh[0])
    print("Number of kpoints: %d (full BZ)" % np.size(MAT_BZ_full[:,0]))
    
    file = open('k_BZ_irr.dat','w')
    for i in range(num_kpoints):
        for j in range(3):
            file.write("%s " % (MAT_irr_BZ[i][j]/lconst))
        file.write("\n")    
    file.close()
    
    file = open('k_weights_irr.dat','w')
    for i in range(num_kpoints):
        file.write("%s " % (weights[i]*1.0))
        file.write("\n")    
    file.close()
    
    file = open('k_BZ_full.dat','w')
    for i in range(np.size(MAT_BZ_full[:,0])):
        for j in range(3):
            file.write("%s " % (MAT_BZ_full[i][j]/(mesh[0]*lconst)))
        file.write("\n")    
    file.close()
    
    file = open('k_weights_full.dat','w')
    for i in range(np.size(MAT_BZ_full[:,0])):
        file.write("%s " % 1.0)
        file.write("\n")    
    file.close()
    return MAT_irr_BZ/lconst, MAT_BZ_full/(1.0*mesh[0]*lconst)               # in 1/(AA)   
Beispiel #33
0
 def __init__(self,astruct,mesh,evals,fermi_energy):
     import spglib,numpy
     cell=astruct_to_cell(astruct)
     self.lattice=cell[0]
     #celltmp=[ a if a!=float('inf') else 1.0 for a in astruct['cell']]
     #self.lattice=numpy.diag(celltmp)
     #print 'lattice',self.lattice
     #pos=[ [ a/b if b!=float('inf') else 0.0 for a,b in zip(at.values()[0], celltmp)]for at in astruct['positions']]
     #atoms=[ at.keys()[0] for at in astruct['positions']]
     #ianames,iatype=numpy.unique(atoms,return_inverse=True) #[1,]*4+[2,]*4 #we should write a function for the iatype
     #print 'iatype', iatype
     #cell=(self.lattice,pos,iatype)
     safe_print('spacegroup',spglib.get_spacegroup(cell, symprec=1e-5))
     #then define the pathes and special points
     import ase.dft.kpoints as ase
     #we should adapt the 'cubic'
     cell_tmp=astruct['cell']
     #print 'cell',cell_tmp,numpy.allclose(cell_tmp,[cell_tmp[0],]*len(cell_tmp))
     if numpy.allclose(cell_tmp,[cell_tmp[0],]*len(cell_tmp)):
         lattice_string='cubic'
     else:
         lattice_string='orthorhombic'
     safe_print('Lattice found:',lattice_string)
     self.special_points=ase.get_special_points(lattice_string, self.lattice, eps=0.0001)
     self.special_paths=ase.parse_path_string(ase.special_paths[lattice_string])
     self.fermi_energy=fermi_energy
     #dataset = spglib.get_symmetry_dataset(cell, symprec=1e-3)
     #print dataset
     #the shift has also to be put if present
     mapping, grid = spglib.get_ir_reciprocal_mesh(mesh, cell, is_shift=[0, 0, 0])
     lookup=[]
     for ikpt in numpy.unique(mapping):
         ltmp=[]
         for ind, (m, g) in enumerate(zip(mapping, grid)):
             if m==ikpt:
                 ltmp.append((g,ind))
         lookup.append(ltmp)
     safe_print('irreductible k-points',len(lookup))
     #print 'mapping',mapping
     #print 'grid',len(grid),numpy.max(grid)
     coords=numpy.array(grid, dtype = numpy.float)/mesh
     #print 'coords',coords
     #print 'shape',coords.shape
     #print grid #[ x+mesh[0]*y+mesh[0]*mesh[1]*z for x,y,z in grid]
     #brillouin zone
     kp=numpy.array([ k.kpt for k in evals])
     ourkpt=numpy.rint(kp*(numpy.array(mesh))).astype(int)
     #print ourkpt
     bz=numpy.ndarray((coords.shape[0],evals[0].size),dtype=float)
     #print bz
     shift=(numpy.array(mesh)-1)/2
     #print 'shift',shift
     for ik in lookup:
         irrk=None
         for orbs,bzk in zip(evals,ourkpt):
             for (kt,ind) in ik:
                 if (bzk==kt).all():
                     irrk=orbs
                     #print 'hello',orbs.kpt,kt
                     break 
             if irrk is not None: break
         if irrk is None:
             safe_print( 'error in ik',ik)
             safe_print( 'our',ourkpt)
             safe_print( 'spglib',grid)
             safe_print( 'mapping',mapping)
         for (kt,ind) in ik:
             #r=kt+shift
             #ind=numpy.argwhere([(g==kt).all() for g in grid])
             #print 'ik',kt,r,ind
             #print irrk.shape, bz.shape
             #bz[r[0],r[1],r[2],:]=irrk.reshape(irrk.size)
             bz[ind,:]=irrk.reshape(irrk.size)
     #duplicate coordinates for the interpolation
     bztmp=bz#.reshape((mesh[0]*mesh[1]*mesh[2], -1))
     #print bztmp
     ndup=7
     duplicates=[[-1,0,0],[1,0,0],[0,-1,0],[0,1,0],[0,0,-1],[0,0,1]]
     bztot=numpy.ndarray((ndup,bztmp.shape[0],bztmp.shape[1]))
     bztot[0,:,:]=bztmp
     ctot=numpy.ndarray((ndup,coords.shape[0],coords.shape[1]))
     ctot[0,:,:]=coords
     for i,sh in enumerate(duplicates):
         bztot[i+1,:,:]=bztmp
         ctot[i+1,:,:]=coords+sh
         #print 'coors',coords,coords+[1.0,0,0]
     bztot=bztot.reshape((ndup*bztmp.shape[0], -1))
     ctot=ctot.reshape((ndup*coords.shape[0], -1))
     import scipy.interpolate.interpnd as interpnd
     self.interpolator=interpnd.LinearNDInterpolator(ctot,bztot)
     #sanity check of the interpolation
     sanity=0.0
     for kpt in evals:
         diff=numpy.ravel(numpy.ravel(kpt)-numpy.ravel(self.interpolator([ kpt.kpt])))
         sanity=max(sanity,numpy.dot(diff,diff))
     print('Interpolation bias',sanity)