Periodic KS-DFT¶
Switch from HF to DFT by using PeriodicKSOptions instead of
PeriodicSCFOptions and calling run_rks_periodic:
import numpy as np
from vibeqc import (
Atom, BasisSet, PeriodicSystem, PeriodicKSOptions,
monkhorst_pack, run_rks_periodic,
)
unit_cell = [Atom(1, [0, 0, 0]), Atom(1, [0, 0, 1.4])]
sysp = PeriodicSystem(
dim=1,
lattice=np.diag([4.0, 30.0, 30.0]),
unit_cell=unit_cell,
)
basis = BasisSet(sysp.unit_cell_molecule(), "pob-tzvp")
kmesh = monkhorst_pack(sysp, [6, 1, 1])
opts = PeriodicKSOptions()
opts.functional = "PBE"
opts.lattice_opts.cutoff_bohr = 12.0
opts.lattice_opts.nuclear_cutoff_bohr = 40.0
opts.conv_tol_energy = 1e-10
result = run_rks_periodic(sysp, basis, kmesh, opts)
print(f"E_KS per cell = {result.energy:.10f}")
print(f" E_Coulomb = {result.e_coulomb:.10f}")
print(f" E_xc = {result.e_xc:.10f}")
print(f" E_HF_exch = {result.e_hf_exchange:.10f} (0 for pure DFT)")
Functional support¶
All 500+ libxc functionals work in principle. Today’s validation covers:
LDA (Slater + VWN5)
PBE — pure GGA
BLYP — pure GGA
Hybrid functionals (B3LYP, PBE0, …) work in the code path — the
exchange_scale parameter on build_fock_2e_real_space routes the
HF-exchange fraction through the lattice sum — but have not yet been
validated end-to-end against CRYSTAL reference numbers. That waits
for Phase 12e’s Ewald splitting.
Grid quality¶
Reuse the molecular-DFT grid controls:
opts.grid.n_radial = 99
opts.grid.n_theta = 29
opts.grid.n_phi = 58
The grid is built over the unit-cell atoms with the molecular Becke partition scheme. For tight unit cells where image-atom Voronoi cells intrude on the reference cell, expect small (<1e-4 Ha) boundary effects until the periodic Becke partition lands in Phase 12f.