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.397832316710                   -0.90    5.2   26.0ms
  2   -8.400249715097       -2.62       -1.74    1.0   18.6ms
  3   -8.400396471887       -3.83       -2.93    1.2   19.0ms
  4   -8.400427756780       -4.50       -2.91    3.2   24.0ms
  5   -8.400427735293   +   -7.67       -2.87    1.0   18.7ms
  6   -8.400428139521       -6.39       -4.71    1.0   18.6ms
  7   -8.400428151262       -7.93       -4.24    3.2   24.4ms
  8   -8.400428152110       -9.07       -4.82    1.0   18.9ms
  9   -8.400428152203      -10.03       -6.19    1.0   18.9ms

Potential-based SCF

scfres_scfv = DFTK.scf_potential_mixing(basis; tol);
n     Energy            log10(ΔE)   log10(Δρ)   α      Diag   Δtime
---   ---------------   ---------   ---------   ----   ----   ------
  1   -8.397899464944                   -0.90           5.2   25.8ms
  2   -8.400380603671       -2.61       -1.79   0.80    2.0   18.5ms
  3   -8.400422357394       -4.38       -2.99   0.80    1.0   15.9ms
  4   -8.400428112794       -5.24       -3.42   0.80    2.5   26.8ms
  5   -8.400428149317       -7.44       -4.61   0.80    1.2   16.7ms
  6   -8.400428152187       -8.54       -5.46   0.80    2.5   19.9ms
  7   -8.400428152209      -10.67       -6.55   0.80    2.0   19.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/7krni/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/7krni/src/types.jl:120
n     Energy            log10(ΔE)   log10(Δρ)   Δtime
---   ---------------   ---------   ---------   ------
  1   +1.109720647556                   -1.04   57.3ms
  2   -1.962300952921        0.49       -0.66   32.2ms
  3   -4.641112157590        0.43       -0.39   43.6ms
  4   -6.316372936990        0.22       -0.49   43.2ms
  5   -7.676258225102        0.13       -0.80   43.4ms
  6   -8.067048047519       -0.41       -1.28   38.0ms
  7   -8.241133048312       -0.76       -1.63   32.1ms
  8   -8.310313004885       -1.16       -1.81   32.3ms
  9   -8.343811762567       -1.47       -2.22   32.1ms
 10   -8.364106631311       -1.69       -2.10   32.1ms
 11   -8.379746791098       -1.81       -2.28   32.3ms
 12   -8.391768082365       -1.92       -3.16   32.1ms
 13   -8.396917669315       -2.29       -2.85   32.1ms
 14   -8.398610759630       -2.77       -3.03   37.0ms
 15   -8.399795177743       -2.93       -3.62   32.1ms
 16   -8.400081880545       -3.54       -3.52   32.2ms
 17   -8.400278262870       -3.71       -3.65   32.4ms
 18   -8.400343984104       -4.18       -3.45   32.5ms
 19   -8.400399933432       -4.25       -3.88   32.2ms
 20   -8.400413847120       -4.86       -3.98   36.3ms
 21   -8.400422831137       -5.05       -4.19   33.0ms
 22   -8.400425967139       -5.50       -4.48   32.1ms
 23   -8.400427253127       -5.89       -4.89   32.3ms
 24   -8.400427813933       -6.25       -4.70   32.8ms
 25   -8.400428016677       -6.69       -5.30   36.1ms
 26   -8.400428096733       -7.10       -4.91   32.3ms
 27   -8.400428125918       -7.53       -5.29   32.1ms
 28   -8.400428142908       -7.77       -5.45   32.3ms
 29   -8.400428148209       -8.28       -5.69   36.1ms
 30   -8.400428150667       -8.61       -6.08   32.2ms

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.397893771370                   -0.90    5.2   26.1ms

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.400427986614                   -1.79    588ms
  2   -8.400428152209       -6.78       -4.03    395ms
  3   -8.400428152209      -14.45       -7.85    102ms

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|  = 2.1741810733380497e-6
|ρ_newton - ρ_scfv| = 2.2735654124514448e-7
|ρ_newton - ρ_dm|   = 3.1686578272393646e-6