# Spectra & density of states

The final property family reads the **orbital-energy spectrum** — the ladder of orbital energies an SCF
produces. Broadened into a **density of states (DOS)** and summarized by the **HOMO–LUMO gap**, it connects
your calculation to electronic structure, optical onset, and chemical hardness. These live in `qc.prop.spec`.

## Theory: from orbital levels to a spectrum

An SCF returns a set of orbital energies $\{\varepsilon_i\}$ — the occupied levels up to the **HOMO** (highest
occupied) and the empty levels from the **LUMO** (lowest unoccupied) up. Two summaries matter:

- The **HOMO–LUMO gap** $\varepsilon_{\text{LUMO}} - \varepsilon_{\text{HOMO}}$ — a first estimate of the
  excitation energy and a measure of kinetic stability (large gap = hard, inert; small gap = reactive). It is
  the orbital-energy sibling of the chemical hardness from the [reactivity chapter](cdft-reactivity.md).
- The **density of states (DOS)** — the discrete levels **broadened** into a continuous curve $g(\varepsilon)$
  by convolving each with a Gaussian/Lorentzian. It shows *how many* states sit near each energy, the natural
  way to compare a spectrum of levels or to line up computed and photoelectron spectra.

For a molecule the "DOS" is really a broadened stick spectrum of discrete levels; the same machinery underlies
band-structure DOS for extended systems.

## The HOMO–LUMO gap

```python
import qc
water = "O 0 0 0.117; H 0 0.757 -0.469; H 0 -0.757 -0.469"
m = qc.chk.new(atom=water, ao="cc-pvdz", unit="angstrom").scf(ref="r").run()

fl = qc.prop.spec.fermi_level(m)
fl["homo"], fl["lumo"]     # -13.419, 5.049   frontier orbital energies (eV)
fl["gap"]                  # 18.468           the HOMO–LUMO gap (eV)
fl["fermi_level"]          # -4.185           midgap "Fermi" level
```

Water's gap of ~18.5 eV is large — consistent with its chemical inertness, and (as expected) equal to the
hardness $\eta$ from the [conceptual-DFT chapter](cdft-reactivity.md), since both are $I - A$ in the Koopmans
picture.

## Density of states

`qc.prop.spec.dos` broadens the level spectrum into a curve you can plot:

```python
dos = qc.prop.spec.dos(m)
dos["energies"]     # the energy axis (2000 points, eV)
dos["tdos"]         # the total DOS g(ε)
dos["pdos"]         # projected DOS (per atom / angular momentum)
dos["levels"]       # the 24 underlying discrete orbital energies
dos["broadening"], dos["fwhm"]   # the broadening scheme and width
```

Plotting `tdos` vs `energies` gives the broadened spectrum; `pdos` decomposes it by atom or angular momentum
(which atoms contribute states at a given energy). `qc.prop.spec` also provides `band_center` (a d-band-center-
style first moment, useful in catalysis) and `fermi_level`.

## Related: moments and spin

Two more single-number properties round out this family:

```python
qc.prop.mpol.molecular(m)["dipole_magnitude_debye"]   # 2.056   the molecular dipole (Debye)
qc.prop.mpol.polarizability(m)["polarizability"]      # atomic polarizabilities / C6 (Hirshfeld-partitioned)
qc.prop.spin.s_squared(m)                             # 0.0     ⟨S²⟩ (0 for a closed-shell singlet)
```

The **dipole** (2.06 D for water, close to the experimental 1.85 D — HF overestimates it) is the leading
electric moment; `qc.prop.spin.s_squared` reports ⟨S²⟩ (0 here for RHF; non-zero contamination for UHF, as in
the [SCF chapter](../scf.md)).

## Worked example

```python
import qc
water = "O 0 0 0.117; H 0 0.757 -0.469; H 0 -0.757 -0.469"
m = qc.chk.new(atom=water, ao="cc-pvdz", unit="angstrom").scf(ref="r").run()

fl = qc.prop.spec.fermi_level(m)
print(f"HOMO {fl['homo']:.2f} eV, LUMO {fl['lumo']:.2f} eV, gap {fl['gap']:.2f} eV")
# HOMO -13.42 eV, LUMO 5.05 eV, gap 18.47 eV

dos = qc.prop.spec.dos(m)
print("DOS points:", len(dos["energies"]), "| levels:", len(dos["levels"]))   # 2000 | 24
```

:::{exercise}
:label: ex-spec

1. Molecule X has a HOMO–LUMO gap of 1.5 eV, molecule Y of 8 eV. Which is likely more reactive / more deeply
   coloured, and which is the harder molecule?
2. Why is the DOS a *broadened* curve rather than just the list of orbital energies — what does the broadening
   let you do?
3. `qc.prop.spin.s_squared` returns 0.0 for your closed-shell RHF water but 0.76 for a UHF methyl radical.
   What does the 0.76 (vs the exact 0.75) tell you?
:::

:::{solution} ex-spec
:class: dropdown

1. **Molecule X** (1.5 eV gap) is **more reactive and more deeply coloured** — a small gap means a low
   excitation energy (visible-light absorption) and easy electron rearrangement. **Molecule Y** (8 eV) is the
   **harder**, more inert molecule (a large gap ≈ large hardness).
2. The discrete levels are convolved with a Gaussian/Lorentzian to make a continuous $g(\varepsilon)$, which
   lets you **compare with experiment** (photoelectron/absorption spectra are broadened) and read off *where*
   states cluster; a bare list of energies cannot be overlaid on a measured spectrum.
3. ⟨S²⟩ = 0.76 vs the exact 0.75 for a doublet indicates **slight spin contamination** of the UHF
   wavefunction — a small admixture of higher-spin states, acceptable here but worth watching (the
   [SCF chapter](../scf.md) discusses it).
:::

That completes Part III. You can now go from a molecule to an SCF, forces and geometries, correlated energies,
solvation and dispersion, pictures, and a full analysis of charges, bonding, topology, aromaticity,
reactivity, and spectra — all in one toolkit. Beyond here, [Part IV](../../30-hpc/index.md) scales these
calculations across threads, machines, and GPUs.
