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
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)))
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
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)))
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
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]
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]
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)
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())
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)
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
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, )
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
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 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)
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
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)]
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
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
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
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('')
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])
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)
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
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)
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)