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.397811793729 -0.90 5.2 27.1ms
2 -8.400237838323 -2.62 -1.74 1.0 19.4ms
3 -8.400405312553 -3.78 -2.96 1.8 20.6ms
4 -8.400427824130 -4.65 -2.97 3.0 24.1ms
5 -8.400427948301 -6.91 -3.05 1.0 67.9ms
6 -8.400428145490 -6.71 -4.67 1.0 19.2ms
7 -8.400428151788 -8.20 -4.46 2.8 23.7ms
8 -8.400428152194 -9.39 -5.72 1.0 19.4ms
9 -8.400428152209 -10.82 -6.41 2.0 22.4ms
Potential-based SCF
scfres_scfv = DFTK.scf_potential_mixing(basis; tol);n Energy log10(ΔE) log10(Δρ) α Diag Δtime
--- --------------- --------- --------- ---- ---- ------
1 -8.397864551459 -0.90 5.2 1.68s
2 -8.400384461344 -2.60 -1.78 0.80 2.2 489ms
3 -8.400423020092 -4.41 -3.00 0.80 1.0 215ms
4 -8.400428105194 -5.29 -3.45 0.80 2.5 20.7ms
5 -8.400428148814 -7.36 -4.73 0.80 1.2 17.4ms
6 -8.400428152191 -8.47 -5.54 0.80 2.5 20.6ms
7 -8.400428152208 -10.77 -6.51 0.80 2.0 19.1ms
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.296835977040 -1.06 3.38s
2 -1.488896743330 0.44 -0.66 148ms
3 -4.380695655419 0.46 -0.41 44.0ms
4 -5.953162128670 0.20 -0.47 43.6ms
5 -7.519029961086 0.19 -0.72 79.7ms
6 -7.929262518392 -0.39 -1.29 32.6ms
7 -8.218964207670 -0.54 -1.51 32.3ms
8 -8.302727441045 -1.08 -1.68 32.4ms
9 -8.357711442759 -1.26 -1.96 32.2ms
10 -8.376406680480 -1.73 -2.34 32.3ms
11 -8.388693554386 -1.91 -2.44 53.3ms
12 -8.396543288987 -2.11 -2.55 32.3ms
13 -8.398487023965 -2.71 -2.85 32.3ms
14 -8.399841825416 -2.87 -3.12 32.7ms
15 -8.400016839890 -3.76 -3.43 32.2ms
16 -8.400289086349 -3.57 -3.51 38.1ms
17 -8.400350066091 -4.21 -4.03 32.4ms
18 -8.400400047888 -4.30 -4.75 32.1ms
19 -8.400413130359 -4.88 -4.31 32.2ms
20 -8.400423192917 -5.00 -4.15 32.4ms
21 -8.400425882509 -5.57 -4.45 36.9ms
22 -8.400427137003 -5.90 -4.90 32.4ms
23 -8.400427596439 -6.34 -5.15 32.4ms
24 -8.400427909618 -6.50 -5.21 32.3ms
25 -8.400428017652 -6.97 -5.14 36.7ms
26 -8.400428091836 -7.13 -5.24 32.8ms
27 -8.400428126433 -7.46 -5.54 32.0ms
28 -8.400428139212 -7.89 -5.97 32.3ms
29 -8.400428147924 -8.06 -5.80 32.5ms
30 -8.400428150045 -8.67 -5.75 36.8ms
31 -8.400428151443 -8.85 -6.52 32.3ms
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.397828591081 -0.90 5.2 27.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.400427986311 -1.79 11.3s
2 -8.400428152209 -6.78 -4.04 3.68s
3 -8.400428152209 -14.45 -7.85 75.1ms
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| = 4.1269006210954543e-7
|ρ_newton - ρ_scfv| = 3.81460313832426e-7
|ρ_newton - ρ_dm| = 1.47840549987321e-6