Periodic-method requirements from basissetdev¶
Audience: the periodic-methods main development chat.
Authors: basissetdev, M. F. Peintinger.
Date: 2026-05-08; last refresh 2026-05-13.
Status: living document; rebased onto main as features land.
2026-05-13 refresh. Since the initial audit on
2c7c7df, Codex landed the native GDF backend (periodic_rhf_gdf.py,periodic_k_gdf.py,periodic_gdf_blocks.py) — replacing the retired in-process PySCF periodic backend, which CLAUDE.md § 10 now formally forbids. CRYSTAL-style FMIXING (previous-Fock mixing) and Fermi-Dirac smearing are wired through the GDF and Ewald multi-k paths. Shared SCF mixing helpers (validate_fraction_01,mix_fock_matrices) live incpp/include/vibeqc/scf_mixing.hpp— new basissetdev work must reuse these, never duplicate (manifest rule). See per-requirement status notes below.
This is the punch list of periodic capabilities basissetdev needs
in order to reproduce the published pob-paper test sets in vibe-qc.
The papers in scope are:
M. F. Peintinger, D. Vilela Oliveira, T. Bredow, J. Comput. Chem. 34, 451 (2013). [pob-TZVP, PT2013]
D. Vilela Oliveira, J. Laun, M. F. Peintinger, T. Bredow, J. Comput. Chem. 40, 2364 (2019). [pob-TZVP-rev2 + pob-DZVP-rev2, VO2019]
Together they enumerate roughly 70 binary and ternary ionic / semiconducting / TM-oxide / metallic systems plus a 9-compound subset of the X23 molecular crystals. Each requirement here is tagged with the table(s) it gates and the count of compounds that become runnable when it lands.
Conventions¶
P0: hard blocker for ≥10 compounds in the test set.
P1: blocker for 1-10 compounds, or for cross-method validation.
P2: nice-to-have / faithful reproduction of CRYSTAL workflow.
vibe-qc state originally audited on commit
2c7c7dfofbasissetdev; refreshed 2026-05-13 on commit1bf32cc.Feature counts below are conservative — orthorhombic is the most permissive cell shape vibe-qc currently handles.
Test-set overview¶
Source |
Table |
Cell shape |
Compounds |
Listed |
|---|---|---|---|---|
PT2013 |
T4 |
cubic |
12 |
LiCl, NaCl, LiF, NaF, KF, CaF₂, K₂O, MgO, CaO, LiH, NaH, KH |
PT2013 |
T5 |
hexagonal |
10 |
BeF₂, ScCl₃, MgBr₂, BeO, α-SiO₂, B₂O₃, Al₂O₃, NaNO₃, MgCO₃, FePO₄ |
PT2013 |
T6 |
orthorhombic |
5 |
BeBr₂, NaNO₂, CaH₂, CrCl₂, GeSe |
PT2013 |
T8 |
cubic semiconductor |
22 |
C(diamond), Si, Ge, AlP, AlN, Na₂Se, GaAs, GaP, ZnS, MnSe, ZnSe, β-BN, β-SiC, TiC, Cu₃N, VC, VN, TiN, CrN, K₂S, MnS |
PT2013 |
T9 |
hexagonal semicond. |
9 |
NiAs, α-SiC, α-BN, B₄C, ScB₂, CoS, CuS, GaF₃, GeO₂ |
PT2013 |
T10 |
cubic TM oxide |
7 |
Sc₂O₃, MnO, FeO, CoO, NiO, Cu₂O, ZnCr₂O₄ |
PT2013 |
T11 |
hexagonal/tetragonal TM oxide |
4 |
V₂O₃, Cr₂O₃, ZnO, TiO₂(rutile) |
PT2013 |
T12 |
cubic metal |
11 |
Li, Na, K, Ca, Sc, V, Cr, Fe, Ni, Cu, Al, Ni₃Al |
PT2013 |
T14 |
HF cubic ionic |
12 (subset of T4 + K₂S) |
LiCl, NaCl, LiF, NaF, KF, CaF₂, K₂O, MgO, CaO, LiH, NaH, KH |
VO2019 |
T2 |
cubic ionic |
14 |
+ KBr, SiF₄ |
VO2019 |
T3 |
hexagonal ionic |
10 |
(overlap with PT2013 T5) |
VO2019 |
T4 |
orthorhombic ionic |
4 |
NaNO₂, CaH₂, CrCl₂, GeSe |
VO2019 |
T6 |
cubic semicond. |
14 |
(subset of PT2013 T8) |
VO2019 |
T7 |
hex semicond. |
9 |
(subset of PT2013 T9) |
VO2019 |
T9 |
cubic TM oxide |
7 |
(overlap with PT2013 T10) |
VO2019 |
T10 |
hex/tet TM oxide |
5 |
+ TiO₂(anatase) |
VO2019 |
T14 |
molecular crystal |
9 |
from X23 — dispersion-dominated |
VO2019 |
Figs 2–7 |
molecular hydride dimer |
~30 |
H_n A–AH_n at 1.4–5 Å, A=Li–Br |
Total unique compounds: ≈75. Counted by cell shape: roughly 40 cubic, 20 hexagonal, 10 orthorhombic/tetragonal, plus the molecular-crystal subset.
Hard requirements¶
R1 — Non-orthorhombic Ewald [P0]¶
The current ewald_j / periodic_*_ewald family rejects any cell
that is not strictly orthorhombic, because the FFT Poisson solver
indexes the real-space grid by Cartesian (a×b×c) box dimensions.
Hexagonal, trigonal, and tetragonal cells with non-orthogonal a/b
or a/c are refused at SCF entry with:
“system lattice must be orthorhombic (FFT Poisson solver does not yet support triclinic cells).”
The test-set fraction that requires non-orthorhombic Ewald:
Hexagonal: PT2013 T5 (10), PT2013 T9 (9), PT2013 T11 (3), VO2019 T3 (10), VO2019 T7 (9), VO2019 T10 (4) — ≈32 unique compounds blocked.
Tetragonal: TiO₂(rutile), TiO₂(anatase) — 2 compounds.
Acceptance: run_rhf_periodic_multi_k_ewald3d accepts
hexagonal (a, b=a, c, α=β=90°, γ=120°) cells; total energy on
α-Al₂O₃ (R-3c) at experimental geometry agrees with PySCF.pbc.GDF
to 100 µHa per formula unit. Tetragonal (P4/mmm and P4₂/mnm
spacegroups) covered by the same fix.
Note for kpoints.py: the hexagonal/trigonal Γ-centring guard
is already in place; the work is on the Poisson side. No changes to
the k-mesh API required.
R2 — Multi-k MP-grid SCF on production basis sizes [P0]¶
Status as of 2026-05-13: partially landed.
Native GDF backend live: periodic_rhf_gdf.py (Γ-only),
periodic_k_gdf.py (multi-k), periodic_gdf_blocks.py (Bloch
assembly from lattice blocks). The in-process PySCF periodic
backend was retired (commits 545db04 / 7ab9384) — manifest
§ 10 now forbids importing PySCF inside vibe-qc; parity testing
against PySCF happens out-of-process via examples/regression/ runner_pyscf.py. The CaF₂ pob-TZVP RKS-PBE CRYSTAL14 regression
fixture (e46211c) is the first cubic-ionic parity test
exercising basissetdev’s .d12 sidecar pipeline (Phase 14h).
Already landed in the multi-k path:
smearing_temperatureFermi-Dirac occupations (periodic_rhf_multi_k_ewald.pylines 33-34, 156, 445;periodic_k_gdf.pyline 76). Unit-bearing strings (“0.01 Ha”, “300 K”) accepted via the GDF gamma path (7eacfd3). Free energy withE - T·Scorrection surfaced in the result bundle (periodic_rhf_gdf.pyline 548).fock_mixing(CRYSTAL FMIXING-equivalent) wired through both Γ-GDF and multi-k. Validation against MgO PBE/POB-TZVP CRYSTAL14 totals viaexamples/regression(commit7c02666).Low-dimensional MP meshes (1D / 2D systems) accepted by the legacy path (
f4d95f9).Periodic dimensionality is logged in GDF jobs (
56fd2e7).
Still open:
Validation against CRYSTAL k-mesh density at production sizes. PT2013 / VO2019 use Pack-Monkhorst grids around 8×8×8 for rocksalt ionics, 4×4×4 for the larger sesquioxides. vibe-qc tests have so far focused on small (2×2×2 to 4×4×4) grids; the linear-system size at full pob-TZVP × 8×8×8 is unmeasured. The Phase-14h
.d12sidecars now make this measurable: same compound, same basis, same k-mesh, on both codes viavq. Bench needed.Smoke test on metallic Cu (FCC, T12). Smearing is in; the metal-specific SCF flow at production size hasn’t been benchmarked. T12 metals (Li, Na, K, Ca, Sc, V, Cr, Fe, Ni, Cu, Al, Ni₃Al) inherit any remaining issues.
Acceptance: MgO total energy at Γ + 8×8×8 Pack-Monkhorst with pob-TZVP/PW1PW agrees with PT2013 SI Table 1 (E = −275.477 595 Ha per cell) to 1 mHa. Metallic Cu (FCC) converges with smearing σ = 0.01 Ha and reproduces the 2013 Table 12 lattice constant (3.506 Å) to 0.01 Å.
Reuse, don’t duplicate. Shared mixing helpers
(validate_fraction_01, mix_fock_matrices) in
cpp/include/vibeqc/scf_mixing.hpp are the canonical
implementation across molecular + periodic, per manifest § 10.
Any new basissetdev SCF-control work plugs into this header.
R3 — Stable open-shell UKS / UHF for transition-metal oxides [P0]¶
Status as of 2026-05-13: still blocked. No change since the
2026-05-08 audit; the broken-symmetry initial guess for AFM
ground states has not landed. Basissetdev’s Goal 3 ships the 6
AFM-II compounds (MnO, FeO, CoO, NiO, α-MnS, α-MnSe) as
BLOCKED ON: R3 stubs — their .py inputs are wired so the
moment R3 lands, only the initial-guess hook needs filling in.
The .d12 sidecars (Phase 14h) skip emission for AFM compounds
since the CRYSTAL ATOMSPIN block requires the same magnetic-
ordering decision; both emit when R3 + ATOMSPIN-aware generator
support land together.
The multi-k UKS (periodic_uks_multi_k_ewald.py) and UHF
(periodic_uhf_multi_k_ewald.py) modules exist. The blocker is
not the kernel but the initial-guess strategy for
antiferromagnetic ordering. Currently both default to Hcore →
identical α/β densities → SCF converges to the closed-shell
solution by symmetry. This is the wrong basin for AFM systems.
Compounds blocked (counted once across PT2013 + VO2019): MnO, FeO, CoO, NiO (T10/T9), Cr₂O₃, V₂O₃ (T11/T10), CrCl₂ (T6/T4), CrN, MnS, MnSe (T8/T6) — 10 transition-metal compounds.
Acceptance: broken-symmetry initial guess (Mulliken-localised single-atom UKS densities tiled into the AFM unit cell, optionally with a small spin-symmetry-breaking field on the magnetic sublattice). NiO total energy with pob-TZVP/PW1PW reproduces PT2013 SI Table 1 (−3167.495 768 Ha per cell, two formula units in the AFM-II unit cell) to 1 mHa.
R4 — PW1PW hybrid functional [P0]¶
PW1PW is the workhorse functional for PT2013 and VO2019. It is the 1-parameter global hybrid of Bredow & Gerson (T. Bredow, A. R. Gerson, Phys. Rev. B 61, 5194 (2000), DOI 10.1103/PhysRevB.61.5194), originally introduced as the “HF+PWGGA hybrid approach” in §III.D of that paper. The mixing α = 0.20 was empirically optimised on MgO / NiO / CoO bulk properties and coincidentally matched the B3LYP exchange-mixing fraction. The “PW1PW” name came into use in subsequent CRYSTAL-community papers (Peintinger 2013 onward).
Definition:
E_x = 0.20 · E_x^HF + 0.80 · E_x^PW91E_c = E_c^PW91
Where PW91 = Perdew-Wang 91 GGA (libxc IDs XC_GGA_X_PW91 = 109
and XC_GGA_C_PW91 = 134). The hf_exchange_fraction mechanism
in periodic_rks_multi_k_ewald.py already supports α = 0.20
mixing; what’s missing is the named entry in vibe-qc’s functional
registry that resolves "PW1PW" to this triplet. Status
2026-05-13: still missing — no registry alias landed since the
audit. The 33 .d12 parity sidecars in Phase 14h currently emit
the no-DFT (HF) form; once PW1PW resolves, the generator just
flips method="pw1pw" and CRYSTAL’s PW1PW keyword does the
matching parity run.
Note: PW1PW is distinct from PBE0 (PBE-based hybrid, α = 0.25), B3LYP (three-parameter Becke88 + LYP + VWN5), and plain PW91 (no HF mixing). Do not silently substitute any of these for PW1PW in benchmarks against the pob SI tables.
Acceptance: functional="PW1PW" resolves to the Bredow-Gerson
hybrid with α = 0.20 and PWGGA (X + C) DFT components. RKS total
energy on MgO with pob-TZVP at converged k-mesh equals PT2013 SI
Table 1 (E = −275.477 595 Ha per cell) to 1 mHa. (Without R1+R2
this is testable only for cubic ionics and TM oxides.)
The Bredow-Gerson 2000 paper additionally benchmarks HF+LYP, HF
alone, B3LYP, BLYP, PBE, and plain PWGGA on MgO / NiO / CoO. If
the periodic chat wants a smaller cross-validation acceptance
target, the seven-functional comparison from that paper’s
Tables I–IV is a clean test fixture: ≈30 (compound × functional)
data points at known geometry. PDF reference:
/private/tmp/bredow2000.pdf on the user’s machine; user-shipped
2026-05-08.
R5 — Geometry optimisation in periodic [P0]¶
Status as of 2026-05-13: still blocked. Gradients are
present and have been extended (RKS gradients,
periodic_gradient_rks.py; open-shell gradients,
periodic_gradient_open_shell.py; multi-k gradients,
periodic_gradient_multi_k.py), but no atom-or-lattice
relaxation driver. Phase 14h .d12 sidecars fix the lattice at
the experimental value so the parity test isn’t also gated on
this requirement.
The molecular path has _optimize_geometry (runner.py); the
periodic path has gradients (periodic_gradient*.py) but no
relaxation driver. Every line of every pob-paper table is a
relaxed geometry: lattice parameters and atomic positions are
optimised against the basis. Without relaxation, comparison to
the paper tables is impossible.
Two flavours needed:
Atomic-position-only relax at fixed lattice. Required for T5/T6/T9/T10/T11/T8 (anything with internal coordinates), ≈40 compounds.
Lattice + atomic-position simultaneous relax. Required for every cell in the test set, ≈75 compounds.
Acceptance: wrap the existing periodic-gradient drivers behind an ASE BFGS / FIRE optimiser that updates both atomic positions and the lattice tensor. NaCl (Fm-3m) with pob-TZVP/PW1PW relaxes from 5.5 Å starting cell to 5.609 ± 0.005 Å (PT2013 Table 4), atomic positions stay at (0, 0, 0) and (½, ½, ½) by symmetry.
For the lattice-tensor side, the stress tensor is the natural primitive but is currently not in vibe-qc (memory: deferred to v0.8). A first cut can use finite-difference lattice gradient (perturb each lattice parameter by ε, recompute total energy, divide) and feed that to the BFGS optimiser. Slower than analytical stress but unblocks the test set.
R6 — Counterpoise / BSSE for periodic crystals [P1]¶
VO2019’s central novelty is the BSSE-aware re-optimisation. They
use CRYSTAL’s ATOMBSSE to compute the per-atom counterpoise
correction in a periodic crystal (ghost-atom basis on the heavy
atom, no nuclei, no electrons, in the otherwise-real lattice).
vibe-qc has no equivalent yet. To reproduce VO2019 numbers, needed; to use the rev2 basis sets, not strictly needed (the basis already incorporates the BSSE-aware exponent shift).
For Goal 4 of basissetdev (re-running the rev2 optimisation in
vibe-qc), counterpoise IS required as part of the objective
function. Hence P1 not P0.
Acceptance: ghost_atoms=[(symbol, position), …] parameter on
PeriodicSystem that places basis functions but no nuclei / no
electrons. NaH ATOMBSSE matches CRYSTAL within 1 mHa.
Cross-method validations¶
R7 — Functional zoo: PBE, PBE0, B3LYP, BLYP, HSE [P1]¶
PT2013 and VO2019 cite cross-validation against B3LYP and PBE0 in side notes. vibe-qc’s libxc-based functional registry should already accept these strings (the runner advertises them). What’s missing is end-to-end verification at converged k-mesh + multi-k SCF for the cubic ionic subset (which is the easy 12-compound benchmark). Listing here so the periodic chat doesn’t deprioritise.
Acceptance: the 12 cubic ionics from PT2013 T4 run with PBE, PBE0, B3LYP, BLYP, HSE06 (each), in addition to PW1PW.
R8 — Wu-Cohen GGA (WC) [P2]¶
WC (XC_GGA_X_WC = 118; correlation typically PBE) is used in
PT2013 for the metallic systems (preliminary basis-set
optimisation). Easy to add — libxc has it; the question is the
registry alias.
Acceptance: functional="WC" resolves to WC-X + PBE-C.
Numerics & screening¶
R9 — TOLINTEG-equivalent screening control [P1]¶
linear_dependence.py and eigs_preflight.py already point at
LatticeSumOptions.schwarz_threshold as the TOLINTEG-equivalent
knob. PT2013 explicitly mentions ITOL5 = 27 (vs default 14) for
ionic SCF convergence — i.e. extremely tight Coulomb-tail screening.
Need to verify schwarz_threshold covers ITOL4 (Schwarz
two-electron) AND ITOL5 (penetration / overlap-based truncation
distance). If they’re conflated in vibe-qc, surface separately.
Acceptance: running the sulfide subset (ZnS, MnS, K₂S, CoS, CuS) with default screening converges; bumping the equivalent of ITOL5 to 27 closes any residual SCF oscillation.
R10 — Atomic-reference HF energies for cohesive / atomization [P1]¶
PT2013 Table 13 reports atomization enthalpies. To compute these you need (a) the periodic total energy and (b) the isolated-atom total energy in the same basis. The molecular path handles (b) at the symmetry-broken UHF level; the question is exposing a single-atom reference path that accepts a Mulliken-style fractional- occupation specification (atoms in PT2013 are computed with “neutral atomic configurations from our website” — the .single files in the Bredow archive).
Acceptance: vq.atomic_reference_energy(symbol, basis, configuration="neutral") returns the SCF energy for the open-shell
atom with the published occupation, for every element in pob-TZVP.
Lower-priority polish¶
R11 — D3(BJ) for periodic [P2]¶
dispersion.py exists in molecular path. VO2019 Table 14 applies
D3(BJ) on top of pob-TZVP / pob-TZVP-rev2 for the X23-subset
molecular crystals; the deltas drive ≈2-3 % lattice-constant
improvements. Periodic D3 is an additive post-SCF step on the
relaxed geometry — needs lattice summation of the C₆/C₈ pairs but
no SCF intrusion.
Acceptance: ZnO + D3(BJ) with pob-TZVP-rev2 reproduces VO2019
Table 14 D3-corrected c to 0.01 Å.
R12 — ATOMBSSE for the molecular hydride dimers [P2]¶
The 2019 BSSE-correction recipe uses molecular counterpoise on H_n A–AH_n dimers (computed in ORCA 3.0 with MP2). vibe-qc’s molecular DF MP2 was wired in v0.7.3. A native vibe-qc version of this step is needed for Goal 4 (re-running the rev2 optimisation without external ORCA dependencies).
Acceptance: counterpoise(H₂O)₂ at 2.5 Å with vibe-qc/MP2 matches ORCA 3.0 MP2 to 1 mHa.
Out of scope here (other chats / future versions)¶
Periodic stress tensor. Memory: reserved for vibe-qc v0.8. Once landed, R5 lattice opt becomes analytical instead of FD.
Slab / surface support. Same: v0.8 deliverable.
AutoAux periodic aux basis. Owned by the DF dev chat (memory:
feedback_aux_basis_routing.md).CCM / cyclic-cluster method. Memory: deferred to a later vibe-qc version.
Suggested implementation order¶
The order that unblocks the most of the test set per landed feature:
R5 atomic-position relax + R4 PW1PW + R7 functional verification → unlocks 12 cubic ionics from PT2013 T4 + 12 cubic ionics from VO2019 T2 (overlap) + 22 cubic semiconductors from PT2013 T8 + 7 cubic TM oxides from PT2013 T10 = ≈40 compounds runnable.
R3 broken-symmetry UKS guess → unlocks the 10 TM oxide / chloride / nitride compounds.
R1 non-orthorhombic Ewald → unlocks the 32 hexagonal/ tetragonal compounds. Big single-feature payoff.
R5b lattice relax (FD lattice gradient) → enables the actual lattice-constant comparison vs. paper tables for everything above.
R2 metallic k-mesh smearing → unlocks the 12 cubic metals.
R6 ATOMBSSE periodic + R12 molecular counterpoise → unlocks the rev2 re-optimisation pipeline for Goal 4.
Status table (as of refresh on 1bf32cc, 2026-05-13)¶
Req |
Title |
State |
|---|---|---|
R1 |
Non-orthorhombic Ewald |
MISSING |
R2 |
Multi-k MP-grid SCF |
partial — native GDF + smearing + FMIXING landed; production-size CRYSTAL14 parity bench outstanding |
R3 |
Open-shell UKS for AFM TM oxides |
partial — kernels exist, BS guess still missing |
R4 |
PW1PW hybrid functional |
partial — |
R5 |
Periodic geometry / lattice optimisation |
MISSING — gradients exist (RKS / open-shell / multi-k), no relax driver |
R6 |
Counterpoise / BSSE periodic |
MISSING |
R7 |
PBE/PBE0/B3LYP/BLYP/HSE verification |
partial — registry exists, end-to-end untested at production size |
R8 |
WC GGA functional |
partial — libxc has it, registry alias TBD |
R9 |
TOLINTEG-equivalent screening control |
partial — |
R10 |
Atomic-reference HF for atomisation |
partial — molecular UHF works, fractional-occ wrapper missing |
R11 |
D3(BJ) for periodic |
partial — molecular path exists, periodic glue missing |
R12 |
ATOMBSSE molecular dimer |
partial — molecular MP2 works, counterpoise glue missing |
Hand-off note¶
This document is the deliverable from basissetdev to the
periodic-methods chat. It does not prescribe how each requirement
is implemented; that is the periodic chat’s call. When a
requirement lands, mark it ✅ here and update
PLAN.md Goal 2 status. basissetdev rebases onto
main after each landing.