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-61.0e-6Density-based self-consistent field
scfres_scf = self_consistent_field(basis; tol);n Energy log10(ΔE) log10(Δρ) Diag Δtime
--- --------------- --------- --------- ---- ------
1 -8.397851962696 -0.90 5.5 27.3ms
2 -8.400249413406 -2.62 -1.74 1.0 18.1ms
3 -8.400405454081 -3.81 -2.97 1.5 19.2ms
4 -8.400427869000 -4.65 -2.97 3.2 23.8ms
5 -8.400427950075 -7.09 -3.03 1.0 18.2ms
6 -8.400428145736 -6.71 -4.74 1.0 18.4ms
7 -8.400428151824 -8.22 -4.47 2.8 23.3ms
8 -8.400428152193 -9.43 -5.44 1.0 18.5ms
9 -8.400428152208 -10.82 -6.07 1.8 20.6ms
Potential-based SCF
scfres_scfv = DFTK.scf_potential_mixing(basis; tol);n Energy log10(ΔE) log10(Δρ) α Diag Δtime
--- --------------- --------- --------- ---- ---- ------
1 -8.397814467753 -0.90 5.0 1.70s
2 -8.400384887702 -2.59 -1.79 0.80 2.0 500ms
3 -8.400422719182 -4.42 -3.05 0.80 1.0 218ms
4 -8.400428110073 -5.27 -3.43 0.80 2.5 20.9ms
5 -8.400428148986 -7.41 -4.51 0.80 1.2 17.3ms
6 -8.400428152174 -8.50 -5.37 0.80 2.2 20.2ms
7 -8.400428152208 -10.47 -6.61 0.80 2.0 19.8ms
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/gmigl/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/gmigl/src/types.jl:120
n Energy log10(ΔE) log10(Δρ) Δtime
--- --------------- --------- --------- ------
1 +0.808857559312 -1.13 3.39s
2 -1.848929498169 0.42 -0.65 151ms
3 -4.989621271578 0.50 -0.36 43.5ms
4 -6.622388116710 0.21 -0.51 168ms
5 -7.825305257357 0.08 -0.83 43.7ms
6 -8.135342528174 -0.51 -1.27 32.5ms
7 -8.238179142487 -0.99 -1.72 32.8ms
8 -8.303041387494 -1.19 -1.99 32.2ms
9 -8.323745433133 -1.68 -2.22 32.3ms
10 -8.348920508014 -1.60 -2.40 32.3ms
11 -8.369628501606 -1.68 -2.13 32.5ms
12 -8.384919945107 -1.82 -2.03 32.0ms
13 -8.392329821416 -2.13 -2.66 77.7ms
14 -8.397135701883 -2.32 -2.76 32.5ms
15 -8.398996916706 -2.73 -2.90 32.5ms
16 -8.399902168165 -3.04 -3.26 32.4ms
17 -8.400193754581 -3.54 -3.30 32.5ms
18 -8.400337855633 -3.84 -3.52 32.3ms
19 -8.400393607760 -4.25 -3.82 32.1ms
20 -8.400414918268 -4.67 -3.81 32.1ms
21 -8.400421853245 -5.16 -3.96 38.9ms
22 -8.400425373892 -5.45 -4.58 32.2ms
23 -8.400426902177 -5.82 -4.70 32.3ms
24 -8.400427533393 -6.20 -4.74 32.7ms
25 -8.400427894648 -6.44 -4.89 32.3ms
26 -8.400428043998 -6.83 -5.04 32.0ms
27 -8.400428109913 -7.18 -5.33 32.2ms
28 -8.400428132398 -7.65 -5.31 39.7ms
29 -8.400428144216 -7.93 -5.83 32.4ms
30 -8.400428147945 -8.43 -5.86 32.4ms
31 -8.400428150415 -8.61 -6.21 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.397819497038 -0.90 5.2 50.4ms
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.400427965688 -1.78 11.4s
2 -8.400428152209 -6.73 -4.01 3.67s
3 -8.400428152209 -14.45 -7.78 90.0ms
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| = 3.6306445100299206e-7
|ρ_newton - ρ_scfv| = 2.2144158228218754e-7
|ρ_newton - ρ_dm| = 1.5351451977452087e-6