Comparison of DFT solvers
We compare four different approaches for solving the DFT minimisation problem, namely a density-based SCF, a potential-based SCF, direct minimisation and Newton.
First we setup our problem
using AtomsBuilder
using DFTK
using LinearAlgebra
using PseudoPotentialData
pseudopotentials = PseudoFamily("dojo.nc.sr.pbesol.v0_4_1.standard.upf")
model = model_DFT(bulk(:Si); functionals=PBEsol(), pseudopotentials)
basis = PlaneWaveBasis(model; Ecut=5, kgrid=[3, 3, 3])
# Convergence we desire in the density
tol = 1e-6
1.0e-6
Density-based self-consistent field
scfres_scf = self_consistent_field(basis; tol);
n Energy log10(ΔE) log10(Δρ) Diag Δtime
--- --------------- --------- --------- ---- ------
1 -8.397832316710 -0.90 5.2 26.0ms
2 -8.400249715097 -2.62 -1.74 1.0 18.6ms
3 -8.400396471887 -3.83 -2.93 1.2 19.0ms
4 -8.400427756780 -4.50 -2.91 3.2 24.0ms
5 -8.400427735293 + -7.67 -2.87 1.0 18.7ms
6 -8.400428139521 -6.39 -4.71 1.0 18.6ms
7 -8.400428151262 -7.93 -4.24 3.2 24.4ms
8 -8.400428152110 -9.07 -4.82 1.0 18.9ms
9 -8.400428152203 -10.03 -6.19 1.0 18.9ms
Potential-based SCF
scfres_scfv = DFTK.scf_potential_mixing(basis; tol);
n Energy log10(ΔE) log10(Δρ) α Diag Δtime
--- --------------- --------- --------- ---- ---- ------
1 -8.397899464944 -0.90 5.2 25.8ms
2 -8.400380603671 -2.61 -1.79 0.80 2.0 18.5ms
3 -8.400422357394 -4.38 -2.99 0.80 1.0 15.9ms
4 -8.400428112794 -5.24 -3.42 0.80 2.5 26.8ms
5 -8.400428149317 -7.44 -4.61 0.80 1.2 16.7ms
6 -8.400428152187 -8.54 -5.46 0.80 2.5 19.9ms
7 -8.400428152209 -10.67 -6.55 0.80 2.0 19.0ms
Direct minimization
scfres_dm = direct_minimization(basis; tol);
┌ Warning: x_tol is deprecated. Use x_abstol or x_reltol instead. The provided value (-1) will be used as x_abstol.
└ @ Optim ~/.julia/packages/Optim/7krni/src/types.jl:110
┌ Warning: f_tol is deprecated. Use f_abstol or f_reltol instead. The provided value (-1) will be used as f_reltol.
└ @ Optim ~/.julia/packages/Optim/7krni/src/types.jl:120
n Energy log10(ΔE) log10(Δρ) Δtime
--- --------------- --------- --------- ------
1 +1.109720647556 -1.04 57.3ms
2 -1.962300952921 0.49 -0.66 32.2ms
3 -4.641112157590 0.43 -0.39 43.6ms
4 -6.316372936990 0.22 -0.49 43.2ms
5 -7.676258225102 0.13 -0.80 43.4ms
6 -8.067048047519 -0.41 -1.28 38.0ms
7 -8.241133048312 -0.76 -1.63 32.1ms
8 -8.310313004885 -1.16 -1.81 32.3ms
9 -8.343811762567 -1.47 -2.22 32.1ms
10 -8.364106631311 -1.69 -2.10 32.1ms
11 -8.379746791098 -1.81 -2.28 32.3ms
12 -8.391768082365 -1.92 -3.16 32.1ms
13 -8.396917669315 -2.29 -2.85 32.1ms
14 -8.398610759630 -2.77 -3.03 37.0ms
15 -8.399795177743 -2.93 -3.62 32.1ms
16 -8.400081880545 -3.54 -3.52 32.2ms
17 -8.400278262870 -3.71 -3.65 32.4ms
18 -8.400343984104 -4.18 -3.45 32.5ms
19 -8.400399933432 -4.25 -3.88 32.2ms
20 -8.400413847120 -4.86 -3.98 36.3ms
21 -8.400422831137 -5.05 -4.19 33.0ms
22 -8.400425967139 -5.50 -4.48 32.1ms
23 -8.400427253127 -5.89 -4.89 32.3ms
24 -8.400427813933 -6.25 -4.70 32.8ms
25 -8.400428016677 -6.69 -5.30 36.1ms
26 -8.400428096733 -7.10 -4.91 32.3ms
27 -8.400428125918 -7.53 -5.29 32.1ms
28 -8.400428142908 -7.77 -5.45 32.3ms
29 -8.400428148209 -8.28 -5.69 36.1ms
30 -8.400428150667 -8.61 -6.08 32.2ms
Newton algorithm
Start not too far from the solution to ensure convergence: We run first a very crude SCF to get close and then switch to Newton.
scfres_start = self_consistent_field(basis; tol=0.5);
n Energy log10(ΔE) log10(Δρ) Diag Δtime
--- --------------- --------- --------- ---- ------
1 -8.397893771370 -0.90 5.2 26.1ms
Remove the virtual orbitals (which Newton cannot treat yet)
ψ = DFTK.select_occupied_orbitals(basis, scfres_start.ψ, scfres_start.occupation).ψ
scfres_newton = newton(basis, ψ; tol);
n Energy log10(ΔE) log10(Δρ) Δtime
--- --------------- --------- --------- ------
1 -8.400427986614 -1.79 588ms
2 -8.400428152209 -6.78 -4.03 395ms
3 -8.400428152209 -14.45 -7.85 102ms
Comparison of results
println("|ρ_newton - ρ_scf| = ", norm(scfres_newton.ρ - scfres_scf.ρ))
println("|ρ_newton - ρ_scfv| = ", norm(scfres_newton.ρ - scfres_scfv.ρ))
println("|ρ_newton - ρ_dm| = ", norm(scfres_newton.ρ - scfres_dm.ρ))
|ρ_newton - ρ_scf| = 2.1741810733380497e-6
|ρ_newton - ρ_scfv| = 2.2735654124514448e-7
|ρ_newton - ρ_dm| = 3.1686578272393646e-6