Collinear spin and magnetic systems

In this example we consider iron in the BCC phase. To show that this material is ferromagnetic we will model it once allowing collinear spin polarization and once without and compare the resulting SCF energies. In particular the ground state can only be found if collinear spins are allowed.

First we setup BCC iron without spin polarization using a single iron atom inside the unit cell.

In [1]:
using DFTK

a = 5.42352  # Bohr
lattice = a / 2 * [[-1  1  1];
                   [ 1 -1  1];
                   [ 1  1 -1]]
Fe = ElementPsp(:Fe, psp=load_psp("hgh/lda/Fe-q8.hgh"))
atoms = [Fe => [zeros(3)]];

To get the ground-state energy we use an LDA model and rather moderate discretisation parameters.

In [2]:
kgrid = [3, 3, 3]  # k-point grid (Regular Monkhorst-Pack grid)
Ecut = 15          # kinetic energy cutoff in Hartree
model_nospin = model_LDA(lattice, atoms, temperature=0.01)
basis_nospin = PlaneWaveBasis(model_nospin, Ecut; kgrid=kgrid)

scfres_nospin = self_consistent_field(basis_nospin, tol=1e-6, mixing=KerkerMixing());
n     Free energy       Eₙ-Eₙ₋₁     ρout-ρin   Diag
---   ---------------   ---------   --------   ----
  1   -16.64708732170         NaN   3.28e-01    5.0 
  2   -16.64775318371   -6.66e-04   7.80e-02    1.0 
  3   -16.64782279277   -6.96e-05   3.31e-03    1.8 
  4   -16.64783256813   -9.78e-06   1.99e-03    3.0 
  5   -16.64783415769   -1.59e-06   4.08e-04    1.0 
  6   -16.64783430211   -1.44e-07   1.24e-04    2.0 
In [3]:
scfres_nospin.energies
Out[3]:
Energy breakdown:
    Kinetic             15.9215670
    AtomicLocal         -5.0696477
    AtomicNonlocal      -5.2206870
    Ewald               -21.4723040
    PspCorrection       1.8758831 
    Hartree             0.7794347 
    Xc                  -3.4437925
    Entropy             -0.0182879

    total               -16.647834302113

Since we did not specify any initial magnetic moment on the iron atom, DFTK will automatically assume that a calculation with only spin-paired electrons should be performed. As a result the obtained ground state features no spin-polarization.

Now we repeat the calculation, but give the iron atom an initial magnetic moment. For specifying the magnetic moment pass the desired excess of spin-up over spin-down electrons at each centre to the Model and the guess density functions. In this case we seek the state with as many spin-parallel d-electrons as possible. In our pseudopotential model the 8 valence electrons are 2 pair of s-electrons, 1 pair of d-electrons and 4 unpaired d-electrons giving a desired magnetic moment of 4 at the iron centre. The structure (i.e. pair mapping and order) of the magnetic_moments array needs to agree with the atoms array and 0 magnetic moments need to be specified as well.

In [4]:
magnetic_moments = [Fe => [4, ]];

!!! tip "Units of the magnetisation and magnetic moments in DFTK" Unlike all other quantities magnetisation and magnetic moments in DFTK are given in units of the Bohr magneton μ_B, which in atomic units has the value \frac{1}{2}. Since μ_B is (roughly) the magnetic moment of a single electron the advantage is that one can directly think of these quantities as the excess of spin-up electrons or spin-up electron density.

We repeat the calculation using the same model as before. DFTK now detects the non-zero moment and switches to a collinear calculation.

In [5]:
model = model_LDA(lattice, atoms, magnetic_moments=magnetic_moments, temperature=0.01)
basis = PlaneWaveBasis(model, Ecut; kgrid=kgrid)
ρspin = guess_spin_density(basis, magnetic_moments)
scfres = self_consistent_field(basis, tol=1e-6, ρspin=ρspin, mixing=KerkerMixing());
n     Free energy       Eₙ-Eₙ₋₁     ρout-ρin   Magnet   Diag
---   ---------------   ---------   --------   ------   ----
  1   -16.65998124633         NaN   3.41e-01    2.620    4.5 
  2   -16.66626168792   -6.28e-03   6.92e-02    2.428    1.0 
  3   -16.66693986495   -6.78e-04   8.45e-03    2.349    2.3 
  4   -16.66698649599   -4.66e-05   3.62e-03    2.320    2.1 
  5   -16.66699463706   -8.14e-06   6.63e-04    2.309    2.0 
  6   -16.66699628351   -1.65e-06   3.72e-04    2.301    2.1 
  7   -16.66699652132   -2.38e-07   2.50e-05    2.297    1.9 
In [6]:
scfres.energies
Out[6]:
Energy breakdown:
    Kinetic             16.3014882
    AtomicLocal         -5.2260199
    AtomicNonlocal      -5.4135697
    Ewald               -21.4723040
    PspCorrection       1.8758831 
    Hartree             0.8201288 
    Xc                  -3.5395240
    Entropy             -0.0130790

    total               -16.666996521316

!!! note "Model and magnetic moments" DFTK does not store the magnetic_moments inside the Model, but only uses them to determine the lattice symmetries. This step was taken to keep Model (which contains the physical model) independent of the details of the numerical details such as the initial guess for the spin density.

In direct comparison we notice the first, spin-paired calculation to be a little higher in energy

In [7]:
println("No magnetization: ", scfres_nospin.energies.total)
println("Magnetic case:    ", scfres.energies.total)
println("Difference:       ", scfres.energies.total - scfres_nospin.energies.total);
No magnetization: -16.64783430211281
Magnetic case:    -16.666996521315998
Difference:       -0.019162219203188613

Notice that with the small cutoffs we use to generate the online documentation the calculation is far from converged. With more realistic parameters a larger energy difference of about 0.1 Hartree is obtained.

The spin polarization in the magnetic case is visible if we consider the occupation of the spin-up and spin-down Kohn-Sham orbitals. Especially for the d-orbitals these differ rather drastically. For example for the first k-point:

In [8]:
iup   = 1
idown = iup + length(scfres.basis.kpoints) ÷ 2
@show scfres.occupation[iup][1:7]
@show scfres.occupation[idown][1:7];
(scfres.occupation[iup])[1:7] = [1.0, 0.9999988139689593, 0.9999988139612348, 0.9999988139445563, 0.9585673791988384, 0.9585668796136337, 1.1540079785367461e-29]
(scfres.occupation[idown])[1:7] = [1.0, 0.8326826261828263, 0.8326805017856539, 0.8326792520478095, 7.840289089817195e-6, 7.84019475042066e-6, 1.5497931141714043e-32]

Similarly the eigenvalues differ

In [9]:
@show scfres.eigenvalues[iup][1:7]
@show scfres.eigenvalues[idown][1:7];
(scfres.eigenvalues[iup])[1:7] = [-0.06926618424468207, 0.35688291356907764, 0.3568829786978953, 0.3568831193215683, 0.46191816912127137, 0.4619182949100824, 1.1596491487097627]
(scfres.eigenvalues[idown])[1:7] = [-0.030407370124734448, 0.47728428138314927, 0.47728443386317937, 0.4772845235632276, 0.6108941526628173, 0.6108942729909107, 1.2257778978453593]

!!! note "k-points in collinear calculations" For collinear calculations the kpoints field of the PlaneWaveBasis object contains each k-point coordinate twice, once associated with spin-up and once with down-down. The list first contains all spin-up k-points and then all spin-down k-points, such that iup and idown index the same k-point, but differing spins.

We can observe the spin-polarization by looking at the density of states (DOS) around the Fermi level, where the spin-up and spin-down DOS differ.

In [10]:
using Plots
plot_dos(scfres)
Out[10]:

Similarly the band structure shows clear differences between both spin components.

In [11]:
plot_bandstructure(scfres, kline_density=3, unit=:eV)
Computing bands along kpath:
       Γ -> H -> N -> Γ -> P -> H  and  P -> N
Diagonalising Hamiltonian kblocks: 100%|████████████████| Time: 0:00:03
Out[11]: