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.397843450839 -0.90 5.2 27.3ms
2 -8.400236257349 -2.62 -1.74 1.0 78.8ms
3 -8.400406924908 -3.77 -2.97 1.5 20.8ms
4 -8.400427865047 -4.68 -3.01 3.2 25.4ms
5 -8.400427969456 -6.98 -3.08 1.0 19.9ms
6 -8.400428146645 -6.75 -4.61 1.0 19.9ms
7 -8.400428151839 -8.28 -4.50 2.2 23.6ms
8 -8.400428152173 -9.48 -5.05 1.0 19.9ms
9 -8.400428152206 -10.48 -6.13 1.0 49.5ms
Potential-based SCF
scfres_scfv = DFTK.scf_potential_mixing(basis; tol);n Energy log10(ΔE) log10(Δρ) α Diag Δtime
--- --------------- --------- --------- ---- ---- ------
1 -8.397855275854 -0.90 5.2 1.69s
2 -8.400386008693 -2.60 -1.79 0.80 2.0 482ms
3 -8.400423470890 -4.43 -2.98 0.80 1.0 216ms
4 -8.400428092439 -5.34 -3.43 0.80 2.2 96.9ms
5 -8.400428149826 -7.24 -4.53 0.80 1.2 18.1ms
6 -8.400428152183 -8.63 -5.85 0.80 2.2 20.2ms
7 -8.400428152209 -10.59 -6.11 0.80 3.2 22.6ms
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.921715324439 -1.05 3.33s
2 -1.016226088281 0.29 -0.66 204ms
3 -4.311415988979 0.52 -0.34 43.5ms
4 -5.454148747734 0.06 -0.46 43.1ms
5 -7.454053876390 0.30 -0.56 43.2ms
6 -7.599500262128 -0.84 -1.36 32.1ms
7 -8.142760096497 -0.26 -1.56 58.5ms
8 -8.242616770017 -1.00 -1.84 32.1ms
9 -8.307469131809 -1.19 -2.20 31.9ms
10 -8.341032440902 -1.47 -2.05 32.1ms
11 -8.365908391247 -1.60 -2.26 31.9ms
12 -8.382859004430 -1.77 -2.18 31.8ms
13 -8.392276611469 -2.03 -2.40 37.7ms
14 -8.397821152092 -2.26 -2.60 32.0ms
15 -8.399240425245 -2.85 -2.85 31.9ms
16 -8.399900520381 -3.18 -3.47 31.9ms
17 -8.400189380011 -3.54 -3.30 31.9ms
18 -8.400339579900 -3.82 -3.62 36.4ms
19 -8.400394007897 -4.26 -3.56 31.9ms
20 -8.400414886268 -4.68 -3.75 32.0ms
21 -8.400423366806 -5.07 -4.06 32.8ms
22 -8.400425658970 -5.64 -4.33 36.5ms
23 -8.400427232825 -5.80 -4.50 32.0ms
24 -8.400427675101 -6.35 -4.77 32.4ms
25 -8.400427995260 -6.49 -5.22 32.0ms
26 -8.400428080274 -7.07 -5.11 36.2ms
27 -8.400428116392 -7.44 -5.47 31.8ms
28 -8.400428134236 -7.75 -5.26 31.7ms
29 -8.400428143617 -8.03 -5.67 32.0ms
30 -8.400428149178 -8.25 -5.76 32.0ms
31 -8.400428150962 -8.75 -6.10 36.7ms
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.397887522445 -0.90 5.2 27.3ms
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.400427987828 -1.78 7.85s
2 -8.400428152209 -6.78 -4.04 3.07s
3 -8.400428152209 -14.45 -7.85 83.6ms
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| = 1.8949611561832562e-6
|ρ_newton - ρ_scfv| = 1.0492500454414279e-7
|ρ_newton - ρ_dm| = 1.7146795383827009e-6