Change of dimension in last kpoint when using non-converging scf
Closed this issue · 4 comments
Hi all,
I currently have a problem using non converging SCF. I'm using ~1-3 steps of SCF in order to improve an initial guess for an iterative method. The problem here is, that the dimensions of ψ1
and ψ2
sometimes differ, making the method fail. This happens around ~30% of the time even for fixed ψ1
.
Here is a minimal working example.
using DFTK
using LinearAlgebra
function graphene_setup(;Ecut = 15)
L = 20 # height of the simulation box
kgrid = [6, 6, 1]
# Define the geometry and pseudopotential
a = 4.66 # lattice constant
a1 = a*[1/2,-sqrt(3)/2, 0]
a2 = a*[1/2, sqrt(3)/2, 0]
a3 = L*[0 , 0 , 1]
lattice = [a1 a2 a3]
C1 = [1/3,-1/3,0.0] # in reduced coordinates
C2 = -C1
positions = [C1, C2]
C = ElementPsp(:C; psp=load_psp("hgh/pbe/c-q4"))
atoms = [C, C]
# Run SCF
model = model_PBE(lattice, atoms, positions)
basis = PlaneWaveBasis(model; Ecut, kgrid)
return [model, basis]
end
model, basis = graphene_setup(Ecut = 15);
# Convergence we desire in the density
tol = 1e-6
filled_occ = DFTK.filled_occupation(model)
n_spin = model.n_spin_components
n_bands = div(model.n_electrons, n_spin * filled_occ, RoundUp)
ψ1 = [DFTK.random_orbitals(basis, kpt, n_bands) for kpt in basis.kpoints];
#scf messes up dimensions
scfres_start = self_consistent_field(basis; ψ = ψ1 , maxiter = 1);
ψ2 = DFTK.select_occupied_orbitals(basis, scfres_start.ψ, scfres_start.occupation).ψ;
# different dims in the last kpoint!
println(length(ψ1[length(ψ1)])) #4248
println(length(ψ2[length(ψ2)])) #sometimes 4248, sometimes 5310
I've consulted with @gkemlin and he came to the following conclusion: In this case, there is an additional occupied state in the last kpoint of ψ2
. In scfres_start.occupation
, we have the following :
7-element Vector{Vector{Float64}}:
[2.0, 2.0, 2.0, 2.0, 0.0, 0.0, 0.0]
[2.0, 2.0, 2.0, 2.0, 0.0, 0.0, 0.0]
[2.0, 2.0, 2.0, 2.0, 0.0, 0.0, 0.0]
[2.0, 2.0, 2.0, 2.0, 0.0, 0.0, 0.0]
[2.0, 2.0, 2.0, 2.0, 0.0, 0.0, 0.0]
[2.0, 2.0, 2.0, 2.0, 0.0, 0.0, 0.0]
[2.0, 2.0, 2.0, 0.0, 2.0, 0.0, 0.0]
Here we can see, that 4th state is 0 and the 5th state is filled. This is because the two eigenvalues in scfres.eigenvalues[7][4:5]
are very close, as seen here:
2-element Vector{Float64}:
-0.015228616549833577
-0.015228616549801455
Now for the randomness of this occuring, if you do just one iteration of the SCF, the eigenvalues are sometimes not sorted.
Is this intended behaviour? And if it is, is there any way to avoid this in order to always get a "working" ψ2
? As the method I'm using is a Riemannian scheme, it is unfortunately not possible to introduce a very small numerical temperature to allow for fractional occupation number, as this destroys the manifold structure of the problem (at least as far as I know).
Thanks for your help and best regards,
Jonas
Good catch! With small differences the eigenvalues might not be sorted because they are recomputed after the Rayleigh-Ritz. Does https://github.com/JuliaMolSim/DFTK.jl/pull/964/files fix it?
It seems to work yes! I was not sure if sorting directly here would break something elsewhere 😄
I don't see what it would break? This is a bit of a hack, a better solution would be to not recompute the eigenvalues but get them from the Rayleigh Ritz
Good catch! With small differences the eigenvalues might not be sorted because they are recomputed after the Rayleigh-Ritz. Does https://github.com/JuliaMolSim/DFTK.jl/pull/964/files fix it?
Yes, this fixes my problem. Thank you very much :)