Exemplo n.º 1
0
    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
Exemplo n.º 2
0
    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
Exemplo n.º 3
0
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')
Exemplo n.º 4
0
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)
Exemplo n.º 5
0
Arquivo: cell.py Projeto: btodac/ase
 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
Exemplo n.º 6
0
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()}
Exemplo n.º 7
0
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