Skip to content

Commit 1f1b65f

Browse files
lno: compatibility with pyscf >= 2.14 (dfccsd._contract_vvvv_t2 signature) and NumPy 2 (_cp) (#212)
* lno: compatibility with pyscf >= 2.14 and NumPy 2 in lnoccsd - DFLNOCCSD._contract_vvvv_t2: pyscf 2.14 changed dfccsd._contract_vvvv_t2 to a seven-argument signature (mycc, mol, vvL, VVL, t2, out, verbose). The old six-argument call shifted the arguments, so t2 arrived as out and every DF-LNO-CCSD run crashed. The call now adapts to the installed signature. - _cp: np.array(a, copy=False, ...) raises under NumPy 2 when a copy is unavoidable, which it is for an h5py slice on the out-of-core path (max_memory below the fragment's Lov block). np.asarray keeps the intended behaviour on both NumPy 1 and 2. Both fixes have been running in production LNO-CCSD(T) calculations on benzene and naphthalene (cc-pVDZ/cc-pVTZ, pyscf 2.14.0, NumPy 2) since 2026-09-10. * lno: call dfccsd._contract_vvvv_t2 with its real signature, keep _cp NumPy-2 safe, add a regression test for the DF-CCSD fragment solver Both fixes sit in the DF-CCSD fragment solver (MODIFIED_DFCCSD / _make_df_eris / _DFChemistsERIs), which lnoccsd.CCSD selects only when a fragment's vvvv block does not fit in 70 % of the available memory; the shipped water-dimer tests never reach it. Review of 24/25 Sep: - pyscf's dfccsd._contract_vvvv_t2 has had the VVL argument since at least v2.10, so the six-argument call was wrong for every supported version; call it with (mycc, mol, vvL, VVL, t2, out, verbose) unconditionally, no signature inspection, VVL = vvL as in pyscf's own _ChemistsERIs. - _cp: np.asarray(a, order='C') (NumPy 2 raises on copy=False for the non-contiguous Lov slices of the blocked loops). - test_dfccsd_solver_blocked_df_eris: MODIFIED_DFCCSD on the test's water dimer with max_memory = 1 (forces the blocked loops); fails on master with ValueError in _cp, with _cp alone fixed with AttributeError in dfccsd._contract_vvvv_t2, passes with both; e_corr equals cc.CCSD on the same DF mean field to 1e-7. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
1 parent 5db5aae commit 1f1b65f

2 files changed

Lines changed: 22 additions & 2 deletions

File tree

‎pyscf/lno/lnoccsd.py‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,10 @@ def ao2mo(self, mo_coeff=None):
396396
class _DFChemistsERIs(_ChemistsERIs):
397397
def _contract_vvvv_t2(self, mycc, t2, direct=False, out=None, verbose=None):
398398
assert(not direct)
399-
return dfccsd._contract_vvvv_t2(mycc, self.mol, self.vvL, t2, out, verbose)
399+
# pyscf's dfccsd._contract_vvvv_t2 is (mycc, mol, vvL, VVL, t2, out=None, verbose=None) -- VVL has been
400+
# part of the signature since at least pyscf 2.10; with six arguments t2 arrived as VVL and `out` as t2.
401+
# VVL = vvL, as in pyscf.cc.dfccsd._ChemistsERIs.
402+
return dfccsd._contract_vvvv_t2(mycc, self.mol, self.vvL, self.vvL, t2, out, verbose)
400403
def _make_df_eris(cc, mo_coeff=None):
401404
from pyscf.ao2mo import _ao2mo
402405

@@ -467,7 +470,9 @@ def _make_df_eris(cc, mo_coeff=None):
467470
return eris
468471

469472
def _cp(a):
470-
return np.array(a, copy=False, order='C')
473+
# NumPy 2 raises on copy=False when a copy is unavoidable (a non-contiguous Lov slice in the
474+
# blocked loops of _make_df_eris); np.asarray keeps the NumPy 1.x meaning.
475+
return np.asarray(a, order='C')
471476

472477
class MODIFIED_DFCCSD_complex:
473478
pass

‎pyscf/lno/test/test_lnoccsd.py‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,21 @@ def tearDownClass(cls):
6666
cls.mol.stdout.close()
6767
del cls.mol, cls.mf, cls.ecano, cls.frozen
6868

69+
def test_dfccsd_solver_blocked_df_eris(self):
70+
# The DF-CCSD fragment solver (chosen by lnoccsd.CCSD when a fragment's vvvv block does not fit in
71+
# memory, i.e. large fragments or a small max_memory) with the blocked loops of _make_df_eris:
72+
# _cp must accept a non-contiguous Lov slice under NumPy 2, and _DFChemistsERIs._contract_vvvv_t2
73+
# must call pyscf's dfccsd._contract_vvvv_t2 with its (mycc, mol, vvL, VVL, t2, out, verbose)
74+
# signature. Neither path is reached by the LNO tests above on this small system.
75+
from pyscf.lno import lnoccsd
76+
ref = cc.CCSD(self.mf, frozen=self.frozen).run().e_corr
77+
mycc = lnoccsd.MODIFIED_DFCCSD(self.mf, frozen=self.frozen)
78+
mycc.max_memory = 1 # forces the blocked loops; the arrays stay small
79+
mycc.verbose = 0
80+
mycc.kernel()
81+
self.assertTrue(mycc.converged)
82+
self.assertAlmostEqual(mycc.e_corr, ref, 7)
83+
6984
def test_lno_pm_by_thresh(self):
7085
mol = self.mol
7186
mf = self.mf

0 commit comments

Comments
 (0)