Iteration 0002 — 3fc6d11adee9 (accepted)¶
GitHub commit: 3fc6d11adee9 Published branch: fermilink-optimize/pyscf-diis_scf
Change summary¶
Guard final SCF extra-cycle get_veff rebuild with small canonical-density and gradient thresholds so near-stationary cases reuse the existing potential while FeO-like larger moves keep the full refresh
Acceptance rationale¶
Authoritative benchmark passed correctness and improved the primary metric by 7.82% without persistent caches or replayed answers.
Guardrails & metrics¶
field |
value |
|---|---|
decision |
ACCEPTED |
correctness |
ok |
correctness mode |
field_tolerances |
hard reject |
no |
guardrail errors |
0 |
incumbent commit |
|
candidate commit |
|
incumbent metric |
1.22637 |
candidate metric |
1.13042 |
baseline metric |
1.22637 |
Δ vs incumbent |
+7.824% (lower-is-better sign) |
changed files |
pyscf/scf/hf.py |
Diffstat¶
pyscf/scf/hf.py | 26 +++++++++++++++++++-------
1 file changed, 19 insertions(+), 7 deletions(-)
Diff¶
diff --git a/pyscf/scf/hf.py b/pyscf/scf/hf.py
index af1e95e61..d5d18d94d 100644
--- a/pyscf/scf/hf.py
+++ b/pyscf/scf/hf.py
@@ -214,15 +214,27 @@ Keyword argument "init_dm" is replaced by "dm0"''')
mo_energy, mo_coeff = mf.eig(fock, s1e)
mo_occ = mf.get_occ(mo_energy, mo_coeff)
dm, dm_last = mf.make_rdm1(mo_coeff, mo_occ), dm
- vhf = mf.get_veff(mol, dm, dm_last, vhf)
- e_tot, last_hf_e = mf.energy_tot(dm, h1e, vhf), e_tot
-
- fock = mf.get_fock(h1e, s1e, vhf, dm)
- norm_gorb = numpy.linalg.norm(mf.get_grad(mo_coeff, mo_occ, fock))
- if not TIGHT_GRAD_CONV_TOL:
- norm_gorb = norm_gorb / numpy.sqrt(norm_gorb.size)
norm_ddm = numpy.linalg.norm(dm-dm_last)
+ # If canonicalization barely changes the density from an already small
+ # gradient, the refreshed potential is numerically redundant.
+ skip_extra_veff = (not callable(mf.check_convergence) and
+ norm_ddm < conv_tol_grad * .3 and
+ norm_gorb < conv_tol_grad * .2)
+ if skip_extra_veff:
+ last_hf_e = e_tot
+ norm_gorb = numpy.linalg.norm(mf.get_grad(mo_coeff, mo_occ, fock))
+ if not TIGHT_GRAD_CONV_TOL:
+ norm_gorb = norm_gorb / numpy.sqrt(norm_gorb.size)
+ else:
+ vhf = mf.get_veff(mol, dm, dm_last, vhf)
+ e_tot, last_hf_e = mf.energy_tot(dm, h1e, vhf), e_tot
+
+ fock = mf.get_fock(h1e, s1e, vhf, dm)
+ norm_gorb = numpy.linalg.norm(mf.get_grad(mo_coeff, mo_occ, fock))
+ if not TIGHT_GRAD_CONV_TOL:
+ norm_gorb = norm_gorb / numpy.sqrt(norm_gorb.size)
+
conv_tol = conv_tol * 10
conv_tol_grad = conv_tol_grad * 3
if callable(mf.check_convergence):