def niggli_reduce(self, eps=1e-5): """Niggli reduce this cell, returning a new cell and mapping. See also :func:`ase.build.tools.niggli_reduce_cell`.""" from ase.build.tools import niggli_reduce_cell cell, op = niggli_reduce_cell(self, epsfactor=1e-5) return Cell(cell), op
def niggli_reduce(self, eps=1e-5): """Niggli reduce this cell, returning a new cell and mapping. See also :func:`ase.build.tools.niggli_reduce_cell`.""" from ase.build.tools import niggli_reduce_cell cell, op = niggli_reduce_cell(self, epsfactor=eps) result = Cell(cell) result._pbc = self._pbc.copy() return result, op
def crystal_structure_from_cell(cell, eps=2e-4, niggli_reduce=True): """Return the crystal structure as a string calculated from the cell. Supply a cell (from atoms.get_cell()) and get a string representing the crystal structure returned. Works exactly the opposite way as ase.dft.kpoints.get_special_points(). Parameters: cell : numpy.array or list An array like atoms.get_cell() Returns: crystal structure : str 'cubic', 'fcc', 'bcc', 'tetragonal', 'orthorhombic', 'hexagonal' or 'monoclinic' """ cellpar = cell_to_cellpar(cell) abc = cellpar[:3] angles = cellpar[3:] / 180 * pi a, b, c = abc alpha, beta, gamma = angles if abc.ptp() < eps and abs(angles - pi / 2).max() < eps: return 'cubic' elif abc.ptp() < eps and abs(angles - pi / 3).max() < eps: return 'fcc' elif abc.ptp() < eps and abs(angles - np.arccos(-1 / 3)).max() < eps: return 'bcc' elif abs(a - b) < eps and abs(angles - pi / 2).max() < eps: return 'tetragonal' elif abs(angles - pi / 2).max() < eps: return 'orthorhombic' elif (abs(a - b) < eps and (abs(gamma - pi / 3 * 2) < eps or abs(gamma - pi / 3) < eps) and abs(angles[:2] - pi / 2).max() < eps): return 'hexagonal' elif (abs(angles - pi / 2) > eps).sum() == 1: return 'monoclinic' elif (abc.ptp() < eps and angles.ptp() < eps and np.abs(angles).max() < pi / 2): return 'rhombohedral type 1' elif (abc.ptp() < eps and angles.ptp() < eps and np.abs(angles).max() > pi / 2): return 'rhombohedral type 2' else: if niggli_reduce: from ase.build.tools import niggli_reduce_cell cell, _ = niggli_reduce_cell(cell) return crystal_structure_from_cell(cell, niggli_reduce=False) raise ValueError('Cannot find crystal structure')
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)
def niggli_reduce(self): from ase.build.tools import niggli_reduce_cell cell, op = niggli_reduce_cell(self.array) return Cell(cell, self.pbc), op
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