コード例 #1
0
ファイル: bravais.py プロジェクト: btodac/ase
    def bandpath(self, path=None, npoints=50, special_points=None):
        # npoints should depend on the length of the path
        if special_points is None:
            special_points = self.get_special_points()

        if path is None:
            path = self.variant.special_path

        bandpath = BandPath(cell=self.tocell(),
                            labelseq=path,
                            special_points=special_points)
        return bandpath.interpolate(npoints=npoints)
コード例 #2
0
ファイル: cell.py プロジェクト: lilyminium/ase
    def bandpath(self, path=None, npoints=None, density=None,
                 special_points=None, eps=2e-4, *, pbc=None):
        """Build a :class:`~ase.dft.kpoints.BandPath` for this cell.

        If special points are None, determine the Bravais lattice of
        this cell and return a suitable Brillouin zone path with
        standard special points.

        If special special points are given, interpolate the path
        directly from the available data.

        Parameters:

        path: string
            String of special point names defining the path, e.g. 'GXL'.
        npoints: int
            Number of points in total.  Note that at least one point
            is added for each special point in the path.
        density: float
            density of kpoints along the path in Å⁻¹.
        special_points: dict
            Dictionary mapping special points to scaled kpoint coordinates.
            For example ``{'G': [0, 0, 0], 'X': [1, 0, 0]}``.
        eps: float
            Tolerance for determining Bravais lattice.
        pbc: three bools
            Whether cell is periodic in each direction.  Normally not
            necessary.  If cell has three nonzero cell vectors, use
            e.g. pbc=[1, 1, 0] to request a 2D bandpath nevertheless.

        Example
        -------
        >>> cell = Cell.fromcellpar([4, 4, 4, 60, 60, 60])
        >>> cell.bandpath('GXW', npoints=20)
        BandPath(path='GXW', cell=[3x3], special_points={GKLUWX}, kpts=[20x3])

        """
        # TODO: Combine with the rotation transformation from bandpath()

        cell = self if pbc is None else self.uncomplete(pbc)

        if special_points is None:
            from ase.lattice import identify_lattice
            lat, op = identify_lattice(cell, eps=eps)
            path = lat.bandpath(path, npoints=npoints, density=density)
            return path.transform(op)
        else:
            from ase.dft.kpoints import BandPath, resolve_custom_points
            path = resolve_custom_points(path, special_points, eps=eps)
            path = BandPath(cell, path=path, special_points=special_points)
            return path.interpolate(npoints=npoints, density=density)
コード例 #3
0
ファイル: jsonio.py プロジェクト: chrisjsewell/ase
def object_hook(dct):
    if '__datetime__' in dct:
        return datetime.datetime.strptime(dct['__datetime__'],
                                          '%Y-%m-%dT%H:%M:%S.%f')
    if '__complex_ndarray__' in dct:
        r, i = (np.array(x) for x in dct['__complex_ndarray__'])
        return r + i * 1j

    if '__ase_objtype__' in dct:
        objtype = dct.pop('__ase_objtype__')
        dct = numpyfy(dct)

        # We just try each object type one after another and instantiate
        # them manually, depending on which kind it is.
        # We can formalize this later if it ever becomes necessary.
        if objtype == 'cell':
            from ase.cell import Cell
            obj = Cell(**dct)
        elif objtype == 'bandstructure':
            from ase.dft.band_structure import BandStructure
            obj = BandStructure(**dct)
        elif objtype == 'bandpath':
            from ase.dft.kpoints import BandPath
            obj = BandPath(path=dct.pop('labelseq'), **dct)
        else:
            raise RuntimeError('Do not know how to decode object type {} '
                               'into an actual object'.format(objtype))

        assert obj.ase_objtype == objtype
        return obj

    return dct
コード例 #4
0
ファイル: jsonio.py プロジェクト: elinscott/ase_koopmans
def create_ase_object(objtype, dct):
    # We just try each object type one after another and instantiate
    # them manually, depending on which kind it is.
    # We can formalize this later if it ever becomes necessary.
    if objtype == 'cell':
        from ase.cell import Cell
        dct.pop('pbc', None)  # compatibility; we once had pbc
        obj = Cell(**dct)
    elif objtype == 'bandstructure':
        from ase.spectrum.band_structure import BandStructure
        obj = BandStructure(**dct)
    elif objtype == 'bandpath':
        from ase.dft.kpoints import BandPath
        obj = BandPath(path=dct.pop('labelseq'), **dct)
    elif objtype == 'atoms':
        from ase import Atoms
        obj = Atoms.fromdict(dct)
    elif objtype == 'densityofstates':
        from ase.dft.dos import DOS
        obj = DOS(**dct)
    elif objtype == 'griddoscollection':
        from ase.spectrum.doscollection import GridDOSCollection
        obj = GridDOSCollection.fromdict(dct)
    else:
        raise ValueError('Do not know how to decode object type {} '
                         'into an actual object'.format(objtype))
    assert obj.ase_objtype == objtype
    return obj
コード例 #5
0
    def bandpath(self,
                 path=None,
                 npoints=None,
                 density=None,
                 special_points=None,
                 eps=2e-4):
        """Build a :class:`~ase.dft.kpoints.BandPath` for this cell.

        If special points are None, determine the Bravais lattice of
        this cell and return a suitable Brillouin zone path with
        standard special points.

        If special special points are given, interpolate the path
        directly from the available data.

        Parameters:

        path: string
            String of special point names defining the path, e.g. 'GXL'.
        npoints: int
            Number of points in total.  Note that at least one point
            is added for each special point in the path.
        density: float
            density of kpoints along the path in Å⁻¹.
        special_points: dict
            Dictionary mapping special points to scaled kpoint coordinates.
        eps: float
            Tolerance for determining Bravais lattice.

        Example
        -------
        >>> cell = Cell.fromcellpar([4, 4, 4, 60, 60, 60])
        >>> cell.bandpath('GXW', npoints=20)
        BandPath(path='GXW', cell=[3x3], special_points={GKLUWX}, kpts=[20x3])

        """
        # TODO: Combine with the rotation transformation from bandpath()
        if special_points is None:
            from ase.lattice import identify_lattice
            lat, op = identify_lattice(self, eps=eps)
            path = lat.bandpath(path, npoints=npoints, density=density)
            return path.transform(op)
        else:
            from ase.dft.kpoints import BandPath, resolve_custom_points
            path = resolve_custom_points(path, special_points, eps=eps)
            path = BandPath(self, path=path, special_points=special_points)
            return path.interpolate(npoints=npoints, density=density)
コード例 #6
0
ファイル: reciprocal.py プロジェクト: martin-stoehr/ase-devel
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)
コード例 #7
0
ファイル: band_structure.py プロジェクト: joegomes/ase
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)
コード例 #8
0
def test_band_structure_setup(testing_calculator):

    c = testing_calculator

    from ase.dft.kpoints import BandPath

    atoms = ase.build.bulk('Ag')
    bp = BandPath(cell=atoms.cell,
                  path='GX',
                  special_points={
                      'G': [0, 0, 0],
                      'X': [0.5, 0, 0.5]
                  })
    bp = bp.interpolate(npoints=10)

    c.set_bandpath(bp)

    kpt_list = c.cell.bs_kpoint_list.value.split('\n')
    assert len(kpt_list) == 10
    assert list(map(float, kpt_list[0].split())) == [0., 0., 0.]
    assert list(map(float, kpt_list[-1].split())) == [0.5, 0.0, 0.5]
コード例 #9
0
    def read_bands(self):
        outputyaml = self.outputdir.joinpath("band.yaml")
        assert outputyaml.exists(), "File band.yaml not found."
        with open(outputyaml, "r") as stream:
            try:
                data = yaml.safe_load(stream)
            except yaml.YAMLError as exc:
                raise Exception(exc)

        labels = data["labels"]
        bpstring = []
        for i, pair in enumerate(labels):
            if i == 0:
                bpstring.append(pair[0])
            elif i == len(labels) - 1:
                bpstring.append(pair[0])
                bpstring.append(pair[1])
            else:
                bpstring.append(pair[0])
        bpstring = "".join(bpstring)
        bpstring = bpstring.replace("|", ",")
        bplist = parse_path_string(bpstring)

        special_points = (self.structure.cell.get_bravais_lattice().bandpath().
                          special_points)
        self._bandpath = BandPath(path=bpstring,
                                  cell=self.structure.cell,
                                  special_points=special_points)

        phon = data["phonon"]
        nqpoints = data["segment_nqpoint"]

        qpoints = np.array([k["q-position"] for k in phon], dtype=np.float32)
        pbands = np.array([[l["frequency"] for l in k["band"]] for k in phon],
                          dtype=np.float32)

        b = namedtuple("band", ["qpoints", "frequencies"])
        count = 0
        bands = {}

        i = 0
        for segment in bplist:
            for pair in zip(segment[:-1], segment[1:]):
                j1, j2 = count, nqpoints[i] + count
                count = j2
                qp = qpoints[j1:j2, :]
                pb = pbands[j1:j2, :]
                bands[pair] = b(qp, pb)
                rev = (pair[1], pair[0])
                bands[rev] = b(qp[::-1], pb[::-1])
                i += 1
        return bands
コード例 #10
0
ファイル: __init__.py プロジェクト: JaniceLC/aseplayground
    def bandpath(self,
                 path=None,
                 npoints=None,
                 special_points=None,
                 density=None,
                 transformation=None):
        """Return a :class:`~ase.dft.kpoints.BandPath` for this lattice.

        See :meth:`ase.cell.Cell.bandpath` for description of parameters.

        >>> BCT(3, 5).bandpath()
        BandPath(path='GXYSGZS1NPY1Z,XP', cell=[3x3], \
special_points={GNPSS1XYY1Z}, kpts=[51x3])

        .. note:: This produces the standard band path following AFlow
           conventions.  If your cell does not follow this convention,
           you will need :meth:`ase.cell.Cell.bandpath` instead or
           the kpoints may not correspond to your particular cell.

        """
        if special_points is None:
            special_points = self.get_special_points()

        if path is None:
            path = self._variant.special_path
        elif not isinstance(path, str):
            from ase.dft.kpoints import resolve_custom_points
            special_points = dict(special_points)
            path = resolve_custom_points(path, special_points, self._eps)

        cell = self.tocell()
        if transformation is not None:
            cell = transformation.dot(cell)

        bandpath = BandPath(cell=cell,
                            path=path,
                            special_points=special_points)
        return bandpath.interpolate(npoints=npoints, density=density)
コード例 #11
0
    def _set_bandpath(self, bandpathstring=None):
        if bandpathstring == None:
            pbc = [1, 1, 1] if not self.is_2d else [1, 1, 0]
            bandpath = self.structure.cell.get_bravais_lattice(
                pbc=pbc).bandpath()
            self._special_points = bandpath.special_points
            bandpathstring = bandpath.path

        bp = BandPath(
            path=bandpathstring,
            cell=self.structure.cell,
            special_points=self.special_points,
        )
        self._bandpath = bp
        self._special_points = bp.special_points
コード例 #12
0
ファイル: jsonio.py プロジェクト: Abhivega/ase
def create_ase_object(objtype, dct):
    # We just try each object type one after another and instantiate
    # them manually, depending on which kind it is.
    # We can formalize this later if it ever becomes necessary.
    if objtype == 'cell':
        from ase.cell import Cell
        obj = Cell(**dct)
    elif objtype == 'bandstructure':
        from ase.dft.band_structure import BandStructure
        obj = BandStructure(**dct)
    elif objtype == 'bandpath':
        from ase.dft.kpoints import BandPath
        obj = BandPath(path=dct.pop('labelseq'), **dct)
    else:
        raise ValueError('Do not know how to decode object type {} '
                         'into an actual object'.format(objtype))
    assert obj.ase_objtype == objtype
    return obj
コード例 #13
0
 def set_bandpath(self, bandpathstring):
     new_bandpath = parse_path_string(bandpathstring)
     old_path = self.bandpath
     special_points = old_path.special_points
     pairs = [(s[0], s[1]) for s in self.bands.keys()]
     for segment in new_bandpath:
         assert len(segment) > 1, "A vertex needs at least two points."
         p = zip(segment[:-1], segment[1:])
         for s1, s2 in p:
             assert any(x in pairs for x in ((s1, s2), (
                 s2,
                 s1))), "The k-path {}-{} has not been calculated.".format(
                     s1, s2)
     else:
         new_path = BandPath(
             path=bandpathstring,
             cell=self.structure.cell,
             special_points=special_points,
         )
     self._bandpath = new_path
コード例 #14
0
    def read_bandstructure(self):
        if not os.path.isfile(f'{self.label}_band.dat'):
            return

        # Construct the higher-resolution bandpath from the *_band.labelinfo.dat file
        with open(f'{self.label}_band.labelinfo.dat') as fd:
            flines = fd.readlines()
        kpts = []

        self.atoms.cell.pbc = True
        for start, end in zip(flines[:-1], flines[1:]):
            start_label, i_start = start.split()[:2]
            end_label, i_end = end.split()[:2]
            kpts += self.atoms.cell.bandpath(start_label + end_label,
                                             int(i_end) - int(i_start) +
                                             1).kpts[:-1].tolist()
        kpts.append([float(x) for x in flines[-1].split()[-3:]])
        path = self.parameters.kpoint_path.path
        special_points = self.parameters.kpoint_path.special_points
        kpath = BandPath(self.atoms.cell,
                         kpts,
                         path=path,
                         special_points=special_points)

        # Read in the eigenvalues from the *_band.dat file
        with open(f'{self.label}_band.dat') as fd:
            flines = fd.readlines()
        eigs = [[]]
        for line in flines[:-1]:
            splitline = line.strip().split()
            if len(splitline) == 0:
                eigs.append([])
            else:
                eigs[-1].append(line.strip().split()[-1])
        eigs = np.array(eigs, dtype=float).T

        # Construct the bandstructure
        bs = BandStructure(kpath, eigs[np.newaxis, :, :])

        self.results['band structure'] = bs
コード例 #15
0
ファイル: base.py プロジェクト: shahramyalameha/aimstools
 def _set_bandpath_from_sections(self):
     sections = self.band_sections
     special_points = {k.symbol1: k.k1 for k in sections}
     special_points.update({k.symbol2: k.k2 for k in sections})
     pathstring = [[k.symbol1, k.symbol2] for k in sections]
     rev_string = []
     for i, k in enumerate(pathstring):
         s1, s2 = k
         if i == 0:
             rev_string.append(s1)
             rev_string.append(s2)
         elif s1 == rev_string[-1]:
             rev_string.append(s2)
         else:  # s1 != rev_string[-1]:
             rev_string.append(",")
             rev_string.append(s1)
             rev_string.append(s2)
     pathstring = "".join(rev_string)
     bp = BandPath(path=pathstring,
                   cell=self.structure.cell,
                   special_points=special_points)
     self._bandpath = bp
コード例 #16
0
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)
コード例 #17
0
ファイル: wannier90.py プロジェクト: elinscott/ase_koopmans
def construct_kpoint_path(path: str, cell: Cell, bands_point_num: int) -> BandPath:
    path_lengths = _path_lengths(path, cell, bands_point_num)
    special_points = cell.bandpath().special_points

    path_list = path_str_to_list(path, special_points)

    kpts = []
    for start, end, npoints in zip(path_list[:-1], path_list[1:], path_lengths):
        if start == ',':
            pass
        elif end == ',':
            kpts.append(special_points[start].tolist())
        else:
            bp = bandpath(start + end, cell, npoints + 1)
            kpts += bp.kpts[:-1].tolist()
    # Don't forget about the final kpoint
    kpts.append(bp.kpts[-1].tolist())

    if len(kpts) != sum(path_lengths) + 1:
        raise AssertionError(
            'Did not get the expected number of kpoints; this suggests there is a bug in the code')

    return BandPath(cell=cell, kpts=kpts, path=path, special_points=special_points)
コード例 #18
0
def test_castep_interface():
    """Simple shallow test of the CASTEP interface"""
    import os
    import re
    import tempfile
    import warnings

    import numpy as np
    import ase
    import ase.lattice.cubic
    from ase.calculators.castep import (Castep, CastepOption, CastepParam,
                                        CastepCell, make_cell_dict,
                                        make_param_dict, CastepKeywords,
                                        create_castep_keywords,
                                        import_castep_keywords,
                                        CastepVersionError)

    # XXX on porting this test to pytest it wasn't skipped as it should be.
    # At any rate it failed then.  Maybe someone should look into that ...
    #
    # Hence, call the constructor to trigger our test skipping hack:
    Castep()

    tmp_dir = tempfile.mkdtemp()

    # We have fundamentally two sets of tests: one if CASTEP is present, the other
    # if it isn't
    has_castep = False
    # Try creating and importing the castep keywords first
    try:
        create_castep_keywords(castep_command=os.environ['CASTEP_COMMAND'],
                               path=tmp_dir,
                               fetch_only=20)
        has_castep = True  # If it worked, it must be present
    except KeyError:
        print('Could not find the CASTEP_COMMAND environment variable - please'
              ' set it to run the full set of Castep tests')
    except CastepVersionError:
        print(
            'Invalid CASTEP_COMMAND provided - please set the correct one to '
            'run the full set of Castep tests')

    try:
        castep_keywords = import_castep_keywords(
            castep_command=os.environ.get('CASTEP_COMMAND', ''))
    except CastepVersionError:
        castep_keywords = None

    # Start by testing the fundamental parts of a CastepCell/CastepParam object
    boolOpt = CastepOption('test_bool', 'basic', 'defined')
    boolOpt.value = 'TRUE'
    assert boolOpt.raw_value is True

    float3Opt = CastepOption('test_float3', 'basic', 'real vector')
    float3Opt.value = '1.0 2.0 3.0'
    assert np.isclose(float3Opt.raw_value, [1, 2, 3]).all()

    # Generate a mock keywords object
    mock_castep_keywords = CastepKeywords(make_param_dict(), make_cell_dict(),
                                          [], [], 0)
    mock_cparam = CastepParam(mock_castep_keywords, keyword_tolerance=2)
    mock_ccell = CastepCell(mock_castep_keywords, keyword_tolerance=2)

    # Test special parsers
    mock_cparam.continuation = 'default'
    mock_cparam.reuse = 'default'
    assert mock_cparam.reuse.value is None

    mock_ccell.species_pot = ('Si', 'Si.usp')
    mock_ccell.species_pot = ('C', 'C.usp')
    assert 'Si Si.usp' in mock_ccell.species_pot.value
    assert 'C C.usp' in mock_ccell.species_pot.value
    symops = (np.eye(3)[None], np.zeros(3)[None])
    mock_ccell.symmetry_ops = symops
    assert """1.0 0.0 0.0
    0.0 1.0 0.0
    0.0 0.0 1.0
    0.0 0.0 0.0""" in mock_ccell.symmetry_ops.value

    # check if the CastepOpt, CastepCell comparison mechanism works
    if castep_keywords:
        p1 = CastepParam(castep_keywords)
        p2 = CastepParam(castep_keywords)

        assert p1._options == p2._options

        p1._options['xc_functional'].value = 'PBE'
        p1.xc_functional = 'PBE'

        assert p1._options != p2._options

    c = Castep(directory=tmp_dir, label='test_label', keyword_tolerance=2)
    if castep_keywords:
        c.xc_functional = 'PBE'
    else:
        c.param.xc_functional = 'PBE'  # In "forgiving" mode, we need to specify

    lattice = ase.lattice.cubic.BodyCenteredCubic('Li')

    print('For the sake of evaluating this test, warnings')
    print('about auto-generating pseudo-potentials are')
    print('normal behavior and can be safely ignored')

    lattice.calc = c

    param_fn = os.path.join(tmp_dir, 'myParam.param')

    with open(param_fn, 'w') as param:
        param.write('XC_FUNCTIONAL : PBE #comment\n')
        param.write('XC_FUNCTIONAL : PBE #comment\n')
        param.write('#comment\n')
        param.write('CUT_OFF_ENERGY : 450.\n')

    c.merge_param(param_fn)

    assert c.calculation_required(lattice)
    if has_castep:
        assert c.dryrun_ok()

    c.prepare_input_files(lattice)

    # detecting pseudopotentials tests

    # typical filenames
    files = [
        'Ag_00PBE.usp', 'Ag_00.recpot', 'Ag_C18_PBE_OTF.usp',
        'ag-optgga1.recpot', 'Ag_OTF.usp', 'ag_pbe_v1.4.uspp.F.UPF',
        'Ni_OTF.usp', 'fe_pbe_v1.5.uspp.F.UPF', 'Cu_01.recpot'
    ]

    pp_path = os.path.join(tmp_dir, 'test_pp')
    os.makedirs(pp_path)

    for f in files:
        with open(os.path.join(pp_path, f), 'w') as _f:
            _f.write('DUMMY PP')

    c = Castep(directory=tmp_dir,
               label='test_label_pspots',
               castep_pp_path=pp_path)
    c._pedantic = True
    atoms = ase.build.bulk('Ag')
    atoms.calc = c

    # I know, unittest would be nicer... maybe at a later point

    # disabled, but may be useful still
    # try:
    # # this should yield no files
    # atoms.calc.find_pspots(suffix='uspp')
    # raise AssertionError
    #    # this should yield no files
    #    atoms.calc.find_pspots(suffix='uspp')
    #    raise AssertionError
    # except RuntimeError as e:
    # #print(e)
    # pass
    #     # print(e)
    #     pass

    try:
        # this should yield non-unique files
        atoms.calc.find_pspots(suffix='recpot')
        raise AssertionError
    except RuntimeError:
        pass

    # now let's see if we find all...
    atoms.calc.find_pspots(pspot='00PBE', suffix='usp')
    assert atoms.calc.cell.species_pot.value.split()[-1] == 'Ag_00PBE.usp'

    atoms.calc.find_pspots(pspot='00', suffix='recpot')
    assert atoms.calc.cell.species_pot.value.split()[-1] == 'Ag_00.recpot'

    atoms.calc.find_pspots(pspot='C18_PBE_OTF', suffix='usp')
    assert atoms.calc.cell.species_pot.value.split(
    )[-1] == 'Ag_C18_PBE_OTF.usp'

    atoms.calc.find_pspots(pspot='optgga1', suffix='recpot')
    assert atoms.calc.cell.species_pot.value.split()[-1] == 'ag-optgga1.recpot'

    atoms.calc.find_pspots(pspot='OTF', suffix='usp')
    assert atoms.calc.cell.species_pot.value.split()[-1] == 'Ag_OTF.usp'

    atoms.calc.find_pspots(suffix='UPF')
    assert (atoms.calc.cell.species_pot.value.split()[-1] ==
            'ag_pbe_v1.4.uspp.F.UPF')

    # testing regular workflow
    c = Castep(directory=tmp_dir,
               label='test_label_pspots',
               castep_pp_path=pp_path,
               find_pspots=True,
               keyword_tolerance=2)
    c._build_missing_pspots = False
    atoms = ase.build.bulk('Ag')
    atoms.calc = c

    # this should raise an error due to ambuiguity
    try:
        c._fetch_pspots()
        raise AssertionError
    except RuntimeError:
        pass

    for e in ['Ni', 'Fe', 'Cu']:
        atoms = ase.build.bulk(e)
        atoms.calc = c
        c._fetch_pspots()

    # test writing to file
    tmp_dir = os.path.join(tmp_dir, 'input_files')
    c = Castep(directory=tmp_dir,
               find_pspots=True,
               castep_pp_path=pp_path,
               keyword_tolerance=2)
    c._label = 'test'
    atoms = ase.build.bulk('Cu')
    atoms.calc = c
    c.prepare_input_files()

    with open(os.path.join(tmp_dir, 'test.cell'), 'r') as f:
        assert re.search(r'Cu Cu_01\.recpot',
                         ''.join(f.readlines())) is not None

    # test keyword conflict management
    c = Castep(cut_off_energy=300.)
    assert float(c.param.cut_off_energy.value) == 300.0
    with warnings.catch_warnings(record=True) as w:
        warnings.simplefilter("always")

        c.basis_precision = 'MEDIUM'
        assert issubclass(w[-1].category, UserWarning)
        assert "conflicts" in str(w[-1].message)
        assert c.param.cut_off_energy.value is None
        assert c.param.basis_precision.value.strip() == 'MEDIUM'

    with warnings.catch_warnings(record=True) as w:
        warnings.simplefilter("always")

        c.cut_off_energy = 200.0
        assert c.param.basis_precision.value is None
        assert issubclass(w[-1].category, UserWarning)
        assert 'option "cut_off_energy" conflicts' in str(w[-1].message)

    # test kpoint setup options
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        # This block of tests is going to generate a lot of conflict warnings.
        # We already tested that those work, so just hide them from the output.

        c = Castep(kpts=[
            (0.0, 0.0, 0.0, 1.0),
        ])
        assert c.cell.kpoint_list.value == '0.0 0.0 0.0 1.0'
        c.set_kpts(((0.0, 0.0, 0.0, 0.25), (0.25, 0.25, 0.3, 0.75)))
        assert c.cell.kpoint_list.value == '0.0 0.0 0.0 0.25\n0.25 0.25 0.3 0.75'
        c.set_kpts(c.cell.kpoint_list.value.split('\n'))
        assert c.cell.kpoint_list.value == '0.0 0.0 0.0 0.25\n0.25 0.25 0.3 0.75'
        c.set_kpts([3, 3, 2])
        assert c.cell.kpoint_mp_grid.value == '3 3 2'
        c.set_kpts(None)
        assert c.cell.kpoints_list.value is None
        assert c.cell.kpoint_list.value is None
        assert c.cell.kpoint_mp_grid.value is None
        c.set_kpts('2 2 3')
        assert c.cell.kpoint_mp_grid.value == '2 2 3'
        c.set_kpts({'even': True, 'gamma': True})
        assert c.cell.kpoint_mp_grid.value == '2 2 2'
        assert c.cell.kpoint_mp_offset.value == '0.25 0.25 0.25'
        c.set_kpts({'size': (2, 2, 4), 'even': False})
        assert c.cell.kpoint_mp_grid.value == '3 3 5'
        assert c.cell.kpoint_mp_offset.value == '0.0 0.0 0.0'
        atoms = ase.build.bulk('Ag')
        atoms.calc = c
        c.set_kpts({'density': 10, 'gamma': False, 'even': None})
        assert c.cell.kpoint_mp_grid.value == '27 27 27'
        assert c.cell.kpoint_mp_offset.value == '0.018519 0.018519 0.018519'
        c.set_kpts({
            'spacing': (1 / (np.pi * 10)),
            'gamma': False,
            'even': True
        })
        assert c.cell.kpoint_mp_grid.value == '28 28 28'
        assert c.cell.kpoint_mp_offset.value == '0.0 0.0 0.0'

    # test band structure setup
    from ase.dft.kpoints import BandPath
    atoms = ase.build.bulk('Ag')
    bp = BandPath(cell=atoms.cell,
                  path='GX',
                  special_points={
                      'G': [0, 0, 0],
                      'X': [0.5, 0, 0.5]
                  })
    bp = bp.interpolate(npoints=10)
    c = Castep(bandpath=bp)
    kpt_list = c.cell.bs_kpoint_list.value.split('\n')
    assert len(kpt_list) == 10
    assert list(map(float, kpt_list[0].split())) == [0., 0., 0.]
    assert list(map(float, kpt_list[-1].split())) == [0.5, 0.0, 0.5]
コード例 #19
0
    assert c.cell.kpoint_mp_grid.value == '2 2 2'
    assert c.cell.kpoint_mp_offset.value == '0.25 0.25 0.25'
    c.set_kpts({'size': (2, 2, 4), 'even': False})
    assert c.cell.kpoint_mp_grid.value == '3 3 5'
    assert c.cell.kpoint_mp_offset.value == '0.0 0.0 0.0'
    atoms = ase.build.bulk('Ag')
    atoms.set_calculator(c)
    c.set_kpts({'density': 10, 'gamma': False, 'even': None})
    assert c.cell.kpoint_mp_grid.value == '27 27 27'
    assert c.cell.kpoint_mp_offset.value == '0.018519 0.018519 0.018519'
    c.set_kpts({'spacing': (1 / (np.pi *10)), 'gamma': False, 'even': True})
    assert c.cell.kpoint_mp_grid.value == '28 28 28'
    assert c.cell.kpoint_mp_offset.value == '0.0 0.0 0.0'

# test band structure setup
from ase.dft.kpoints import BandPath
atoms = ase.build.bulk('Ag')
bp = BandPath(cell=atoms.cell,
              path='GX',
              special_points={'G': [0, 0, 0], 'X': [0.5, 0, 0.5]})
bp = bp.interpolate(npoints=10)
c = Castep(bandpath=bp)
kpt_list = c.cell.bs_kpoint_list.value.split('\n')
assert len(kpt_list) == 10
assert list(map(float, kpt_list[0].split())) == [0., 0., 0.]
assert list(map(float, kpt_list[-1].split())) == [0.5, 0.0, 0.5]

# cleanup
os.chdir(cwd)
shutil.rmtree(tmp_dir)
コード例 #20
0
def get_band_structure(atoms=None, calc=None, path=None, reference=None):
    """Create band structure object from Atoms or calculator."""
    # path 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 path is None:
        from ase.dft.kpoints import (BandPath, resolve_custom_points,
                                     find_bandpath_kinks)
        standard_path = atoms.cell.bandpath(npoints=0)
        # Kpoints are already evaluated, we just need to put them into
        # the path (whether they fit our idea of what the path is, or not).
        #
        # Depending on how the path was established, the kpoints might
        # be valid high-symmetry points, but since there are multiple
        # high-symmetry points of each type, they may not coincide
        # with ours if the bandpath was generated by another code.
        #
        # Here we hack it so the BandPath has proper points even if they
        # come from some weird source.
        #
        # This operation (manually hacking the bandpath) is liable to break.
        # TODO: Make it available as a proper (documented) bandpath method.
        kinks = find_bandpath_kinks(atoms.cell, kpts, eps=1e-5)
        pathspec, special_points = resolve_custom_points(
            kpts[kinks], standard_path.special_points, eps=1e-5)
        path = BandPath(standard_path.cell,
                        kpts=kpts,
                        path=pathspec,
                        special_points=special_points)

    # XXX If we *did* get the path, now would be a good time to check
    # that it matches the cell!  Although the path can only be passed
    # because we internally want to not re-evaluate the Bravais
    # lattice type.  (We actually need an eps parameter, too.)

    if reference is None:
        # Fermi level should come from the GS calculation, not the BS one!
        reference = calc.get_fermi_level()

    if reference is None:
        # Fermi level may not be available, e.g., with non-Fermi smearing.
        # XXX Actually get_fermi_level() should raise an error when Fermi
        # level wasn't available, so we should fix that.
        reference = 0.0

    return BandStructure(path=path, energies=energies, reference=reference)