12 - DFT+U#
This script demonstrates DFT+U calculations for strongly correlated systems, using iron oxide (FeO, wustite) as an example. DFT+U adds a Hubbard U correction to better describe localized d or f electrons that standard DFT handles poorly. python run.py
from ase import Atoms
from vasp import Vasp
from vasp.parameters import HubbardU, get_ldau_params
print("=" * 60)
print("DFT+U Calculations")
print("=" * 60)
print()
============================================================
DFT+U Calculations
============================================================
Part 1: Standard DFT for FeO#
print("Part 1: Standard DFT calculation")
print("-" * 40)
print()
# Create FeO in rock salt structure
a_FeO = 4.33 # Experimental lattice constant
feo = Atoms(
symbols=['Fe', 'O'],
scaled_positions=[
[0.0, 0.0, 0.0],
[0.5, 0.5, 0.5],
],
cell=[a_FeO, a_FeO, a_FeO],
pbc=True,
)
print("Structure: Rock salt FeO (Wustite)")
print(f" Lattice constant: {a_FeO} Å")
print(" Fe: 3d⁶ configuration")
print()
# Standard DFT calculation (spin-polarized)
calc_dft = Vasp(
label='results/dft_u/feo_standard',
atoms=feo,
xc='PBE',
encut=500,
kpts=(8, 8, 8),
ismear=0,
sigma=0.05,
ispin=2,
magmom=[4.0, 0.0], # Fe high-spin, O non-magnetic
lorbit=11,
)
e_dft = calc_dft.potential_energy
magmom_dft = calc_dft.results.get('magnetic_moment', 0.0)
magmoms_dft = calc_dft.results.get('magnetic_moments', [])
print("Standard DFT results:")
print(f" Total energy: {e_dft:.6f} eV")
print(f" Total magnetic moment: {magmom_dft:.4f} μB")
if len(magmoms_dft) > 0:
print(f" Fe magnetic moment: {magmoms_dft[0]:.4f} μB")
print()
Part 1: Standard DFT calculation
----------------------------------------
Structure: Rock salt FeO (Wustite)
Lattice constant: 4.33 Å
Fe: 3d⁶ configuration
Standard DFT results:
Total energy: -6.770168 eV
Total magnetic moment: 0.0000 μB
Part 2: DFT+U for FeO#
print("Part 2: DFT+U calculation")
print("-" * 40)
print()
# Get DFT+U parameters for Fe-O system
# Typical U values for Fe in oxides: 4-5 eV
ldau_params = get_ldau_params(
symbols=['Fe', 'O'],
u_values={'Fe': HubbardU(u=4.0, j=0.0)},
)
print("DFT+U parameters:")
print(" U(Fe d-electrons) = 4.0 eV")
print(" J(Fe) = 0.0 eV (Dudarev formulation: U_eff = U - J)")
print()
calc_dftu = Vasp(
label='results/dft_u/feo_u4',
atoms=feo.copy(),
xc='PBE',
encut=500,
kpts=(8, 8, 8),
ismear=0,
sigma=0.05,
ispin=2,
magmom=[4.0, 0.0],
lorbit=11,
**ldau_params,
)
e_dftu = calc_dftu.potential_energy
magmom_dftu = calc_dftu.results.get('magnetic_moment', 0.0)
magmoms_dftu = calc_dftu.results.get('magnetic_moments', [])
print("DFT+U (U=4.0 eV) results:")
print(f" Total energy: {e_dftu:.6f} eV")
print(f" Total magnetic moment: {magmom_dftu:.4f} μB")
if len(magmoms_dftu) > 0:
print(f" Fe magnetic moment: {magmoms_dftu[0]:.4f} μB")
print(" Experimental: ~3.6 μB")
print()
Part 2: DFT+U calculation
----------------------------------------
DFT+U parameters:
U(Fe d-electrons) = 4.0 eV
J(Fe) = 0.0 eV (Dudarev formulation: U_eff = U - J)
DFT+U (U=4.0 eV) results:
Total energy: -4.322233 eV
Total magnetic moment: 0.0000 μB
Part 3: U parameter scan#
print("Part 3: Effect of U parameter")
print("-" * 40)
print()
print("Scanning U values...")
print()
u_values = [0.0, 2.0, 4.0, 5.0, 6.0]
results = []
for u in u_values:
ldau = get_ldau_params(['Fe', 'O'], {'Fe': HubbardU(u=u)})
calc = Vasp(
label=f'results/dft_u/feo_u{u:.1f}',
atoms=feo.copy(),
xc='PBE',
encut=500,
kpts=(8, 8, 8),
ismear=0,
sigma=0.05,
ispin=2,
magmom=[4.0, 0.0],
lorbit=11,
**ldau,
)
e = calc.potential_energy
mag = calc.results.get('magnetic_moments', [0.0])[0]
results.append({'u': u, 'energy': e, 'magmom': mag})
print(f" U = {u:.1f} eV: Fe moment = {mag:.3f} μB")
print()
print("Effect of U on Fe magnetic moment:")
print(f" {'U (eV)':<10} {'μ_Fe (μB)':<12}")
print(" " + "-" * 22)
for r in results:
print(f" {r['u']:<10.1f} {r['magmom']:<12.3f}")
print()
Part 3: Effect of U parameter
----------------------------------------
Scanning U values...
Part 4: Compare band gap#
print("Part 4: Electronic structure comparison")
print("-" * 40)
print()
print("Band gap comparison:")
print()
# Note: Full band gap analysis requires DOS calculation
# Here we show the concept
print("Standard DFT:")
print(" - FeO predicted to be metallic (incorrect)")
print(" - Underestimated d-electron localization")
print()
print("DFT+U (U=4 eV):")
print(" - Correct insulating behavior")
print(" - Band gap opens due to d-electron localization")
print(" - Experimental gap: ~2.4 eV")
print()
Part 5: Different U schemes#
print("Part 5: DFT+U formulations")
print("-" * 40)
print()
print("VASP DFT+U options (LDAUTYPE):")
print()
print(" 1. Liechtenstein (LDAUTYPE=1):")
print(" - Uses both U and J separately")
print(" - E_U = (U-J)/2 × Σ [n_m - Σ n_mm' n_m'm]")
print()
print(" 2. Dudarev (LDAUTYPE=2) [default]:")
print(" - Uses effective U_eff = U - J")
print(" - E_U = (U-J)/2 × Σ [n_m(1 - n_m)]")
print(" - Simpler, most commonly used")
print()
print(" 4. Liechtenstein without exchange (LDAUTYPE=4):")
print(" - Uses U without J")
print()
Part 6: How to determine U#
print("Part 6: Determining U values")
print("-" * 40)
print()
print("Methods to determine Hubbard U:")
print()
print(" 1. Linear response (constrained DFT):")
print(" - Self-consistent calculation of U")
print(" - Most rigorous approach")
print()
print(" 2. Empirical fitting:")
print(" - Match to experimental properties")
print(" - Band gap, magnetic moment, lattice constant")
print()
print(" 3. Literature values:")
print(" - Use established U values for similar systems")
print()
print("Common U values (eV):")
print(" Fe(d): 3-5 Co(d): 3-4 Ni(d): 5-7")
print(" Mn(d): 3-4 Cr(d): 3-4 V(d): 3-4")
print(" Ce(f): 5-6 U(f): 4-5")
print()
Summary#
print("=" * 60)
print("Summary: DFT+U for FeO")
print("=" * 60)
print()
print("Comparison:")
print(f" {'Method':<15} {'Fe moment (μB)':<18} {'Behavior':<15}")
print(" " + "-" * 48)
print(f" {'Standard DFT':<15} {magmoms_dft[0] if magmoms_dft else 0.0:<18.3f} {'Metallic':<15}")
print(f" {'DFT+U (U=4)':<15} {magmoms_dftu[0] if magmoms_dftu else 0.0:<18.3f} {'Insulating':<15}")
print(f" {'Experimental':<15} {'~3.6':<18} {'Insulating':<15}")
print()
print("Key points:")
print(" - DFT+U corrects for self-interaction error")
print(" - Essential for transition metal oxides")
print(" - U value affects magnetic moment and band gap")
print(" - Dudarev formulation (LDAUTYPE=2) is most common")
print()
print("Next: Try 13_hybrid_functionals/ for HSE06 calculations.")