def efield(efield=0.05, n=30):
    printit('running GS calculation for {}'.format(efield))
    fname = "sb_relaxed.cif"
    a = read(fname)
    atom = read(fname)
    wire = make_supercell(atom, [[n, 0, 0], [0, 1, 0], [
                          0, 0, 1]], wrap=True, tol=1e-05)
    wire.center(vacuum=15, axis=0)
    a = wire.copy()
    if not os.path.isfile('gs_{}.gpw'.format(efield)):
        calc = GPAW(  # mode='lcao',
            mode='fd',
            basis='szp(dzp)',
            # eigensolver='cg',
            #mixer=Mixer(beta=0.2, nmaxold=3, weight=70.0),
            xc='PBE',
            # poissonsolver=DipoleCorrection(PoissonSolver(relax='GS'), 2),
            mixer=Mixer(beta=0.06, nmaxold=5, weight=100.0),
            occupations=FermiDirac(width=0.1),
            kpts={'density': 4.5},
            txt='gs_output_{}.txt'.format(efield),
            h=0.20,
            external=ConstantElectricField(efield, [0, 0, 1]))

        a.set_calculator(calc)
        a.get_potential_energy()
        calc.write('gs_{}.gpw'.format(efield))

    calc = GPAW('gs_{}.gpw'.format(efield),
                nbands=-100,
                fixdensity=True,
                symmetry='off',
                kpts={'path': 'XGX', 'npoints': 100},
                convergence={'bands': 'CBM+1'},
                txt='gs_output_{}.txt'.format(efield))
    calc.get_potential_energy()
    bs = calc.band_structure()
    bs.plot(filename='bandstructure_{}.png'.format(
        efield), show=False, emax=calc.get_fermi_level()+1, emin=calc.get_fermi_level()-1)
    bs.write('bs_{}.json'.format(
        efield))
    try:
        gap, p1, p2 = get_gap(calc)
        printit("{} {} {} {}".format(efield, gap, p1, p2), fname="gaps.dat")
    except:
        None
예제 #2
0
# Get the valence band maximum
efermi = calc.get_fermi_level()
Nk = len(calc.get_ibz_k_points())
Ns = calc.get_number_of_spins()
eigval = np.array([[calc.get_eigenvalues(kpt=k, spin=s) for k in range(Nk)]
                   for s in range(Ns)])
evbm = np.max(eigval[eigval < efermi])

# Next, a band structure calculation
calc.set(
    nbands=nbnd,  # 4 occupied and 4 unoccupied bands
    fixdensity=True,
    eigensolver=CG(niter=5),
    symmetry='off',
    kpts={
        'path': spath,
        'npoints': 50
    },
    convergence={'bands': 'all'},
)
calc.get_potential_energy()

bs_gpaw = calc.band_structure()
#bs_gpaw.reference = evbm
bs_gpaw_reference = evbm
bs_gpaw.plot(filename='bs_gpaw_data.png',
             show=False,
             emax=evbm + 5.,
             emin=evbm - 15.)
write_json('bs_gpaw.json', bs_gpaw)
예제 #3
0
from gpaw import GPAW

calc = GPAW('groundstate.rutile.gpw')
atoms = calc.get_atoms()
path = calc.bandpath(density=7)
path.write('path.rutile.json')

calc.set(kpts=path, fixdensity=True, symmetry='off')

atoms.get_potential_energy()
bs = calc.band_structure()
bs.write('bs.rutile.json')
예제 #4
0
    e = atom.get_potential_energy()
    calc.write('coo_gs.gpw')
    parprint("total energy = {}".format(e))

    calc.set(nbands='nao',
             fixdensity=True,
             symmetry='off',
             kpts={
                 'path': atom.cell.bandpath().path,
                 'npoints': 200
             },
             convergence={'bands': 'all'})

    calc.get_potential_energy()
    calc.write('coo_bands.gpw')
    bs = calc.band_structure()
    with open('band_energies.pickle', 'wb') as handle:
        pickle.dump(calc.band_structure().todict(),
                    handle,
                    protocol=pickle.HIGHEST_PROTOCOL)
    bs.plot(filename='bandstructure.png',
            show=False,
            emax=8.0,
            emin=-8.0,
            reference=8.84354)

else:
    atom = read("sqs_coo.cif")
    parprint("Reading from restart file")
    calc = GPAW('coo_gs.gpw',
                nbands='nao',
예제 #5
0
    def test_bs(self):
        sb = StructureBuilder()
        atoms, *_ = sb.get_structure("Si", "diamond")
        # print(atoms)
        base_dir = os.path.join(os.path.dirname(__file__),
                                "../../tmp/Si-class/")
        m_calc = MaterCalc(atoms=atoms, base_dir=base_dir)
        self.assertTrue(m_calc.relax(fmax=0.002))  # Very tight limit!
        self.assertTrue(m_calc.ground_state())
        # get the PBE BS
        lattice_type = get_cellinfo(m_calc.atoms.cell).lattice
        self.assertTrue(lattice_type in special_paths.keys())
        kpts_bs = dict(path=special_paths[lattice_type], npoints=120)
        gpw_name = os.path.join(base_dir, "gs.gpw")
        self.assertTrue(os.path.exists(gpw_name))
        calc_bs = GPAW(restart=gpw_name,
                       kpts=kpts_bs,
                       fixdensity=True,
                       symmetry='off',
                       txt=os.path.join(base_dir, "pbe-bs.txt"))
        calc_bs.get_potential_energy()
        # PBE bandgap
        bg_pbe_min, *_ = bandgap(calc_bs, direct=False)
        bg_pbe_dir, *_ = bandgap(calc_bs, direct=True)
        calc_bs.write(os.path.join(base_dir, "pbe-bs.gpw"))
        bs_pbe = calc_bs.band_structure()
        bs_pbe.plot(emin=-10,
                    emax=10,
                    filename=os.path.join(base_dir, "pbe-bs.png"))

        # get the gllbsc by steps
        calc_ = GPAW(restart=gpw_name)
        calc_gllb = GPAW(**calc_.parameters)
        calc_gllb.set(xc="GLLBSC", txt=os.path.join(base_dir, "gllb-gs.txt"))
        calc_gllb.atoms = calc_.atoms
        del calc_
        calc_gllb.get_potential_energy()  # SC calculation
        calc_gllb.write("gllb-gs.gpw")
        calc_gllb_bs = GPAW(restart="gllb-gs.gpw",
                            kpts=kpts_bs,
                            fixdensity=True,
                            symmetry="off",
                            txt=os.path.join(base_dir, "gllb-bs.txt"))
        world.barrier()
        calc_gllb_bs.get_potential_energy()
        homolumo = calc_gllb_bs.get_homo_lumo()
        bg_gllb_ks = homolumo[1] - homolumo[0]
        response = calc_gllb_bs.hamiltonian.xc.xcs["RESPONSE"]
        response.calculate_delta_xc(homolumo / Ha)
        EKs, Dxc = response.calculate_delta_xc_perturbation()
        bg_gllb_deltaxc = EKs + Dxc

        ibz_kpts = calc_gllb_bs.get_ibz_k_points()
        e_kn = numpy.array([calc_gllb_bs.get_eigenvalues(kpt=k) \
                            for k in range(len(ibz_kpts))])
        efermi = calc_gllb_bs.get_fermi_level()
        e_kn[e_kn > efermi] += Dxc
        bg_gllb_min, *_ = bandgap(eigenvalues=e_kn,
                                  efermi=efermi,
                                  direct=False)
        bg_gllb_dir, *_ = bandgap(eigenvalues=e_kn, efermi=efermi, direct=True)

        parprint("PBE: E_min \t E_dir")
        parprint("{:.3f}\t{:.3f}".format(bg_pbe_min, bg_pbe_dir))
        parprint("Gllb: EKS \t E_deltaxc")
        parprint("{:.3f}\t{:.3f}".format(bg_gllb_ks, bg_gllb_deltaxc))
        parprint("Gllb: E_min \t E_dir")
        parprint("{:.3f}\t{:.3f}".format(bg_gllb_min, bg_gllb_dir))
        bs_gllb = calc_gllb_bs.band_structure()
        bs_gllb.energies[bs_gllb.energies > bs_gllb.reference] += Dxc
        bs_gllb.plot(emin=-10,
                     emax=10,
                     filename=os.path.join(base_dir, "gllb-bs.png"))

        calc_gllb_bs.write(os.path.join(base_dir, "gllb-bs.gpw"))
예제 #6
0
def _main():
    si = make_Si_cell()

    # First step: find the ground-state charge density.
    # Use plane-wave basis with 200 eV wavefunction cutoff energy.
    # Cutoff energy should be chosen such that the error introduced by the incompleteness
    # of the basis is not too high.
    # The appropriate energy is different for each atom.
    # See here: https://wiki.fysik.dtu.dk/gpaw/setups/Si.html
    calc = GPAW(
        mode=PW(200),
        # PBE exchange-correlation functional
        xc='PBE',
        # Sample the Brillouin zone with 8 k-points in each reciprocal lattice direction
        kpts=(8, 8, 8),
        # Smear step functions appearing in Brillouin zone integrals using Fermi-Dirac
        # distribution at temperature k_B T = 0.01 eV.
        occupations=FermiDirac(0.01),
        # Start calculation using random wavefunctions.
        # We have a physically-reasonable initial value for the charge density based
        # on the atomic positions.
        # The Hamiltonian is diagonalized iteratively, so we also need an initial guess for
        # the wavefunctions. Random starting wavefunctions generally work well.
        random=True,
        # Set the log file for the ground-state DFT calculation.
        txt="Si_gs.txt")

    si.calc = calc
    # To make GPAW perform the DFT calculation, we need to ask it for something
    # that it needs to perform the calculation to know.
    si.get_potential_energy()
    # Save the result for the ground state so we can load it later.
    ground_state_file = "Si_gs.gpw"
    calc.write(ground_state_file)

    # Second step: using the converged ground-state charge density, calculate the
    # wavefunctions along a high-symmetry path in the Brilllouin zone.
    # The energies along this path give the band structure diagram.
    calc = GPAW(
        ground_state_file,
        # Include the 16 lowest-energy valence bands in the calculation.
        nbands=16,
        # Keep the charge density constant, using our converged ground-state density.
        fixdensity=True,
        # Don't consider symmetry in the k-point distribution: we want to use exactly
        # the k-points we specify.
        # (In the ground-state calculation, many k-points can be eliminated due to
        # being redundant by symmetry.)
        symmetry='off',
        # Use a high-symmetry k-point path.
        # High-symmetry paths following the [SC10] convention for band structure are
        # built-in (can use these if our unit cell also follows the [SC10] convention).
        # Use 300 k-points total.
        kpts={
            'path': special_paths['fcc'],
            'npoints': 300
        },
        # Require that the energies of the lowest 8 bands are well-converged.
        convergence={'bands': 8},
        # Set the log file for the band-structure calculation.
        txt="Si_bands.txt")

    # Make GPAW perform the band-structure calculation.
    calc.get_potential_energy()

    # Plot the band structure.
    # Since we used kpoints={'path': ...}, we can use an ASE convenience function for this.
    bs = calc.band_structure()
    bs.plot(filename="Si_bands.png")
예제 #7
0
from gpaw import GPAW

# Restart from ground state and fix potential:
calc = GPAW("Si_gs.gpw",
            nbands=16,
            fixdensity=True,
            symmetry="off",
            kpts={"path": "GXWKL", "npoints": 60},
            convergence={"bands": 8},
            txt="LOG_Si_bands.txt")
calc.get_potential_energy()

bs = calc.band_structure() # band structure info, such as energies, path, etc
bs.plot(filename="bandstructure.png", emax=10.0)

calc.write("Si_bands.gpw")
예제 #8
0
    def bandgap(self, method="GLLB", save=True, skip=False):
        # Check method input
        method = method.strip().lower()
        if method not in ("pbe", "gllb", "hse", "gw"):
            raise ValueError("Method for bandgap calculation not known!")
        # Check ground state
        if not os.path.exists(self.__gs_file):
            raise FileNotFoundError("Ground state not calculated!")

        # Check bandgap?
        self.__bg_file = self.__bg_file_template.format(method)
        if os.path.exists(self.__bg_file):
            parprint(
                "Bandgap for method {} is already calculated!".format(method))
            data = numpy.load(self.__bg_file)
            return data["Eg_min"], data["Eg_dir"], None

        # Real calculation now

        if method == "pbe":
            # Use band_structure or simple sampling kpts?
            calc = GPAW(restart=self.__gs_file)
            try:
                lattice_type = get_cellinfo(calc.atoms.cell).lattice
                use_bs = lattice_type in special_paths.keys()
            except (ValueError, AssertionError):  # Monolithic cell?
                use_bs = False
            parprint("Use bandpath?", use_bs)
            if use_bs:
                kpts = dict(path=special_paths[lattice_type],
                            npoints=self.params["gap"][method]["npoints"])
                calc.set(kpts=kpts, fixdensity=True, symmetry="off",
                         txt=None)  # non-SC
            calc.get_potential_energy(
            )  # Otherwise the wavefunction not known?
            bg_min, *_ = bg(calc, direct=False)
            bg_dir, *_ = bg(calc, direct=True)
            # Possibly no gap
            if bg_min is None:
                bg_min = 0
            if bg_dir is None:
                bg_dir = 0
            if use_bs:
                bs = calc.band_structure()
                xcoords, label_xcoords, labels = bs.get_labels()
                res_bs = bs.todict()
                res_bs.update(xcoords=xcoords,
                              label_xcoords=label_xcoords,
                              labels=labels)
            else:
                res_bs = {}  # no result
            if save:
                if rank == 0:
                    numpy.savez(self.__bg_file,
                                Eg_min=bg_min,
                                Eg_dir=bg_dir,
                                **res_bs)
                    print("Bandgap saved!")
            world.barrier()
            return bg_min, bg_dir, res_bs
        elif method == "gllb":
            # Need to restart the SC calculation
            if not os.path.exists(self.__gs_gllb_file):
                if not os.path.exists(self.__relaxed_gllb_traj):
                    self.relax(fmax=0.002, steps=200, xc="gllb", skip=skip)
                world.barrier()
                atoms = read(self.__relaxed_gllb_traj)
                calc = GPAW(**self.params["gs"],
                            txt=os.path.join(self.__base_dir, "gs_gllb.txt"))
                atoms.set_calculator(calc)
                calc.set(xc="GLLBSC")
                atoms.get_potential_energy()  # Recalculate GS
                calc.write(self.__gs_gllb_file, mode="all")
            #TODO: merge with PBE method
            calc_bs = GPAW(restart=self.__gs_gllb_file)
            try:
                lattice_type = get_cellinfo(calc_bs.atoms.cell).lattice
                use_bs = lattice_type in special_paths.keys()
            except (ValueError, AssertionError):  # Monolithic cell?
                use_bs = False
            if use_bs:
                kpts = dict(path=special_paths[lattice_type],
                            npoints=self.params["gap"][method]["npoints"])
                calc_bs.set(kpts=kpts, fixdensity=True, symmetry="off")
            calc_bs.get_potential_energy()
            homolumo = calc_bs.get_homo_lumo()
            response = calc_bs.hamiltonian.xc.xcs["RESPONSE"]
            response.calculate_delta_xc(homolumo / Ha)
            EKs, Dxc = response.calculate_delta_xc_perturbation()
            ns = calc_bs.get_number_of_spins()
            nk = len(calc_bs.get_ibz_k_points())
            e_kn = numpy.array([[calc_bs.get_eigenvalues(kpt=k, spin=s) \
                                for k in range(nk)] for s in range(ns)])
            efermi = calc_bs.get_fermi_level()
            e_kn[e_kn > efermi] += Dxc
            bg_gllb_min, *_ = bg(eigenvalues=e_kn, efermi=efermi, direct=False)
            bg_gllb_dir, *_ = bg(eigenvalues=e_kn, efermi=efermi, direct=True)
            if bg_gllb_min is None:
                bg_gllb_min = 0
            if bg_gllb_dir is None:
                bg_gllb_dir = 0
            if use_bs:
                bs = calc_bs.band_structure()
                bs.energies[bs.energies >
                            bs.reference] += Dxc  # Shift gllbsc discontinuous
                res_bs = bs.todict()
                xcoords, label_xcoords, labels = bs.get_labels()
                res_bs.update(xcoords=xcoords,
                              label_xcoords=label_xcoords,
                              labels=labels)
            else:
                res_bs = {}
            if save:
                if rank == 0:
                    numpy.savez(self.__bg_file,
                                Eg_min=bg_gllb_min,
                                Eg_dir=bg_gllb_dir,
                                **res_bs)
                    print("Bandgap saved!")
            world.barrier()
            return bg_gllb_min, bg_gllb_dir, res_bs
        else:
            raise NotImplementedError("Method not implemented yet")