pob-* basis-set verification report¶
Date: 2026-05-08 (work conducted on basissetdev)
Scope: verify the three pob-* basis files bundled in vibe-qc
against the upstream Bredow-group sources and the supporting
information of the cited papers.
Tool: scripts/basisset_dev/pob_basis_verify.py
Findings¶
Bug: sulfur d-polarisation column-swap in shipped pob-TZVP and pob-TZVP-rev2¶
Both shipped pob-tzvp.g94 and pob-tzvp-rev2.g94 had the d-shell
of sulfur in the wrong columns:
D 1 1.00
0.0000000000 0.5207010100 ← bug: exponent zero
vs. authoritative source:
D 1 1.00
0.5207010100 1.0000000000 ← correct (pob-TZVP)
0.4107010100 1.0000000000 ← correct (pob-TZVP-rev2)
Root cause. The Bredow source files for sulfur in both bases
contain a typo — the d-shell scale 1.0 is mistyped as two
whitespace-separated tokens 1 0:
0 3 1 0.0 1 0
0.5207010100 1.00000000000000
CRYSTAL itself parses this correctly (it’s whitespace-tolerant
across newlines). The previous CRYSTAL-to-.g94 conversion that
seeded vibe-qc’s bundled file was not tolerant: it took the 0
on the header line as the start of the next primitive’s exponent,
shifting all subsequent fields by one slot. Result: exponent column
ended up holding 0 and the coefficient column held the d-exponent
0.5207010100. The actual 1.0000000000000 coefficient was orphaned
on the next line and silently truncated.
Chemistry impact. A d-polarisation function with exponent zero contributes nothing to the orbital expansion. Sulfur calculations using the previously bundled pob-TZVP or pob-TZVP-rev2 silently ran with no d-polarisation on S — equivalent to running pob-TZ rather than pob-TZVP for the sulfur centres. Quantitative impact on sulfur-containing systems (S, B₄C with no S, no, but ZnS, MnS, K₂S, CoS, CuS, β-ZnS in the paper test set) is yet to be measured — expect lattice-constant errors O(0.01-0.05 Å) and total-energy errors several kJ/mol per S centre, since the d-function is structurally important on second-row p-block elements.
Fix. pob_basis_verify.py parser is line-aware and detects the
“1 0” typo, reconstructing the scale as 1.0. --regenerate
re-emits the affected .g94 files. Both pob-tzvp.g94 and
pob-tzvp-rev2.g94 now carry the correct d-polarisation on sulfur.
Precision of all numbers¶
Beyond the sulfur fix, the main change is preserving full source precision. The previous shipped files rounded contraction coefficients to 10 decimal places; the Bredow CRYSTAL files publish 11 dp for pob-TZVP and pob-TZVP-rev2 and 8 dp for pob-DZVP-rev2. The regenerated files preserve every digit the source publishes.
Element coverage¶
Basis |
Source files |
Shipped |
Match |
|---|---|---|---|
pob-TZVP |
32 (H–Br excluding noble gases) |
32 |
✅ |
pob-TZVP-rev2 |
32 (same range) |
32 |
✅ |
pob-DZVP-rev2 |
19 (H–V excluding Si and noble gases) |
19 |
✅ |
Verification command¶
$ python3 scripts/basisset_dev/pob_basis_verify.py --atol 1e-15
=== pob-TZVP ===
source elements: 32
in shipped g94: 32
parity: CLEAN within tolerance
=== pob-TZVP-rev2 ===
source elements: 32
in shipped g94: 32
parity: CLEAN within tolerance
=== pob-DZVP-rev2 ===
source elements: 19
in shipped g94: 19
parity: CLEAN within tolerance
All three basis sets are byte-clean against their authoritative upstream sources to 1e-15 absolute tolerance — i.e. exact agreement to all printed digits.
Follow-ups¶
Tell Bredow group about the
16_S“1 0” typo so it can be fixed upstream (CRYSTAL parses it but other consumers may not).Add a regression test that runs
pob_basis_verify.py --atol 1e-15in CI.Once sulfur-relevant features land in vibe-qc periodic (multi-k + open-shell + hexagonal), regenerate the pob-paper benchmark numbers for sulfides (ZnS, MnS, K₂S, CoS, CuS, β-ZnS) with the corrected basis and compare to SI Tables 1 / 8 / 9. The delta between previously shipped (broken d on S) and corrected basis is the chemistry impact of this bug.