-
Notifications
You must be signed in to change notification settings - Fork 97
Add Hubbard corrections and DFT+U #1158
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 20 commits
bc0e2eb
d4dfa7b
48a33f0
6c77122
5540b22
9e894bf
4a1d0e2
db7d948
e0a1002
7045a6d
fab6fb5
ae13ba7
5aefec2
0d69edd
d0cf01a
16a3f6f
c9d8328
f905197
7ea2342
3b72e16
42b5f85
5a95c9d
20b1370
914bbe6
b31874d
d4cb53c
aeab561
1fad1c8
efc83f5
074f539
41bebad
a431717
8a87487
52a20d8
8de7498
8f636d7
75cc62c
b2da690
761ee8b
ea48cca
b7e90bb
3cf787e
0e17b63
2fe39dc
3c611b1
aecf0bd
1d4d73c
15304e7
253931d
f649481
df51495
5c05a9f
a021e32
e2d97d6
2da2d03
9f7dbcd
ca16a44
7aab38e
3533669
99bddba
872c29a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| # # Hubbard correction (DFT+U) | ||
| # In this example, we'll plot the DOS and projected DOS of Nickel Oxide | ||
| # with and without the Hubbard term correction. | ||
|
|
||
| using DFTK | ||
| using Printf | ||
Technici4n marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| using PseudoPotentialData | ||
| using Unitful | ||
| using UnitfulAtomic | ||
| using Plots | ||
|
|
||
| # Define the geometry and pseudopotential | ||
| a = 7.9 # Nickel Oxide lattice constant in Bohr | ||
| lattice = a * [[ 1.0 0.5 0.5]; | ||
| [ 0.5 1.0 0.5]; | ||
| [ 0.5 0.5 1.0]] | ||
| pseudopotentials = PseudoFamily("dojo.nc.sr.pbe.v0_4_1.standard.upf") | ||
| Ni, O = ElementPsp(:Ni, pseudopotentials), ElementPsp(:O, pseudopotentials) | ||
Technici4n marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| atoms = [Ni, O, Ni, O] | ||
| positions = [zeros(3), ones(3) / 4, ones(3) / 2, ones(3) * 3 / 4] | ||
| magnetic_moments = [2, 0, -1, 0] | ||
|
|
||
| # First, we run an SCF and NSCF without the Hubbard term | ||
| model = model_DFT(lattice, atoms, positions; temperature=5e-3, | ||
| functionals = PBE(), magnetic_moments=magnetic_moments) | ||
Technici4n marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| basis = PlaneWaveBasis(model; Ecut = 32, kgrid = [2, 2, 2] ) | ||
| scfres = self_consistent_field(basis; tol=1e-10, ρ=guess_density(basis, magnetic_moments)) | ||
| bands = compute_bands(scfres, MonkhorstPack(2, 2, 2); ρ=scfres.ρ); | ||
Technici4n marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| band_gap = bands.eigenvalues[1][25] - bands.eigenvalues[1][24] | ||
Technici4n marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| # Then we plot the DOS and the PDOS for the relevant 3D (pseudo)atomic projector | ||
| εF = bands.εF | ||
| width = 5.0u"eV" | ||
| εrange = (εF - austrip(width), εF + austrip(width)) | ||
| p = plot_dos(bands; εrange, colors=[:red, :red]) | ||
| plot_pdos(bands; p, temperature=2e-3, iatom=1, label="3D", colors=[:yellow, :orange], εrange) | ||
|
|
||
| # To perform and Hubbard computation, we have to define the Hubbard manifold and associated constant | ||
| U = 10u"eV" | ||
| manifold = DFTK.OrbitalManifold(;species=:Ni, label="3D") | ||
mfherbst marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| # Run SCF | ||
| model = model_DFT(lattice, atoms, positions; extra_terms=[DFTK.Hubbard(manifold, U)], | ||
| functionals = PBE(), temperature=5e-3, magnetic_moments=magnetic_moments) | ||
fsicignano marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| basis = PlaneWaveBasis(model; Ecut = 32, kgrid = [2, 2, 2] ) | ||
fsicignano marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| scfres = self_consistent_field(basis; tol=1e-10, ρ=guess_density(basis, magnetic_moments)) | ||
|
|
||
| # Run NSCF | ||
Technici4n marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| bands_hub = compute_bands(scfres, MonkhorstPack(2, 2, 2); ρ=scfres.ρ) | ||
fsicignano marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| band_gap = bands_hub.eigenvalues[1][26] - bands_hub.eigenvalues[1][25] | ||
Technici4n marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| # With the electron localization introduced by the Hubbard term, the band gap has now opened, | ||
| # reflecting the experimental insulating behaviour of Nickel Oxide. | ||
| εF = bands_hub.εF | ||
| εrange = (εF - austrip(width), εF + austrip(width)) | ||
| p = plot_dos(bands_hub; colors=[:blue, :blue], εrange) | ||
| plot_pdos(bands_hub; p, iatom=1, label="3D", colors=[:green, :purple], εrange) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -119,31 +119,6 @@ function compute_pdos(εs, bands; kwargs...) | |
| compute_pdos(εs, bands.basis, bands.ψ, bands.eigenvalues; kwargs...) | ||
| end | ||
|
|
||
| """ | ||
| Structure for manifold choice and projectors extraction. | ||
|
|
||
| Overview of fields: | ||
| - `iatom`: Atom position in the atoms array. | ||
| - `species`: Chemical Element as in ElementPsp. | ||
| - `label`: Orbital name, e.g.: "3S". | ||
|
|
||
| All fields are optional, only the given ones will be used for selection. | ||
| Can be called with an orbital NamedTuple and returns a boolean | ||
| stating whether the orbital belongs to the manifold. | ||
| """ | ||
| @kwdef struct OrbitalManifold | ||
| iatom ::Union{Int64, Nothing} = nothing | ||
| species ::Union{Symbol, AtomsBase.ChemicalSpecies, Nothing} = nothing | ||
| label ::Union{String, Nothing} = nothing | ||
| end | ||
| function (s::OrbitalManifold)(orb) | ||
| iatom_match = isnothing(s.iatom) || (s.iatom == orb.iatom) | ||
| # See JuliaMolSim/AtomsBase.jl#139 why both species equalities are needed | ||
| species_match = isnothing(s.species) || (s.species == orb.species) || (orb.species == s.species) | ||
| label_match = isnothing(s.label) || (s.label == orb.label) | ||
| iatom_match && species_match && label_match | ||
| end | ||
|
|
||
| """ | ||
| atomic_orbital_projectors(basis; [isonmanifold, positions]) | ||
|
|
||
|
|
@@ -191,6 +166,7 @@ function atomic_orbital_projectors(basis::PlaneWaveBasis{T}; | |
| labels = [] | ||
| for (iatom, atom) in enumerate(basis.model.atoms) | ||
| psp = atom.psp | ||
| count_n_pswfc(psp) # We need this to check if we have any atomic orbital projector | ||
|
||
| for l in 0:psp.lmax, n in 1:DFTK.count_n_pswfc_radial(psp, l) | ||
| label = DFTK.pswfc_label(psp, n, l) | ||
| if !isonmanifold((; iatom, atom.species, label)) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.