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.397742764959                   -0.90    5.0   26.0ms
  2   -8.400217793318       -2.61       -1.74    1.0   19.0ms
  3   -8.400404327688       -3.73       -2.95    1.5   20.2ms
  4   -8.400427878933       -4.63       -2.99    3.0   23.9ms
  5   -8.400428018688       -6.85       -3.14    1.0   26.8ms
  6   -8.400428147300       -6.89       -4.94    1.0   19.3ms
  7   -8.400428152005       -8.33       -4.59    3.5   26.1ms
  8   -8.400428152199       -9.71       -5.42    1.0   19.5ms
  9   -8.400428152208      -11.07       -6.12    1.0   19.7ms

Potential-based SCF

scfres_scfv = DFTK.scf_potential_mixing(basis; tol);
n     Energy            log10(ΔE)   log10(Δρ)   α      Diag   Δtime
---   ---------------   ---------   ---------   ----   ----   ------
  1   -8.397843265668                   -0.90           5.2   26.6ms
  2   -8.400386627204       -2.59       -1.79   0.80    2.2   19.5ms
  3   -8.400422834491       -4.44       -3.02   0.80    1.0   16.5ms
  4   -8.400428111809       -5.28       -3.39   0.80    2.5   26.3ms
  5   -8.400428149798       -7.42       -4.44   0.80    1.0   16.7ms
  6   -8.400428152176       -8.62       -5.93   0.80    2.2   19.9ms
  7   -8.400428152209      -10.49       -5.89   0.80    3.0   22.3ms
  8   -8.400428152209      -12.89       -7.21   0.80    1.0   17.2ms

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.197074277617                   -0.99   59.7ms
  2   -1.821709009552        0.48       -0.63   33.4ms
  3   -4.444926343277        0.42       -0.35   49.8ms
  4   -6.114580312377        0.22       -0.40   44.5ms
  5   -7.556420010640        0.16       -0.70   44.5ms
  6   -7.900475762705       -0.46       -1.38   33.5ms
  7   -8.204033685128       -0.52       -1.54   37.9ms
  8   -8.318600047222       -0.94       -1.77   33.1ms
  9   -8.364890644987       -1.33       -2.13   33.1ms
 10   -8.382939633450       -1.74       -2.28   33.1ms
 11   -8.392331930862       -2.03       -2.49   36.7ms
 12   -8.397004371448       -2.33       -2.87   33.1ms
 13   -8.398837745888       -2.74       -2.91   33.1ms
 14   -8.399778725947       -3.03       -3.18   33.1ms
 15   -8.400068292158       -3.54       -3.79   36.9ms
 16   -8.400296599091       -3.64       -3.52   32.8ms
 17   -8.400352286013       -4.25       -3.73   33.1ms
 18   -8.400397055817       -4.35       -3.74   36.8ms
 19   -8.400410298902       -4.88       -3.81   33.0ms
 20   -8.400423340482       -4.88       -3.83   33.1ms
 21   -8.400425636821       -5.64       -4.39   33.2ms
 22   -8.400427381278       -5.76       -4.51   37.5ms
 23   -8.400427617219       -6.63       -5.06   33.3ms
 24   -8.400428010836       -6.40       -4.76   33.2ms
 25   -8.400428052684       -7.38       -5.14   33.3ms
 26   -8.400428115155       -7.20       -5.62   36.5ms
 27   -8.400428131717       -7.78       -5.52   33.0ms
 28   -8.400428143697       -7.92       -5.73   33.1ms
 29   -8.400428147151       -8.46       -5.82   36.5ms
 30   -8.400428149976       -8.55       -6.01   33.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.397840710081                   -0.90    5.5   26.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.400427982745                   -1.79    599ms
  2   -8.400428152209       -6.77       -4.03    409ms
  3   -8.400428152209   +    -Inf       -7.83    121ms

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|  = 1.652650757639361e-6
|ρ_newton - ρ_scfv| = 1.9371483567762906e-8
|ρ_newton - ρ_dm|   = 3.125837292622972e-6