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.397828786723 -0.90 5.2 27.7ms
2 -8.400232933169 -2.62 -1.74 1.0 19.8ms
3 -8.400405950093 -3.76 -2.98 1.5 20.8ms
4 -8.400427852767 -4.66 -2.99 3.0 25.0ms
5 -8.400427955744 -6.99 -3.06 1.0 19.6ms
6 -8.400428145331 -6.72 -4.70 1.0 19.5ms
7 -8.400428151767 -8.19 -4.43 3.0 34.8ms
8 -8.400428152188 -9.37 -5.40 1.0 20.5ms
9 -8.400428152207 -10.72 -6.34 1.8 22.0msPotential-based SCF
scfres_scfv = DFTK.scf_potential_mixing(basis; tol);n Energy log10(ΔE) log10(Δρ) α Diag Δtime
--- --------------- --------- --------- ---- ---- ------
1 -8.397796484264 -0.90 4.8 27.1ms
2 -8.400374913282 -2.59 -1.77 0.80 2.0 19.2ms
3 -8.400422324153 -4.32 -2.98 0.80 1.0 16.5ms
4 -8.400428108548 -5.24 -3.46 0.80 2.5 28.2ms
5 -8.400428148562 -7.40 -5.05 0.80 1.2 17.3ms
6 -8.400428152204 -8.44 -5.20 0.80 3.5 23.5ms
7 -8.400428152209 -11.29 -6.28 0.80 1.0 16.9msDirect 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.892185875672 -1.03 57.3ms
2 -1.669149508252 0.41 -0.66 33.0ms
3 -4.591462868235 0.47 -0.35 51.4ms
4 -6.174225043057 0.20 -0.44 43.5ms
5 -7.614420947048 0.16 -0.68 43.6ms
6 -8.068895202141 -0.34 -1.28 32.2ms
7 -8.238559826318 -0.77 -1.68 32.2ms
8 -8.300935025729 -1.20 -1.95 32.2ms
9 -8.338741125448 -1.42 -2.10 38.7ms
10 -8.353183744979 -1.84 -2.35 32.2ms
11 -8.369810654194 -1.78 -2.23 32.2ms
12 -8.384887836849 -1.82 -2.17 32.0ms
13 -8.391707399890 -2.17 -2.58 32.2ms
14 -8.397580652834 -2.23 -3.03 32.3ms
15 -8.399268658227 -2.77 -2.78 39.3ms
16 -8.399949531672 -3.17 -3.54 32.7ms
17 -8.400226458519 -3.56 -3.35 32.4ms
18 -8.400356156075 -3.89 -3.73 32.2ms
19 -8.400391771839 -4.45 -3.48 32.4ms
20 -8.400419429381 -4.56 -4.22 32.1ms
21 -8.400423277126 -5.41 -3.97 37.8ms
22 -8.400426319072 -5.52 -4.22 32.4ms
23 -8.400427259287 -6.03 -4.38 32.5ms
24 -8.400427766617 -6.29 -4.78 32.2ms
25 -8.400427954221 -6.73 -4.78 32.2ms
26 -8.400428082313 -6.89 -5.70 32.0ms
27 -8.400428115891 -7.47 -5.19 31.9ms
28 -8.400428139286 -7.63 -6.09 39.8msNewton 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.397812518225 -0.90 5.2 27.2msRemove 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.400427977670 -1.78 552ms
2 -8.400428152209 -6.76 -4.03 365ms
3 -8.400428152209 -14.45 -7.82 83.6msComparison 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.2585501466496013e-6
|ρ_newton - ρ_scfv| = 2.397060241894607e-7
|ρ_newton - ρ_dm| = 3.1254271045776822e-6