home

DFT Jacob's Ladder

A visualization of Perdew's Jacob's ladder of density functional theory (DFT), representing a hierarchy of increasingly sophisticated approximations to the exchange-correlation energy (E_xc). The ladder climbs from the Hartree approximation (no exchange-correlation) through local density approximations to accurate but expensive double-hybrid functionals one rung below chemical accuracy, with each rung adding new physical ingredients to improve accuracy at the cost of computational complexity.


DFT Jacob's Ladder

Download

PNG PDF SVG

Code

dft-jacobs-ladder.typ (61 lines)
#import "@preview/cetz:0.5.3": canvas, draw
#import draw: circle, content, line, rect

#set page(width: auto, height: auto, margin: 8pt, fill: none)
#set text(size: 14pt)

#canvas({
  let rung-sep = 2.2 // Vertical separation between rungs
  let width = 12.4 // Width of each rung
  let height = 1.5 // Height of each rung
  let circle-r = 0.8 // Radius of symbol circles
  let rung-stroke = rgb("888") + 0.4pt

  // Each rung: fill, name and example functionals, ingredient symbol, ingredient name
  for (idx, (color, label, symbol, ingredient)) in (
    (rgb("b4a7d6"), [0: *Hartree World*], none, none),
    (rgb("a4c2f4"), [1: *Local Density Approx. (LDA)*\ VWN, PW92], $rho(bold(r))$, [density]),
    (
      rgb("f9cb9c"),
      [2: *Generalized Gradient Approx. (GGA)*\ PBE, BLYP],
      $nabla rho(bold(r))$,
      [\+ density gradient],
    ),
    (
      rgb("ffe599"),
      [3: *Meta-GGA*\ (r/r$""^2$)SCAN],
      [$\ nabla^(2) rho(bold(r))$ \ $tau(bold(r))$],
      [\+ Laplacian, kinetic energy density],
    ),
    (
      rgb("b6d7a8"),
      [4: *Occupied Hybrid Methods* \ B3LYP, CAM-B3LYP, M06-2X],
      ${phi_i^"occ"}$,
      [\+ occupied orbitals],
    ),
    (
      rgb("ea9999"),
      [5: *Virtual Double-Hybrids* \ B2PLYP],
      ${phi_i^"virt"}$,
      [\+ virtual orbitals],
    ),
    (rgb("ffb7c5"), [*Chemical accuracy*], none, none),
  ).enumerate() {
    let y = idx * rung-sep
    rect((-width / 2, y), (width / 2, y + height), fill: color, stroke: rung-stroke, name: "rung")
    let symbol-center = (rel: (1.15, 0), to: "rung.west") // Keep the symbols near the left edge
    // Left-align text next to the symbol circle
    content((rel: (circle-r + 0.2, 0), to: symbol-center), align(horizon, label), anchor: "west")
    if symbol != none {
      circle(symbol-center, radius: circle-r, fill: color, stroke: rung-stroke)
      content(symbol-center, align(center, symbol))
    }
    if ingredient != none {
      // Name the new ingredient right-aligned on the label's second line
      content((rel: (-0.3, -0.33), to: "rung.east"), emph(ingredient), anchor: "east")
    }
  }

  // Ladder rails run from the ground to the top of the last rung
  for x in (-width / 2, width / 2) { line((x, 0), ((x, 0), "|-", "rung.north"), stroke: 0.7pt) }
})