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