def __init__(self, atoms=None, calc=None, filename=None): """Band-structure object. Create a band-structure object from an Atoms object, a calculator or from a pickle file. Labels for special points will be automatically added. """ if filename: self.read(filename) else: atoms = atoms or calc.atoms calc = calc or atoms.calc self.cell = atoms.cell self.kpts = calc.get_ibz_k_points() self.fermilevel = calc.get_fermi_level() energies = [] for s in range(calc.get_number_of_spins()): energies.append([calc.get_eigenvalues(kpt=k, spin=s) for k in range(len(self.kpts))]) self.energies = np.array(energies) x, X, labels = labels_from_kpts(self.kpts, self.cell) self.xcoords = x self.label_xcoords = X self.labels = labels
def atoms2bandpath(atoms, path='default', k_points=False, ibz_k_points=False, dimension=3, verbose=False): cell = atoms.get_cell() icell = atoms.get_reciprocal_cell() try: cs = crystal_structure_from_cell(cell) except ValueError: cs = None if verbose: if cs: print('Crystal:', cs) print('Special points:', special_paths[cs]) print('Lattice vectors:') for i, v in enumerate(cell): print('{}: ({:16.9f},{:16.9f},{:16.9f})'.format(i + 1, *v)) print('Reciprocal vectors:') for i, v in enumerate(icell): print('{}: ({:16.9f},{:16.9f},{:16.9f})'.format(i + 1, *v)) # band path special_points = None if path: if path == 'default': path = special_paths[cs] paths = [] special_points = get_special_points(cell) for names in parse_path_string(path): points = [] for name in names: points.append(np.dot(icell.T, special_points[name])) paths.append((names, points)) else: paths = None # k points points = None if atoms.calc is not None and hasattr(atoms.calc, 'get_bz_k_points'): bzk = atoms.calc.get_bz_k_points() if path is None: try: size, offset = get_monkhorst_pack_size_and_offset(bzk) except ValueError: # This was not a MP-grid. Must be a path in the BZ: path = ''.join(labels_from_kpts(bzk, cell)[2]) if k_points: points = bzk elif ibz_k_points: points = atoms.calc.get_ibz_k_points() return BandPath(cell, kpts=points, special_points=special_points)
def get_band_structure(atoms=None, calc=None, _bandpath=None, _reference=None): """Create band structure object from Atoms or calculator.""" # _bandpath and _reference are used internally at the moment, but # the exact implementation will probably change. WIP. # # XXX We throw away info about the bandpath when we create the calculator. # If we have kept the bandpath, we can provide it as an argument here. # It would be wise to check that the bandpath kpoints are the same as # those stored in the calculator. atoms = atoms if atoms is not None else calc.atoms calc = calc if calc is not None else atoms.calc kpts = calc.get_ibz_k_points() energies = [] for s in range(calc.get_number_of_spins()): energies.append( [calc.get_eigenvalues(kpt=k, spin=s) for k in range(len(kpts))]) energies = np.array(energies) if _bandpath is None: from ase.dft.kpoints import BandPath, get_cellinfo, labels_from_kpts cellinfo = get_cellinfo(cell=atoms.cell) special_points = cellinfo.special_points _, _, labels = labels_from_kpts(kpts, cell=atoms.cell, special_points=special_points) _bandpath = BandPath(labelseq=labels, cell=atoms.cell, scaled_kpts=kpts, special_points=special_points) if _reference is None: # Fermi level should come from the GS calculation, not the BS one! _reference = calc.get_fermi_level() return BandStructure(path=_bandpath, energies=energies, reference=_reference)
def get_labels(self): return labels_from_kpts(self.kpts, self.cell)
def plot_reciprocal_cell(atoms, path='default', k_points=False, ibz_k_points=False, plot_vectors=True, dimension=3, output=None, verbose=False): import matplotlib.pyplot as plt cell = atoms.get_cell() icell = atoms.get_reciprocal_cell() try: cs = crystal_structure_from_cell(cell) except ValueError: cs = None if verbose: if cs: print('Crystal:', cs) print('Special points:', special_paths[cs]) print('Lattice vectors:') for i, v in enumerate(cell): print('{}: ({:16.9f},{:16.9f},{:16.9f})'.format(i + 1, *v)) print('Reciprocal vectors:') for i, v in enumerate(icell): print('{}: ({:16.9f},{:16.9f},{:16.9f})'.format(i + 1, *v)) # band path if path: if path == 'default': path = special_paths[cs] paths = [] special_points = get_special_points(cell) for names in parse_path_string(path): points = [] for name in names: points.append(np.dot(icell.T, special_points[name])) paths.append((names, points)) else: paths = None # k points points = None if atoms.calc is not None and hasattr(atoms.calc, 'get_bz_k_points'): bzk = atoms.calc.get_bz_k_points() if path is None: try: size, offset = get_monkhorst_pack_size_and_offset(bzk) except ValueError: # This was not a MP-grid. Must be a path in the BZ: path = ''.join(labels_from_kpts(bzk, cell)[2]) if k_points: points = bzk elif ibz_k_points: points = atoms.calc.get_ibz_k_points() if points is not None: for i in range(len(points)): points[i] = np.dot(icell.T, points[i]) kwargs = { 'cell': cell, 'vectors': plot_vectors, 'paths': paths, 'points': points } if dimension == 1: bz1d_plot(**kwargs) elif dimension == 2: bz2d_plot(**kwargs) else: bz3d_plot(interactive=True, **kwargs) if output: plt.savefig(output) else: plt.show()
def get_labels(self): return labels_from_kpts(self.path.scaled_kpts, self.path.cell, special_points=self.path.special_points)