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.397866984384                   -0.90    5.0   25.5ms
  2   -8.400249087824       -2.62       -1.73    1.0   17.4ms
  3   -8.400403575903       -3.81       -2.94    1.8   18.9ms
  4   -8.400427778396       -4.62       -2.92    3.0   23.1ms
  5   -8.400427960019       -6.74       -3.05    1.0   17.6ms
  6   -8.400428149280       -6.72       -4.78    1.0   17.6ms
  7   -8.400428155835       -8.18       -4.42    3.2   24.3ms
  8   -8.400428156260       -9.37       -5.68    1.0   17.8ms
  9   -8.400428156276      -10.78       -6.37    2.0   20.9ms

Potential-based SCF

scfres_scfv = DFTK.scf_potential_mixing(basis; tol);
n     Energy            log10(ΔE)   log10(Δρ)   α      Diag   Δtime
---   ---------------   ---------   ---------   ----   ----   ------
  1   -8.397876647065                   -0.90           5.0   26.3ms
  2   -8.400384967689       -2.60       -1.79   0.80    2.0   18.3ms
  3   -8.400423056586       -4.42       -3.03   0.80    1.0   15.2ms
  4   -8.400428112264       -5.30       -3.45   0.80    2.2   18.7ms
  5   -8.400428152753       -7.39       -4.80   0.80    1.0   15.0ms
  6   -8.400428156259       -8.46       -5.46   0.80    2.8   20.1ms
  7   -8.400428156276      -10.77       -6.31   0.80    1.8   17.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.686388109699                   -1.08   50.1ms
  2   -2.026207779030        0.43       -0.64   28.0ms
  3   -4.662941822030        0.42       -0.38   37.6ms
  4   -6.258392780343        0.20       -0.44   37.6ms
  5   -7.774343735594        0.18       -0.70   37.5ms
  6   -8.107744114751       -0.48       -1.38   27.8ms
  7   -8.304136123386       -0.71       -1.67   27.7ms
  8   -8.344514369723       -1.39       -2.04   27.8ms
  9   -8.377729451176       -1.48       -2.47   34.5ms
 10   -8.385700232703       -2.10       -2.27   52.9ms
 11   -8.393442443570       -2.11       -2.69   73.0ms
 12   -8.396251425547       -2.55       -2.71   28.6ms
 13   -8.398235239972       -2.70       -2.90   28.5ms
 14   -8.399181497601       -3.02       -3.14   28.5ms
 15   -8.399799289298       -3.21       -3.37   28.5ms
 16   -8.400153247858       -3.45       -3.26   28.5ms
 17   -8.400300764328       -3.83       -3.39   28.4ms
 18   -8.400381985291       -4.09       -3.41   28.4ms
 19   -8.400408649669       -4.57       -3.88   28.3ms
 20   -8.400420212134       -4.94       -3.85   28.0ms
 21   -8.400424326760       -5.39       -4.45   28.3ms
 22   -8.400426512010       -5.66       -4.30   28.5ms
 23   -8.400427367576       -6.07       -5.08   28.2ms
 24   -8.400427870430       -6.30       -4.66   28.3ms
 25   -8.400428026132       -6.81       -4.96   28.4ms
 26   -8.400428100952       -7.13       -5.11   28.3ms
 27   -8.400428131867       -7.51       -5.20   40.4ms
 28   -8.400428145508       -7.87       -5.43   28.4ms
 29   -8.400428151205       -8.24       -5.63   28.1ms
 30   -8.400428154170       -8.53       -5.72   27.9ms
 31   -8.400428155305       -8.94       -6.03   28.0ms

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.397841269786                   -0.90    5.2   28.7ms

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.400427977946                   -1.78    554ms
  2   -8.400428156277       -6.75       -4.02    345ms
  3   -8.400428156277      -14.75       -7.81    107ms

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|  = 7.425866763761935e-7
|ρ_newton - ρ_scfv| = 4.324782705746229e-7
|ρ_newton - ρ_dm|   = 1.494024332992863e-6