Ejemplo n.º 1
0
    def calculate_bandstructure(self, bs):
        """ Returns a BandStructure object with a DFTB band structure.
        Assumes that the necessary *-*.skf files have been generated.

        bs: ase.dft.band_structure.BandStructure instance with an
            additional 'atoms' and 'kpts_scf' attributes. The latter
            represents the k-points to be used in the self-consistent
            calculation prior to the bandstructure calculation in DFTB.
        """
        # Perform a regular DFTB calculation first
        # to converge the charges and get the
        # reference energy
        atoms = bs.atoms.copy()
        calc = Dftb(atoms=atoms, kpts=bs.kpts_scf, **self.dftbplus_kwargs)
        atoms.set_calculator(calc)
        etot = atoms.get_potential_energy()

        efermi = calc.get_fermi_level()
        if bs.reference_level == 'vbm':
            eig = np.array(calc.results['eigenvalues'])
            eref = np.max(eig[eig < efermi])
        elif bs.reference_level == 'fermi':
            eref = efermi

        # Now a band structure calculation
        kwargs = self.dftbplus_kwargs.copy()
        kwargs.update({
            'Hamiltonian_MaxSCCIterations': 1,
            'Hamiltonian_ReadInitialCharges': 'Yes',
            'Hamiltonian_SCCTolerance': 1e6
        })
        calc = Dftb(atoms=atoms, kpts=bs.path.kpts, **kwargs)
        atoms.set_calculator(calc)
        etot = atoms.get_potential_energy()

        # Update the reference level, k-points,
        # and eigenenergies
        bs_new = copy.deepcopy(bs)
        #bs_new.reference = eref
        bs_new_reference = eref
        bs_new.kpts = calc.get_ibz_k_points()
        #bs_new.energies = []
        bs_new_energies = []

        for s in range(calc.get_number_of_spins()):
            #bs_new.energies.append([calc.get_eigenvalues(kpt=k, spin=s)
            bs_new_energies.append([
                calc.get_eigenvalues(kpt=k, spin=s)
                for k in range(len(bs_new.kpts))
            ])
        #bs_new.energies = np.array(bs_new.energies)
        bs_new_energies = np.array(bs_new_energies)

        return bs_new
Ejemplo n.º 2
0
if '17.1' not in version:
    msg = 'Band structure properties not present in results.tag for ' + version
    raise SkipTest(msg)

# The actual testing starts here
calc = Dftb(label='dftb',
            kpts=(3, 3, 3),
            Hamiltonian_SCC='Yes',
            Hamiltonian_SCCTolerance=1e-5,
            Hamiltonian_MaxAngularMomentum_Si='d')

atoms = bulk('Si')
atoms.set_calculator(calc)
atoms.get_potential_energy()

efermi = calc.get_fermi_level()
assert abs(efermi - -2.90086680996455) < 1.

# DOS does not currently work because of
# missing "get_k_point_weights" function
#from ase.dft.dos import DOS
#dos = DOS(calc, width=0.2)
#d = dos.get_dos()
#e = dos.get_energies()
#print(d, e)

calc = Dftb(atoms=atoms,
            label='dftb',
            kpts={
                'path': 'WGXWLG',
                'npoints': 50
Ejemplo n.º 3
0
def test_dftb_bandstructure():
    import os
    import subprocess
    from unittest import SkipTest
    from ase.test import require
    from ase.test.testsuite import datafiles_directory
    from ase.calculators.dftb import Dftb
    from ase.build import bulk

    require('dftb')

    os.environ['DFTB_PREFIX'] = datafiles_directory

    # We need to get the DFTB+ version to know
    # whether to skip this test or not.
    # For this, we need to run DFTB+ and grep
    # the version from the output header.
    cmd = os.environ['ASE_DFTB_COMMAND'].split()[0]
    proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)

    lines = ''
    for line in proc.stdout:
        l = line.decode()
        if 'DFTB+' in l and ('version' in l.lower() or 'release' in l.lower()):
            version = l[l.index('DFTB+'):]
            break
        lines += l + '\n'
    else:
        raise RuntimeError('Could not parse DFTB+ version ' + lines)

    if '17.1' not in version:
        msg = 'Band structure properties not present in results.tag for ' + version
        raise SkipTest(msg)

    # The actual testing starts here
    calc = Dftb(label='dftb',
                kpts=(3, 3, 3),
                Hamiltonian_SCC='Yes',
                Hamiltonian_SCCTolerance=1e-5,
                Hamiltonian_MaxAngularMomentum_Si='d')

    atoms = bulk('Si')
    atoms.set_calculator(calc)
    atoms.get_potential_energy()

    efermi = calc.get_fermi_level()
    assert abs(efermi - -2.90086680996455) < 1.

    # DOS does not currently work because of
    # missing "get_k_point_weights" function
    #from ase.dft.dos import DOS
    #dos = DOS(calc, width=0.2)
    #d = dos.get_dos()
    #e = dos.get_energies()
    #print(d, e)

    calc = Dftb(atoms=atoms,
                label='dftb',
                kpts={
                    'path': 'WGXWLG',
                    'npoints': 50
                },
                Hamiltonian_SCC='Yes',
                Hamiltonian_MaxSCCIterations=1,
                Hamiltonian_ReadInitialCharges='Yes',
                Hamiltonian_MaxAngularMomentum_Si='d')

    atoms.set_calculator(calc)
    calc.calculate(atoms)

    calc.results['fermi_levels'] = [efermi]
    calc.band_structure()