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.397860908587 -0.90 5.2 27.6ms
2 -8.400251696573 -2.62 -1.74 1.0 20.2ms
3 -8.400408238057 -3.81 -2.97 1.8 33.6ms
4 -8.400427857486 -4.71 -2.99 2.8 25.6ms
5 -8.400427952377 -7.02 -3.06 1.0 20.6ms
6 -8.400428145266 -6.71 -4.72 1.0 22.4ms
7 -8.400428151844 -8.18 -4.47 3.2 27.2ms
8 -8.400428152197 -9.45 -6.02 1.0 20.9msPotential-based SCF
scfres_scfv = DFTK.scf_potential_mixing(basis; tol);n Energy log10(ΔE) log10(Δρ) α Diag Δtime
--- --------------- --------- --------- ---- ---- ------
1 -8.397852946069 -0.90 4.8 28.3ms
2 -8.400381348873 -2.60 -1.77 0.80 2.0 20.4ms
3 -8.400423113117 -4.38 -2.97 0.80 1.0 17.6ms
4 -8.400428111592 -5.30 -3.46 0.80 2.2 21.8ms
5 -8.400428149181 -7.42 -4.81 0.80 1.0 18.4ms
6 -8.400428152189 -8.52 -5.50 0.80 2.8 22.1ms
7 -8.400428152208 -10.72 -6.24 0.80 2.0 19.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.873056137404 -1.02 71.0ms
2 -1.797410289569 0.43 -0.69 33.5ms
3 -4.253168643873 0.39 -0.35 44.8ms
4 -5.632712110226 0.14 -0.43 44.5ms
5 -7.190959408273 0.19 -0.59 54.0ms
6 -7.828504085345 -0.20 -0.92 46.3ms
7 -8.075803389189 -0.61 -1.27 33.6ms
8 -8.227688060627 -0.82 -1.81 32.9ms
9 -8.308477027126 -1.09 -1.96 32.5ms
10 -8.345647355831 -1.43 -2.33 41.0ms
11 -8.371708316959 -1.58 -2.32 33.5ms
12 -8.385243913635 -1.87 -2.12 32.9ms
13 -8.393662790548 -2.07 -2.39 33.3ms
14 -8.397392397064 -2.43 -2.79 33.2ms
15 -8.399339312952 -2.71 -2.75 33.3ms
16 -8.400032400232 -3.16 -2.95 41.5ms
17 -8.400287517992 -3.59 -3.16 32.8ms
18 -8.400372381923 -4.07 -3.52 32.9ms
19 -8.400405946127 -4.47 -3.49 33.8ms
20 -8.400419888455 -4.86 -4.09 33.4ms
21 -8.400424683002 -5.32 -3.93 33.1ms
22 -8.400426486623 -5.74 -4.44 40.3ms
23 -8.400427372669 -6.05 -4.22 32.6ms
24 -8.400427798212 -6.37 -5.31 32.9ms
25 -8.400427981139 -6.74 -4.62 32.5ms
26 -8.400428071575 -7.04 -5.08 32.4ms
27 -8.400428120275 -7.31 -5.08 32.4ms
28 -8.400428138551 -7.74 -5.31 41.6ms
29 -8.400428146664 -8.09 -5.66 33.6ms
30 -8.400428149551 -8.54 -5.51 33.3ms
31 -8.400428151307 -8.76 -5.74 32.6ms
32 -8.400428151780 -9.32 -6.01 33.2msNewton 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.397880637314 -0.90 5.0 36.6msRemove 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.400427980396 -1.79 615ms
2 -8.400428152209 -6.76 -4.03 412ms
3 -8.400428152209 -14.45 -7.83 119msComparison 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| = 2.974858061180254e-6
|ρ_newton - ρ_scfv| = 4.993638387443451e-7
|ρ_newton - ρ_dm| = 1.70376831078109e-6