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.397803592136 -0.90 5.2 28.0ms
2 -8.400251125963 -2.61 -1.74 1.0 19.7ms
3 -8.400397569857 -3.83 -2.91 1.2 20.0ms
4 -8.400427754119 -4.52 -2.93 3.2 25.1ms
5 -8.400427835278 -7.09 -2.94 1.0 19.3ms
6 -8.400428143205 -6.51 -4.61 1.0 30.7ms
7 -8.400428151566 -8.08 -4.34 2.8 25.2ms
8 -8.400428152180 -9.21 -5.27 1.0 20.0ms
9 -8.400428152207 -10.57 -6.13 1.5 21.2msPotential-based SCF
scfres_scfv = DFTK.scf_potential_mixing(basis; tol);n Energy log10(ΔE) log10(Δρ) α Diag Δtime
--- --------------- --------- --------- ---- ---- ------
1 -8.397813490122 -0.90 5.2 29.6ms
2 -8.400383888019 -2.59 -1.79 0.80 2.2 20.3ms
3 -8.400422725128 -4.41 -3.00 0.80 1.0 27.6ms
4 -8.400428098999 -5.27 -3.38 0.80 2.5 20.9ms
5 -8.400428149463 -7.30 -4.38 0.80 1.2 17.8ms
6 -8.400428152156 -8.57 -5.61 0.80 2.0 19.9ms
7 -8.400428152209 -10.27 -6.02 0.80 2.8 22.3msDirect 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.640306604471 -1.00 58.8ms
2 -1.490725562186 0.33 -0.63 41.6ms
3 -4.372689316092 0.46 -0.43 44.2ms
4 -5.784497741939 0.15 -0.50 44.1ms
5 -7.348509937362 0.19 -0.76 44.0ms
6 -7.565199462645 -0.66 -1.41 32.6ms
7 -8.088982227880 -0.28 -1.57 40.4ms
8 -8.245085145918 -0.81 -1.81 32.8ms
9 -8.333261502237 -1.05 -1.90 32.7ms
10 -8.367624898186 -1.46 -2.01 32.8ms
11 -8.383827277995 -1.79 -2.28 33.0ms
12 -8.391258636473 -2.13 -2.51 33.4ms
13 -8.396308193574 -2.30 -2.49 40.9ms
14 -8.398290670932 -2.70 -2.95 33.1ms
15 -8.399417774233 -2.95 -3.06 33.1ms
16 -8.399899494929 -3.32 -3.36 32.9ms
17 -8.400199800701 -3.52 -3.34 33.3ms
18 -8.400324692081 -3.90 -3.44 32.9ms
19 -8.400386317578 -4.21 -3.55 39.7ms
20 -8.400410267434 -4.62 -4.34 32.8ms
21 -8.400422720362 -4.90 -3.93 32.9ms
22 -8.400425731252 -5.52 -4.41 32.8ms
23 -8.400427439841 -5.77 -4.41 32.7ms
24 -8.400427805317 -6.44 -4.55 32.8ms
25 -8.400428041200 -6.63 -4.72 40.5ms
26 -8.400428105111 -7.19 -5.71 32.8ms
27 -8.400428132420 -7.56 -5.43 32.8ms
28 -8.400428143635 -7.95 -6.02 32.6msNewton 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.397835124598 -0.90 5.2 27.5msRemove 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.400427999165 -1.80 609ms
2 -8.400428152209 -6.82 -4.06 399ms
3 -8.400428152209 -14.45 -7.89 108msComparison 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.1514951237542666e-6
|ρ_newton - ρ_scfv| = 1.1191537872309611e-7
|ρ_newton - ρ_dm| = 2.8733858467448253e-6