def atoms2bandstructure(atoms, parser, args): cell = atoms.get_cell() calc = atoms.calc bzkpts = calc.get_bz_k_points() ibzkpts = calc.get_ibz_k_points() efermi = calc.get_fermi_level() nibz = len(ibzkpts) nspins = 1 + int(calc.get_spin_polarized()) eps = np.array([[calc.get_eigenvalues(kpt=k, spin=s) for k in range(nibz)] for s in range(nspins)]) if not args.quiet: print('Spins, k-points, bands: {}, {}, {}'.format(*eps.shape)) if bzkpts is None: if ibzkpts is None: raise ValueError('Cannot find any k-point data') else: path_kpts = ibzkpts else: try: size, offset = get_monkhorst_pack_size_and_offset(bzkpts) except ValueError: path_kpts = ibzkpts else: if not args.quiet: print('Interpolating from Monkhorst-Pack grid (size, offset):') print(size, offset) if args.path is None: err = 'Please specify a path!' try: cs = crystal_structure_from_cell(cell) except ValueError: err += ('\nASE cannot automatically ' 'recognize this crystal structure') else: from ase.dft.kpoints import special_paths kptpath = special_paths[cs] err += ('\nIt looks like you have a {} crystal structure.' '\nMaybe you want its special path:' ' {}'.format(cs, kptpath)) parser.error(err) bz2ibz = calc.get_bz_to_ibz_map() path_kpts = bandpath(args.path, atoms.cell, args.points).kpts icell = atoms.get_reciprocal_cell() eps = monkhorst_pack_interpolate(path_kpts, eps.transpose(1, 0, 2), icell, bz2ibz, size, offset) eps = eps.transpose(1, 0, 2) special_points = get_special_points(cell) path = BandPath(atoms.cell, kpts=path_kpts, special_points=special_points) return BandStructure(path, eps, reference=efermi)
def labels_from_kpts(kpts, cell, eps=1e-5): """Get an x-axis to be used when plotting a band structure. The first of the returned lists can be used as a x-axis when plotting the band structure. The second list can be used as xticks, and the third as xticklabels. Parameters: kpts: list List of scaled k-points. cell: list Unit cell of the atomic structure. Returns: Three arrays; the first is a list of cumulative distances between kpoints, the second is x coordinates of the special points, the third is the special points as strings. """ try: crystal_structure = crystal_structure_from_cell(cell) except ValueError: warnings.warn('Can not recognize your crystal!') special_points = {} else: special_points = get_special_points(crystal_structure, cell) points = np.asarray(kpts) diffs = points[1:] - points[:-1] kinks = abs(diffs[1:] - diffs[:-1]).sum(1) > eps N = len(points) indices = [0] indices.extend(np.arange(1, N - 1)[kinks]) indices.append(N - 1) labels = [] for kpt in points[indices]: for label, k in special_points.items(): if abs(kpt - k).sum() < eps: break else: label = '?' labels.append(label) xcoords = [0] for i1, i2 in zip(indices[:-1], indices[1:]): if i1 + 1 == i2: length = 0 else: diff = points[i2] - points[i1] length = np.linalg.norm(kpoint_convert(cell, skpts_kc=diff)) xcoords.extend(np.linspace(0, length, i2 - i1 + 1)[1:] + xcoords[-1]) xcoords = np.array(xcoords) return xcoords, xcoords[indices], 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 bandpath(path, cell, npoints=50): """Make a list of kpoints defining the path between the given points. path: list or str Can be: * a string that parse_path_string() understands: 'GXL' * a list of BZ points: [(0, 0, 0), (0.5, 0, 0)] * or several lists of BZ points if the the path is not continuous. cell: 3x3 Unit cell of the atoms. npoints: int Length of the output kpts list. Return list of k-points, list of x-coordinates and list of x-coordinates of special points.""" if isinstance(path, basestring): xtal = crystal_structure_from_cell(cell) special = get_special_points(xtal, cell) paths = [] for names in parse_path_string(path): paths.append([special[name] for name in names]) elif np.array(path[0]).ndim == 1: paths = [path] else: paths = path points = np.concatenate(paths) dists = points[1:] - points[:-1] lengths = [np.linalg.norm(d) for d in kpoint_convert(cell, skpts_kc=dists)] i = 0 for path in paths[:-1]: i += len(path) lengths[i - 1] = 0 length = sum(lengths) kpts = [] x0 = 0 x = [] X = [0] for P, d, L in zip(points[:-1], dists, lengths): n = max(2, int(round(L * (npoints - len(x)) / (length - x0)))) for t in np.linspace(0, 1, n)[:-1]: kpts.append(P + t * d) x.append(x0 + t * L) x0 += L X.append(x0) kpts.append(points[-1]) x.append(x0) return np.array(kpts), np.array(x), np.array(X)
def main(args, parser): atoms = read(args.calculation) cell = atoms.get_cell() calc = atoms.calc bzkpts = calc.get_bz_k_points() ibzkpts = calc.get_ibz_k_points() efermi = calc.get_fermi_level() nibz = len(ibzkpts) nspins = 1 + int(calc.get_spin_polarized()) eps = np.array([[calc.get_eigenvalues(kpt=k, spin=s) for k in range(nibz)] for s in range(nspins)]) if not args.quiet: print('Spins, k-points, bands: {}, {}, {}'.format(*eps.shape)) try: size, offset = get_monkhorst_pack_size_and_offset(bzkpts) except ValueError: path = ibzkpts else: if not args.quiet: print('Interpolating from Monkhorst-Pack grid (size, offset):') print(size, offset) if args.path is None: err = 'Please specify a path!' try: cs = crystal_structure_from_cell(cell) except ValueError: err += ('\nGPAW cannot autimatically ' 'recognize this crystal structure') else: from ase.dft.kpoints import special_paths kptpath = special_paths[cs] err += ('\nIt looks like you have a {} crystal structure.' '\nMaybe you want its special path:' ' {}'.format(cs, kptpath)) parser.error(err) bz2ibz = calc.get_bz_to_ibz_map() path = bandpath(args.path, atoms.cell, args.points)[0] icell = atoms.get_reciprocal_cell() eps = monkhorst_pack_interpolate(path, eps.transpose(1, 0, 2), icell, bz2ibz, size, offset) eps = eps.transpose(1, 0, 2) emin, emax = (float(e) for e in args.range) bs = BandStructure(atoms.cell, path, eps, reference=efermi) bs.plot(emin=emin, emax=emax)
def generate_kpath_ase(cell, symprec): eig_val_max = np.real(np.linalg.eigvals(cell)).max() eps = eig_val_max * symprec lattice = crystal_structure_from_cell(cell, eps) paths = special_paths.get(lattice, None) if paths is None: paths = special_paths['orthorhombic'] paths = parse_path_string(special_paths[lattice]) points = special_points.get(lattice) if points is None: try: points = get_special_points(cell) except Exception: return [] return generate_kpath_parameters(points, paths, 100)
def test_monoclinic(): """Test band structure from different variations of hexagonal cells.""" import numpy as np from ase import Atoms from ase.calculators.test import FreeElectrons from ase.geometry import (crystal_structure_from_cell, cell_to_cellpar, cellpar_to_cell) from ase.dft.kpoints import get_special_points mc1 = [[1, 0, 0], [0, 1, 0], [0, 0.2, 1]] par = cell_to_cellpar(mc1) mc2 = cellpar_to_cell(par) mc3 = [[1, 0, 0], [0, 1, 0], [-0.2, 0, 1]] mc4 = [[1, 0, 0], [-0.2, 1, 0], [0, 0, 1]] path = 'GYHCEM1AXH1' firsttime = True for cell in [mc1, mc2, mc3, mc4]: a = Atoms(cell=cell, pbc=True) a.cell *= 3 a.calc = FreeElectrons(nvalence=1, kpts={'path': path}) cs = crystal_structure_from_cell(a.cell) assert cs == 'monoclinic' r = a.cell.reciprocal() k = get_special_points(a.cell)['H'] print(np.dot(k, r)) a.get_potential_energy() bs = a.calc.band_structure() coords, labelcoords, labels = bs.get_labels() assert ''.join(labels) == path e_skn = bs.energies # bs.plot() if firsttime: coords1 = coords labelcoords1 = labelcoords e_skn1 = e_skn firsttime = False else: for d in [ coords - coords1, labelcoords - labelcoords1, e_skn - e_skn1 ]: print(abs(d).max()) assert abs(d).max() < 1e-13, d
def get_cellinfo(cell, lattice=None, eps=2e-4): from ase.build.tools import niggli_reduce_cell rcell, M = niggli_reduce_cell(cell) latt = crystal_structure_from_cell(rcell, niggli_reduce=False) if lattice: assert latt == lattice.lower(), latt if latt == 'monoclinic': # Transform From Niggli to Setyawana-Curtarolo cell: a, b, c, alpha, beta, gamma = cell_to_cellpar(rcell, radians=True) if abs(beta - np.pi / 2) > eps: T = np.array([[0, 1, 0], [-1, 0, 0], [0, 0, 1]]) scell = np.dot(T, rcell) elif abs(gamma - np.pi / 2) > eps: T = np.array([[0, 0, 1], [1, 0, 0], [0, -1, 0]]) else: raise ValueError('You are using a badly oriented ' + 'monoclinic unit cell. Please choose one with ' + 'either beta or gamma != pi/2') scell = np.dot(np.dot(T, rcell), T.T) a, b, c, alpha, beta, gamma = cell_to_cellpar(scell, radians=True) assert alpha < np.pi / 2, 'Your monoclinic angle has to be < pi / 2' M = np.dot(M, T.T) eta = (1 - b * cos(alpha) / c) / (2 * sin(alpha)**2) nu = 1 / 2 - eta * c * cos(alpha) / b points = { 'G': [0, 0, 0], 'A': [1 / 2, 1 / 2, 0], 'C': [0, 1 / 2, 1 / 2], 'D': [1 / 2, 0, 1 / 2], 'D1': [1 / 2, 0, -1 / 2], 'E': [1 / 2, 1 / 2, 1 / 2], 'H': [0, eta, 1 - nu], 'H1': [0, 1 - eta, nu], 'H2': [0, eta, -nu], 'M': [1 / 2, eta, 1 - nu], 'M1': [1 / 2, 1 - eta, nu], 'M2': [1 / 2, eta, -nu], 'X': [0, 1 / 2, 0], 'Y': [0, 0, 1 / 2], 'Y1': [0, 0, -1 / 2], 'Z': [1 / 2, 0, 0] } elif latt == 'rhombohedral type 1': a, b, c, alpha, beta, gamma = cell_to_cellpar(cell=cell, radians=True) eta = (1 + 4 * np.cos(alpha)) / (2 + 4 * np.cos(alpha)) nu = 3 / 4 - eta / 2 points = { 'G': [0, 0, 0], 'B': [eta, 1 / 2, 1 - eta], 'B1': [1 / 2, 1 - eta, eta - 1], 'F': [1 / 2, 1 / 2, 0], 'L': [1 / 2, 0, 0], 'L1': [0, 0, -1 / 2], 'P': [eta, nu, nu], 'P1': [1 - nu, 1 - nu, 1 - eta], 'P2': [nu, nu, eta - 1], 'Q': [1 - nu, nu, 0], 'X': [nu, 0, -nu], 'Z': [0.5, 0.5, 0.5] } else: points = ibz_points[latt] myspecial_points = {label: np.dot(M, kpt) for label, kpt in points.items()} return CellInfo(rcell=rcell, lattice=latt, special_points=myspecial_points)
assert np.allclose(correct_pos, positions) # Test center away from values 0, 0.5 result_positions = wrap_positions(positions, cell, pbc=[True, True, False], center=0.2) correct_pos = [[4.7425, 1.2575, 8.7425], [2.0275, 3.9725, 8.7425], [3.385, 2.615, 10.1], [-0.6875, 1.2575, 8.7425], [6.1, -0.1, 10.1], [3.385, -2.815, 10.1], [2.0275, -1.4575, 8.7425], [0.67, -0.1, 10.1]] assert np.allclose(correct_pos, result_positions) # Get the correct crystal structure from a range of different cells assert crystal_structure_from_cell(bulk('Al').get_cell()) == 'fcc' assert crystal_structure_from_cell(bulk('Fe').get_cell()) == 'bcc' assert crystal_structure_from_cell(bulk('Zn').get_cell()) == 'hexagonal' cell = [[1, 0, 0], [0, 1, 0], [0, 0, 1]] assert crystal_structure_from_cell(cell) == 'cubic' cell = [[1, 0, 0], [0, 1, 0], [0, 0, 2]] assert crystal_structure_from_cell(cell) == 'tetragonal' cell = [[1, 0, 0], [0, 2, 0], [0, 0, 3]] assert crystal_structure_from_cell(cell) == 'orthorhombic' cell = [[1, 0, 0], [0, 2, 0], [0.5, 0, 3]] assert crystal_structure_from_cell(cell) == 'monoclinic' cell = [[1, 0, 0], [0.5, 3**0.5 / 2, 0], [0, 0, 3]] assert crystal_structure_from_cell(cell) == 'hexagonal'
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()
assert np.allclose(correct_pos, positions) # Test center away from values 0, 0.5 result_positions = wrap_positions(positions, cell, pbc=[True, True, False], center=0.2) correct_pos = [[4.7425, 1.2575, 8.7425], [2.0275, 3.9725, 8.7425], [3.385, 2.615, 10.1], [-0.6875, 1.2575, 8.7425], [6.1, -0.1, 10.1], [3.385, -2.815, 10.1], [2.0275, -1.4575, 8.7425], [0.67, -0.1, 10.1]] assert np.allclose(correct_pos, result_positions) # Get the correct crystal structure from a range of different cells assert crystal_structure_from_cell(bulk('Al').get_cell()) == 'fcc' assert crystal_structure_from_cell(bulk('Fe').get_cell()) == 'bcc' assert crystal_structure_from_cell(bulk('Zn').get_cell()) == 'hexagonal' cell = [[1, 0, 0], [0, 1, 0], [0, 0, 1]] assert crystal_structure_from_cell(cell) == 'cubic' cell = [[1, 0, 0], [0, 1, 0], [0, 0, 2]] assert crystal_structure_from_cell(cell) == 'tetragonal' cell = [[1, 0, 0], [0, 2, 0], [0, 0, 3]] assert crystal_structure_from_cell(cell) == 'orthorhombic' cell = [[1, 0, 0], [0, 2, 0], [0, 1, 3]] assert crystal_structure_from_cell(cell) == 'monoclinic'
"""Test band structure from different variations of hexagonal cells.""" import numpy as np from ase import Atoms from ase.calculators.test import FreeElectrons from ase.geometry import crystal_structure_from_cell from ase.dft.kpoints import get_special_points firsttime = True for cell in [[[1, 0, 0], [0.5, 3**0.5 / 2, 0], [0, 0, 1]], [[1, 0, 0], [-0.5, 3**0.5 / 2, 0], [0, 0, 1]], [[0.5, -3**0.5 / 2, 0], [0.5, 3**0.5 / 2, 0], [0, 0, 1]]]: a = Atoms(cell=cell, pbc=True) a.cell *= 3 a.calc = FreeElectrons(nvalence=1, kpts={'path': 'GMKG'}) print(crystal_structure_from_cell(a.cell)) r = a.get_reciprocal_cell() k = get_special_points(a.cell)['K'] print(np.dot(k, r)) a.get_potential_energy() bs = a.calc.band_structure() coords, labelcoords, labels = bs.get_labels() assert ''.join(labels) == 'GMKG' e_skn = bs.energies if firsttime: coords1 = coords labelcoords1 = labelcoords e_skn1 = e_skn firsttime = False else: for d in [coords - coords1, labelcoords - labelcoords1,
def get_special_points(cell, lattice=None, eps=2e-4): """Return dict of special points. The definitions are from a paper by Wahyu Setyawana and Stefano Curtarolo:: http://dx.doi.org/10.1016/j.commatsci.2010.05.010 cell: 3x3 ndarray Unit cell. lattice: str Optionally check that the cell is one of the following: cubic, fcc, bcc, orthorhombic, tetragonal, hexagonal or monoclinic. eps: float Tolerance for cell-check. """ if isinstance(cell, str): warnings.warn('Please call this function with cell as the first ' 'argument') lattice, cell = cell, lattice from ase.build.tools import niggli_reduce_cell rcell, M = niggli_reduce_cell(cell) latt = crystal_structure_from_cell(rcell, niggli_reduce=False) if lattice: assert latt == lattice.lower(), latt if latt == 'monoclinic': # Transform From Niggli to Setyawana-Curtarolo cell: a, b, c, alpha, beta, gamma = cell_to_cellpar(rcell, radians=True) if abs(beta - np.pi / 2) > eps: T = np.array([[0, 1, 0], [-1, 0, 0], [0, 0, 1]]) scell = np.dot(T, rcell) elif abs(gamma - np.pi / 2) > eps: T = np.array([[0, 0, 1], [1, 0, 0], [0, -1, 0]]) else: raise ValueError('You are using a badly oriented ' + 'monoclinic unit cell. Please choose one with ' + 'either beta or gamma != pi/2') scell = np.dot(np.dot(T, rcell), T.T) a, b, c, alpha, beta, gamma = cell_to_cellpar(scell, radians=True) assert alpha < np.pi / 2, 'Your monoclinic angle has to be < pi / 2' M = np.dot(M, T.T) eta = (1 - b * cos(alpha) / c) / (2 * sin(alpha)**2) nu = 1 / 2 - eta * c * cos(alpha) / b points = { 'G': [0, 0, 0], 'A': [1 / 2, 1 / 2, 0], 'C': [0, 1 / 2, 1 / 2], 'D': [1 / 2, 0, 1 / 2], 'D1': [1 / 2, 0, -1 / 2], 'E': [1 / 2, 1 / 2, 1 / 2], 'H': [0, eta, 1 - nu], 'H1': [0, 1 - eta, nu], 'H2': [0, eta, -nu], 'M': [1 / 2, eta, 1 - nu], 'M1': [1 / 2, 1 - eta, nu], 'M2': [1 / 2, eta, -nu], 'X': [0, 1 / 2, 0], 'Y': [0, 0, 1 / 2], 'Y1': [0, 0, -1 / 2], 'Z': [1 / 2, 0, 0] } elif latt == 'rhombohedral type 1': a, b, c, alpha, beta, gamma = cell_to_cellpar(cell=cell, radians=True) eta = (1 + 4 * np.cos(alpha)) / (2 + 4 * np.cos(alpha)) nu = 3 / 4 - eta / 2 points = { 'G': [0, 0, 0], 'B': [eta, 1 / 2, 1 - eta], 'B1': [1 / 2, 1 - eta, eta - 1], 'F': [1 / 2, 1 / 2, 0], 'L': [1 / 2, 0, 0], 'L1': [0, 0, -1 / 2], 'P': [eta, nu, nu], 'P1': [1 - nu, 1 - nu, 1 - eta], 'P2': [nu, nu, eta - 1], 'Q': [1 - nu, nu, 0], 'X': [nu, 0, -nu], 'Z': [0.5, 0.5, 0.5] } else: points = special_points[latt] return {label: np.dot(M, kpt) for label, kpt in points.items()}
def plot_magnon_band(ham, kvectors=np.array([[0, 0, 0], [0.5, 0, 0], [0.5, 0.5, 0], [0, 0, 0], [.5, .5, .5]]), knames=['$\Gamma$', 'X', 'M', '$\Gamma$', 'R'], supercell_matrix=None, npoints=100, color='red', ax=None, eps=1e-3, kpath_fname=None): if ax is None: fig, ax = plt.subplots() if knames is None or kvectors is None: from ase.build.tools import niggli_reduce_cell rcell, M = niggli_reduce_cell(ham.cell) fcell = fix_cell(ham.cell, eps=eps) lattice_type = crystal_structure_from_cell(rcell, eps=eps, niggli_reduce=False) labels = parse_path_string(special_paths[lattice_type]) knames = [item for sublist in labels for item in sublist] kpts, x, X = bandpath(special_paths[lattice_type], rcell, npoints=npoints, eps=1e-8) spk = get_special_points(ham.cell, eps=1e-8) else: kpts, x, X = bandpath(kvectors, fix_cell(ham.cell), npoints) spk = dict(zip(knames, kvectors)) if supercell_matrix is not None: kvectors = [np.dot(k, supercell_matrix) for k in kvectors] qsolver = QSolver(hamiltonian=ham) evals, evecs = qsolver.solve_all(kpts, eigen_vectors=True) nbands = evals.shape[1] #evecs imin = np.argmin(evals[:, 0]) emin = np.min(evals[:, 0]) nspin = evals.shape[1] // 3 evec_min = evecs[imin, :, 0].reshape(nspin, 3) # write information to file if kpath_fname is not None: with open(kpath_fname, 'w') as myfile: myfile.write("K-points:\n") for name, k in spk.items(): myfile.write("%s: %s\n" % (name, k)) myfile.write("\nThe energy minimum is at:") myfile.write("%s\n" % kpts[np.argmin(evals[:, 0])]) for i, ev in enumerate(evec_min): myfile.write("spin %s: %s \n" % (i, ev / np.linalg.norm(ev))) print("\nThe energy minimum is at:") print("%s\n" % kpts[np.argmin(evals[:, 0])]) print("\n The ground state is:") for i, ev in enumerate(evec_min): print("spin %s: %s" % (i, ev / np.linalg.norm(ev))) for i in range(nbands): ax.plot(x, (evals[:, i] - emin) / 1.6e-22) ax.set_xlabel('Q-point') ax.set_ylabel('Energy (meV)') ax.set_xlim(x[0], x[-1]) ax.set_ylim(0) ax.set_xticks(X) ax.set_xticklabels(knames) for x in X: ax.axvline(x, linewidth=0.6, color='gray') return ax
from ase.geometry import crystal_structure_from_cell, cell_to_cellpar, cellpar_to_cell from ase.dft.kpoints import get_special_points mc1 = [[1, 0, 0], [0, 1, 0], [0, 0.2, 1]] par = cell_to_cellpar(mc1) mc2 = cellpar_to_cell(par) mc3 = [[1, 0, 0], [0, 1, 0], [-0.2, 0, 1]] mc4 = [[1, 0, 0], [-0.2, 1, 0], [0, 0, 1]] path = 'GYHCEM1AXH1' firsttime = True for cell in [mc1, mc2, mc3, mc4]: a = Atoms(cell=cell, pbc=True) a.cell *= 3 a.calc = FreeElectrons(nvalence=1, kpts={'path': path}) cs = crystal_structure_from_cell(a.cell) assert cs == 'monoclinic' r = a.get_reciprocal_cell() k = get_special_points(a.cell)['H'] print(np.dot(k, r)) a.get_potential_energy() bs = a.calc.band_structure() coords, labelcoords, labels = bs.get_labels() assert ''.join(labels) == path e_skn = bs.energies # bs.plot() if firsttime: coords1 = coords labelcoords1 = labelcoords e_skn1 = e_skn firsttime = False
def startMeasurement(filepath, file_type, covalent_radii_cut_off, c, n1, n2, calculate): if n1 > n2: print("Final m cannot be smaller than initial m") return print("Starting script...") slab = read(filepath) total_particles = len(slab) print("Slab %s read with success. Total particles %d" % (filepath, total_particles)) print("Creating graph...") if file_type == 'V': G = generateGraphFromSlabVinkFile(slab, covalent_radii_cut_off) else: G = generateGraphFromSlab(slab, covalent_radii_cut_off) total_nodes = G.get_total_nodes() if total_nodes == 0 or G.get_total_edges() == 0: print("No edges found in graph. Check covalent_radii_cut_off") return print("Graph created with success. Nodes found: %d" % total_nodes) cell = slab.get_cell() crystal_structure = crystal_structure_from_cell(cell) if crystal_structure != "ortorhombic" and crystal_structure != "cubic": print("Unit cell is not orthorhombic nor cubic") return measurement = Measurement() measurement.fromFile(filepath, covalent_radii_cut_off, c, n1, n2) measurement.createFile() (pbcX, pbcY, pbcZ) = slab.get_pbc() (dmin, dmax) = getMaxMinSlabArray(slab) maxM = getNumberRandomPositions(n2 - 1, total_particles) configurationalEntropy = bg.ConfigurationalEntropy(G, 3, len(slab), pbcX, pbcY, pbcZ, maxM) configurationalEntropy.add_positions(slab.get_positions(wrap=True)) print("Generating random positions...") configurationalEntropy.init_search(0, cell[0][0], 0, cell[1][1], 0, cell[2][2], n2 - 1, maxM, dmin, dmax) print("Random positions generated.") H_n_values = [] for n in range(n1, n2): measurement.start() m = getNumberRandomPositions(n, total_particles) H_n, H1n = run(configurationalEntropy, m, n, c) measurement.writeResult(n, m, H_n, H1n) measurement.end() H_n_values.append((n, H_n, H1n, "Y")) calculateConfigurationalEntropy(n1, n2, H_n_values, c, calculate) print("Program ended correctly")