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.397646196048 -0.90 5.2 24.3ms
2 -8.400230471764 -2.59 -1.72 1.0 18.0ms
3 -8.400396267974 -3.78 -2.97 1.0 17.9ms
4 -8.400427701261 -4.50 -2.91 3.0 22.2ms
5 -8.400428058299 -6.45 -3.26 1.0 81.2ms
6 -8.400428148881 -7.04 -4.81 1.0 18.1ms
7 -8.400428151910 -8.52 -4.55 2.8 21.9ms
8 -8.400428152174 -9.58 -5.00 1.2 19.4ms
9 -8.400428152208 -10.48 -6.57 1.0 18.4ms
Potential-based SCF
scfres_scfv = DFTK.scf_potential_mixing(basis; tol);n Energy log10(ΔE) log10(Δρ) α Diag Δtime
--- --------------- --------- --------- ---- ---- ------
1 -8.397600897681 -0.90 5.2 1.61s
2 -8.400387990954 -2.55 -1.78 0.80 2.0 1.04s
3 -8.400423917409 -4.44 -2.95 0.80 1.0 195ms
4 -8.400428114454 -5.38 -3.51 0.80 2.2 19.1ms
5 -8.400428149719 -7.45 -4.83 0.80 1.2 16.9ms
6 -8.400428152199 -8.61 -5.44 0.80 3.0 20.3ms
7 -8.400428152209 -11.02 -6.25 0.80 1.5 17.2ms
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 +1.089786769601 -1.01 3.21s
2 -1.434472443980 0.40 -0.61 148ms
3 -3.988566399645 0.41 -0.35 47.6ms
4 -5.425211978186 0.16 -0.39 46.9ms
5 -7.223129113687 0.25 -0.58 46.8ms
6 -7.846388837815 -0.21 -1.08 83.3ms
7 -8.061205871455 -0.67 -1.21 35.0ms
8 -8.220554323183 -0.80 -1.64 34.8ms
9 -8.284277443722 -1.20 -1.86 34.8ms
10 -8.336654019924 -1.28 -1.97 34.6ms
11 -8.363565859038 -1.57 -2.08 35.1ms
12 -8.385182385322 -1.67 -2.24 59.7ms
13 -8.393145708141 -2.10 -2.74 35.1ms
14 -8.397233260440 -2.39 -2.91 35.0ms
15 -8.398694489326 -2.84 -3.02 35.0ms
16 -8.399496298273 -3.10 -3.34 35.0ms
17 -8.399916967296 -3.38 -3.13 34.9ms
18 -8.400201448867 -3.55 -3.37 42.2ms
19 -8.400350190603 -3.83 -3.93 35.0ms
20 -8.400397705073 -4.32 -3.98 35.0ms
21 -8.400417006184 -4.71 -4.41 34.7ms
22 -8.400424343849 -5.13 -4.17 34.7ms
23 -8.400426702520 -5.63 -4.51 39.9ms
24 -8.400427557130 -6.07 -4.45 35.1ms
25 -8.400427948114 -6.41 -5.35 35.2ms
26 -8.400428044986 -7.01 -4.80 35.2ms
27 -8.400428122804 -7.11 -5.56 37.4ms
28 -8.400428139869 -7.77 -5.16 40.2ms
29 -8.400428148325 -8.07 -5.94 35.1ms
30 -8.400428150183 -8.73 -5.82 35.0ms
31 -8.400428151585 -8.85 -6.77 35.0ms
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.397604435974 -0.90 5.2 48.2ms
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.400427976858 -1.79 8.80s
2 -8.400428152209 -6.76 -4.02 3.29s
3 -8.400428152209 -14.75 -7.83 104ms
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.092543598911769e-7
|ρ_newton - ρ_scfv| = 4.075536574504995e-7
|ρ_newton - ρ_dm| = 8.006918754912265e-7