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-6
1.0e-6
Density-based self-consistent field
scfres_scf = self_consistent_field(basis; tol);
n Energy log10(ΔE) log10(Δρ) Diag Δtime
--- --------------- --------- --------- ---- ------
1 -8.397808841376 -0.90 4.8 24.9ms
2 -8.400240273042 -2.61 -1.73 1.0 17.5ms
3 -8.400401731418 -3.79 -2.95 1.5 18.6ms
4 -8.400427836122 -4.58 -2.96 3.2 23.7ms
5 -8.400427944377 -6.97 -3.04 1.0 17.6ms
6 -8.400428149840 -6.69 -4.84 1.0 17.5ms
7 -8.400428155871 -8.22 -4.44 3.0 24.0ms
8 -8.400428156252 -9.42 -5.14 1.0 18.3ms
9 -8.400428156275 -10.63 -6.12 1.0 18.3ms
Potential-based SCF
scfres_scfv = DFTK.scf_potential_mixing(basis; tol);
n Energy log10(ΔE) log10(Δρ) α Diag Δtime
--- --------------- --------- --------- ---- ---- ------
1 -8.397801684657 -0.90 5.2 25.9ms
2 -8.400384034256 -2.59 -1.80 0.80 2.0 17.7ms
3 -8.400422721941 -4.41 -3.03 0.80 1.0 15.2ms
4 -8.400428112432 -5.27 -3.46 0.80 2.5 19.6ms
5 -8.400428152204 -7.40 -4.72 0.80 1.0 15.2ms
6 -8.400428156252 -8.39 -5.36 0.80 2.8 20.2ms
7 -8.400428156276 -10.63 -6.81 0.80 2.0 18.0ms
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/8dE7C/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/8dE7C/src/types.jl:120
n Energy log10(ΔE) log10(Δρ) Δtime
--- --------------- --------- --------- ------
1 +0.996087198059 -1.09 50.4ms
2 -1.614904577278 0.42 -0.65 28.1ms
3 -4.431180668301 0.45 -0.37 37.7ms
4 -6.106105315764 0.22 -0.42 38.0ms
5 -7.522677558388 0.15 -0.75 37.6ms
6 -7.943719510433 -0.38 -1.26 40.6ms
7 -8.186826082562 -0.61 -1.59 28.3ms
8 -8.291376936559 -0.98 -1.92 28.4ms
9 -8.348491274611 -1.24 -2.31 28.1ms
10 -8.371819476989 -1.63 -2.23 28.1ms
11 -8.387291410057 -1.81 -2.36 27.9ms
12 -8.393443332379 -2.21 -2.60 28.0ms
13 -8.397018600359 -2.45 -2.68 28.2ms
14 -8.399132727787 -2.67 -2.72 28.1ms
15 -8.399736895795 -3.22 -3.19 28.2ms
16 -8.400159743635 -3.37 -3.21 27.9ms
17 -8.400281393736 -3.91 -3.83 28.0ms
18 -8.400378442103 -4.01 -3.58 28.1ms
19 -8.400398699345 -4.69 -4.01 28.0ms
20 -8.400416459184 -4.75 -3.98 28.1ms
21 -8.400420886989 -5.35 -4.68 28.3ms
22 -8.400424723724 -5.42 -4.50 34.9ms
23 -8.400426472052 -5.76 -4.85 28.2ms
24 -8.400427469859 -6.00 -5.06 28.2ms
25 -8.400427877352 -6.39 -4.90 28.3ms
26 -8.400428034121 -6.80 -5.01 28.2ms
27 -8.400428109790 -7.12 -5.38 28.3ms
28 -8.400428135808 -7.58 -5.57 28.0ms
29 -8.400428147946 -7.92 -5.64 27.9ms
30 -8.400428151851 -8.41 -6.37 28.1ms
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.397838296936 -0.90 5.5 26.5ms
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.400427987867 -1.79 535ms
2 -8.400428156277 -6.77 -4.03 349ms
3 -8.400428156277 -14.45 -7.84 93.3ms
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| = 8.086084314682903e-7
|ρ_newton - ρ_scfv| = 1.8285139660316163e-7
|ρ_newton - ρ_dm| = 2.5846567863654034e-6