# Pseudopotentials¶

In this example, we'll look at how to use various pseudopotential (PSP) formats in DFTK and discuss briefly the utility and importance of pseudopotentials.

Currently, DFTK supports norm-conserving (NC) PSPs in separable (Kleinman-Bylander) form. Two file formats can currently be read and used: analytical Hartwigsen-Goedecker-Hutter (HGH) PSPs and numeric Unified Pseudopotential Format (UPF) PSPs.

In brief, the pseudopotential approach replaces the all-electron atomic potential with an effective atomic potential. In this pseudopotential, tightly-bound core electrons are completely eliminated ("frozen") and chemically-active valence electron wavefunctions are replaced with smooth pseudo-wavefunctions whose Fourier representations decay quickly. Both these transformations aim at reducing the number of Fourier modes required to accurately represent the wavefunction of the system, greatly increasing computational efficiency.

Different PSP generation codes produce various file formats which contain the same general quantities required for pesudopotential evaluation. HGH PSPs are constructed from a fixed functional form based on Gaussians, and the files simply tablulate various coefficients fitted for a given element. UPF PSPs take a more flexible approach where the functional form used to generate the PSP is arbitrary, and the resulting functions are tabulated on a radial grid in the file. The UPF file format is documented here: http://pseudopotentials.quantum-espresso.org/home/unified-pseudopotential-format.

In this example, we will compare the convergence of an analytical HGH PSP with a modern UPF PSP from PseudoDojo. Then, we will compare the bandstructure at the converged parameters calculated using the two PSPs.

In [1]:
using DFTK
using Unitful
using Plots


Here, we will use Perdew-Wang LDA PSP from PseudoDojo, which is available in the JuliaMolSim PseudoLibrary.

In [2]:
PSEUDOLIB = "https://raw.githubusercontent.com/JuliaMolSim/PseudoLibrary"
URL_UPF = PSEUDOLIB * "/\$COMMIT/pseudos/pd_nc_sr_lda_standard_04_upf/Li.upf";


We load the HGH and UPF PSPs using load_psp, which determines the file format using the file extension.

In [3]:
psp_hgh  = load_psp("hgh/lda/li-q3.hgh");


First, we'll take a look at the energy cutoff convergence of these two pseudopotentials. For both pseudos, a reference energy is calculated with a cutoff of 140 Hartree, and SCF calculations are run at increasing cutoffs until 1 meV / atom convergence is reached.

The converged cutoffs are 128 Ha and 36 Ha for the HGH and UPF pseudos respectively. We see that the HGH pseudopotential is much harder, i.e. it requires a higher energy cutoff, than the UPF PSP. In general, numeric pseudopotentials tend to be softer than analytical pseudos because of the flexibility of sampling arbitrary functions on a grid.

Next, to see that the different pseudopotentials give reasonbly similar results, we'll look at the bandstructures calculated using the HGH and UPF PSPs. Even though the convered cutoffs are 128 and 36 Ha, we perform these calculations with a cutoff of 24 Ha for both PSPs.

In [4]:
function run_bands(psp)
a = -1.53877u"Å"
b = -2.66523u"Å"
c = -4.92295u"Å"
lattice = [ a  a  0;
-b  b  0;
0  0 -c]
Li = ElementPsp(:Li; psp)
atoms     = [Li, Li]
positions = [[1/3, 2/3, 1/4],
[2/3, 1/3, 3/4]]

# These are (as you saw above) completely unconverged parameters
model = model_LDA(lattice, atoms, positions; temperature=1e-2)
basis = PlaneWaveBasis(model; Ecut=24, kgrid=(6, 6, 4))

scfres   = self_consistent_field(basis, tol=1e-6)
bandplot = plot_bandstructure(scfres)
(; scfres, bandplot)
end;


The SCF and bandstructure calculations can then be performed using the two PSPs, where we notice in particular the difference in total energies.

In [5]:
result_hgh = run_bands(psp_hgh)
result_hgh.scfres.energies

n     Energy            log10(ΔE)   log10(Δρ)   Diag
---   ---------------   ---------   ---------   ----
1   -13.91963496198                   -0.12    5.2
2   -13.98182935635       -1.21       -0.71    1.9
3   -13.98666547824       -2.32       -1.54    2.6
4   -13.98668188963       -4.78       -2.29    1.4
5   -13.98668234457       -6.34       -2.98    4.1
Computing bands along kpath:
Γ -> M -> K -> Γ -> A -> L -> H -> A  and  L -> M  and  H -> K
Diagonalising Hamiltonian kblocks: 100%|████████████████| Time: 0:00:22

Out[5]:
Energy breakdown (in Ha):
Kinetic             11.3780390
AtomicLocal         -20.7887917
AtomicNonlocal      0.0000000
Ewald               -5.0511706
PspCorrection       -0.0009254
Hartree             3.7112083
Xc                  -3.2265180
Entropy             -0.0085239

total               -13.986682344568
In [6]:
result_upf = run_bands(psp_upf)
result_upf.scfres.energies

n     Energy            log10(ΔE)   log10(Δρ)   Diag
---   ---------------   ---------   ---------   ----
1   -14.14867293574                   -0.15    5.2
2   -14.21785957090       -1.16       -0.76    2.0
3   -14.22231392669       -2.35       -1.54    2.5
4   -14.22233970944       -4.59       -2.63    2.0
5   -14.22234164100       -5.71       -2.95    3.1
6   -14.22234169328       -7.28       -4.13    2.4
Computing bands along kpath:
Γ -> M -> K -> Γ -> A -> L -> H -> A  and  L -> M  and  H -> K
Diagonalising Hamiltonian kblocks: 100%|████████████████| Time: 0:00:21

Out[6]:
Energy breakdown (in Ha):
Kinetic             10.2237942
AtomicLocal         -10.9141379
AtomicNonlocal      -8.9742118
Ewald               -5.0511706
PspCorrection       0.1151544
Hartree             3.5205498
Xc                  -3.1341366
Entropy             -0.0081831

total               -14.222341693279

But while total energies are not physical and thus allowed to differ, the bands (as an example for a physical quantity) are very similar for both pseudos:

In [7]:
plot(result_hgh.bandplot, result_upf.bandplot, titles=["HGH" "UPF"], size=(800, 400))

Out[7]: