from hf.hf import hf_gap, hf_hcore, hf_overlap, hf_scf, hf_setup_of
from hf.molecule import molecule_packs
from hf.basis import bas_nao_cart
from hf.md_eri import MDERI_SCREEN_TOL
from hf.eri_store import es_len8
from hf.opts import scf_defaults
from hf.integrals import int_eri, INT_TOL_ERI
from hf.sweep import sw_check3_arr, SW_REP_INDEX, sw_rep_new, SW_REP_NSTRAT, SW_REP_STRAT
from hfref.water_631g import (
water631g_atoms, water631g_eri8_cart, WATER631G_ERI8_CART_LEN, water631g_prims,
water631g_shells,
)
fam_atoms = water631g_atoms()
fam_shells = water631g_shells()
fam_prims = water631g_prims()
fam_n = bas_nao_cart(fam_shells)
fam_len = es_len8(fam_n)
# ---- each method alone: a mask with one bit set selects one implementation
md_report = sw_rep_new()
G_mcmurchie_davidson = int_eri(fam_atoms, fam_shells, fam_prims, 2, md_report)
hgp_report = sw_rep_new()
G_head_gordon_pople = int_eri(fam_atoms, fam_shells, fam_prims, 8, hgp_report)
# ---- how far apart they are, integral by integral, in decades
identical_integrals = 0
screened_to_zero = 0
# the decades of the histogram, 10^-22 to 10^-14
NDECADES = 8
decade_count = zeros(NDECADES)
worst_relative_gap = 0.0
smallest_gap = 1.0
# the largest gap among integrals above 0.01, in units of the double epsilon
# relative to the integral, and the largest integral screening set to zero
worst_large_gap_eps = 0.0
largest_screened = 0.0
for i to fam_len {
a = G_mcmurchie_davidson[i]
b = G_head_gordon_pople[i]
d = abs(a - b) / (1.0 + abs(a))
worst_relative_gap = max(worst_relative_gap, d)
if abs(a) > 0.01 {
worst_large_gap_eps = max(worst_large_gap_eps, abs(a - b) / abs(a) / 2.220446049250313e-16)
}
if a == 0.0 {
largest_screened = max(largest_screened, abs(b))
}
if d == 0.0 {
identical_integrals = identical_integrals + 1
}
else {
smallest_gap = min(smallest_gap, d)
if a == 0.0 {
screened_to_zero = screened_to_zero + 1
}
# decade k holds 10^(-22+k) <= d < 10^(-21+k)
k = floor(log(d) / log(10.0)) + 22
k = min(max(k, 0), NDECADES - 1)
decade_count[k] = decade_count[k] + 1
}
}
say("integrals after the eightfold symmetry", fam_len)
decade_center = zeros(NDECADES)
for k to NDECADES {
decade_center[k] = -21.5 + k
}
figure("Integrals where McMurchie-Davidson and Head-Gordon-Pople differ, by size of the difference", "$\\log_{10}$ of $|a - b|/(1 + |a|)$", "number of integrals")
bars(decade_center, decade_count, "the integrals that are not bit-identical")
# ---- each method alone through the SCF, with the default implementation of every other step
fam_mol = molecule_packs(fam_atoms, fam_shells, fam_prims)
S_water = hf_overlap(fam_mol, scf_defaults())
H_water = hf_hcore(fam_mol, scf_defaults())
E_mcmurchie_davidson = hf_scf(hf_setup_of(fam_mol, H_water, S_water, G_mcmurchie_davidson, scf_defaults())).energy
E_head_gordon_pople = hf_scf(hf_setup_of(fam_mol, H_water, S_water, G_head_gordon_pople, scf_defaults())).energy
show E_mcmurchie_davidson
show E_head_gordon_pople
# ---- a planted error, and the cross-check that names it
# Each implementation receives the two integral sets already computed above,
# plus the change to make [index, factor]; the cross-check sees only the arrays
# they return.
NUDGE = [2000, 0.999999999]
#| Implementation 0 for the cross-check: the McMurchie-Davidson integrals, unchanged.
def fam_first(g_md: Arr, g_hgp: Arr, nudge: Arr) -> Arr {
return g_md + 0.0
}
#| Implementation 1: the Head-Gordon-Pople integrals, unchanged.
def fam_second(g_md: Arr, g_hgp: Arr, nudge: Arr) -> Arr {
return g_hgp + 0.0
}
#| The deliberately wrong implementation: the Head-Gordon-Pople integrals with
#| integral `nudge[0]` multiplied by `nudge[1]`.
def fam_second_nudged(g_md: Arr, g_hgp: Arr, nudge: Arr) -> Arr {
g = g_hgp + 0.0
g[nudge[0]] = g[nudge[0]] * nudge[1]
return g
}
#| Run the cross-check over the implementations in `ms`; returns
#| `[verdict, index of the implementation blamed, index of the integral]`.
def fam_blame(ms, g_md: Arr, g_hgp: Arr, nudge: Arr, n) {
rep = sw_rep_new()
out = zeros(n)
v = sw_check3_arr(ms, g_md, g_hgp, nudge, n, n, INT_TOL_ERI, rep, out)
return [v, rep[SW_REP_STRAT], rep[SW_REP_INDEX]]
}
three_members = fam_blame([fam_first, fam_second, fam_second_nudged], G_mcmurchie_davidson, G_head_gordon_pople, NUDGE, fam_len)
two_members = fam_blame([fam_first, fam_second_nudged], G_mcmurchie_davidson, G_head_gordon_pople, NUDGE, fam_len)
blamed_member_of_three = three_members[1]
blamed_integral_of_three = three_members[2]
say("with three implementations, the one blamed (2 is the altered one)", blamed_member_of_three)
say("the integral it is blamed for", blamed_integral_of_three)
test "each method alone matches PySCF's 4186 integrals within 1e-12, and the two agree to 1e-15" {
assert_near(fam_len, 4186, 0.0)
assert_near(md_report[SW_REP_NSTRAT], 1, 0.0)
assert_near(hgp_report[SW_REP_NSTRAT], 1, 0.0)
assert_lt(hf_gap(G_mcmurchie_davidson, water631g_eri8_cart(), WATER631G_ERI8_CART_LEN), 1.0e-12)
assert_lt(hf_gap(G_head_gordon_pople, water631g_eri8_cart(), WATER631G_ERI8_CART_LEN), 1.0e-12)
assert_lt(worst_relative_gap, 1.0e-15)
# the decades span every gap, so no count was clamped into an end bin
assert_lt(1.0e-22, smallest_gap)
# screening zeroes a few tiny integrals; never more than a handful
assert_lt(screened_to_zero, 10)
# every integral is either identical or counted in one decade
total = identical_integrals
for k to NDECADES {
total = total + decade_count[k]
}
assert_near(total, fam_len, 0.0)
}
test "2483 integrals are bit-identical; the rest are within 5.75 epsilon or screened below 3e-20" {
assert_near(identical_integrals, 2483, 0.0)
assert_lt(5.7, worst_large_gap_eps)
assert_lt(worst_large_gap_eps, 5.75)
assert_lt(largest_screened, 3.0e-20)
}
test "each method alone gives PySCF's RHF energy -75.98394849810573 within 1e-9" {
assert_near(E_mcmurchie_davidson, -75.98394849810573, 1.0e-9)
assert_near(E_head_gordon_pople, -75.98394849810573, 1.0e-9)
assert_lt(abs(E_mcmurchie_davidson - E_head_gordon_pople), 1.0e-11)
}
test "with three implementations the check names the altered one and integral 2000; with two it detects the error but blames the correct one" {
assert_near(three_members[0], 0, 0.0)
assert_near(blamed_member_of_three, 2, 0.0)
assert_near(blamed_integral_of_three, 2000, 0.0)
# with two, the median is the larger value, the altered one, so the blame lands on implementation 0
assert_near(two_members[0], 0, 0.0)
assert_near(two_members[1], 0, 0.0)
assert_near(two_members[2], 2000, 0.0)
}
test "water in 6-31G has 13 basis functions and 4186 integrals after the eightfold symmetry" {
assert_near(fam_n, 13, 0.0)
assert_near(fam_len, 4186, 0.0)
}
test "about 60 percent of the integrals are bit-identical from the two methods" {
# 2483 of 4186 is 59.3 percent; "about 60" allows half of the stated 10
assert_near(identical_integrals / fam_len, 0.60, 0.05)
}
test "the screened McMurchie-Davidson code skips quartets whose Schwarz bound is under 1e-14" {
assert_near(MDERI_SCREEN_TOL, 1.0e-14, 0.0)
}
test "the integral the wrong implementation alters, integral 2000, is -0.117" {
assert_near(G_head_gordon_pople[NUDGE[0]], -0.117, 0.0005)
assert_near(NUDGE[1], 1.0 - 1.0e-9, 1.0e-16)
}
# SPDX-License-Identifier: MIT OR Apache-2.0
# SPDX-FileCopyrightText: 2026 The Viv authors