Skip to content

Commit

Permalink
lassi op_o1 hci full support
Browse files Browse the repository at this point in the history
  • Loading branch information
MatthewRHermes committed Aug 29, 2024
1 parent 35fa53f commit 062a580
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 43 deletions.
5 changes: 5 additions & 0 deletions tests/lassi/test_4frag.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from mrh.my_pyscf.lassi import LASSIS
from mrh.my_pyscf.lassi.op_o1 import get_fdm1_maker
from mrh.my_pyscf.lassi.sitools import make_sdm1
from mrh.tests.lassi.addons import case_contract_hlas_ci

def setUpModule ():
global mol, mf, las, nroots, nelec_frs, si
Expand Down Expand Up @@ -186,6 +187,10 @@ def test_fdm1 (self):
sdm1 = make_sdm1 (las, iroot, ifrag, si=si)
self.assertAlmostEqual (lib.fp (fdm1), lib.fp (sdm1), 7)

def test_contract_hlas_ci (self):
h0, h1, h2 = ham_2q (las, las.mo_coeff)
case_contract_hlas_ci (self, las, h0, h1, h2, las.ci, nelec_frs)


if __name__ == "__main__":
print("Full Tests for LASSI o1 4-fragment intermediates")
Expand Down
8 changes: 8 additions & 0 deletions tests/lassi/test_c2h4n4.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from mrh.my_pyscf.mcscf.lasscf_o0 import LASSCF
from mrh.my_pyscf.lassi.lassi import roots_make_rdm12s, root_make_rdm12s, make_stdm12s, ham_2q
from mrh.my_pyscf.lassi import LASSI
from mrh.tests.lassi.addons import case_contract_hlas_ci
topdir = os.path.abspath (os.path.join (__file__, '..'))

def setUpModule ():
Expand Down Expand Up @@ -184,6 +185,13 @@ def test_lassis_slow (self):
self.assertAlmostEqual (lsis.e_roots[0], -295.5210783894406, 7)
self.assertTrue (lsis.converged)

def test_contract_hlas_ci (self):
las, nelec_frs = lsi._las, lsi.get_nelec_frs ()
h0, h1, h2 = lsi.ham_2q ()
ci = [c[:4] for c in las.ci] # No SOC yet
nelec_frs = nelec_frs[:,:4,:] # No SOC yet
case_contract_hlas_ci (self, las, h0, h1, h2, ci, nelec_frs)

if __name__ == "__main__":
print("Full Tests for SA-LASSI of c2h4n4 molecule")
unittest.main()
Expand Down
8 changes: 8 additions & 0 deletions tests/lassi/test_c2h4n4_symm.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from mrh.my_pyscf.mcscf.lasscf_o0 import LASSCF
from mrh.my_pyscf.lassi.lassi import roots_make_rdm12s, make_stdm12s, ham_2q
from mrh.my_pyscf.lassi import LASSI
from mrh.tests.lassi.addons import case_contract_hlas_ci

def setUpModule ():
global lsi, rdm1s, rdm2s
Expand Down Expand Up @@ -121,6 +122,13 @@ def test_rdms (self):
for e1, e0 in zip (e_roots_test, e_roots):
self.assertAlmostEqual (e1, e0, 8)

def test_contract_hlas_ci (self):
las, nelec_frs = lsi._las, lsi.get_nelec_frs ()
h0, h1, h2 = lsi.ham_2q ()
ci = [c[:4] for c in las.ci] # No SOC yet
nelec_frs = nelec_frs[:,:4,:] # No SOC yet
case_contract_hlas_ci (self, las, h0, h1, h2, ci, nelec_frs)

if __name__ == "__main__":
print("Full Tests for SA-LASSI of c2h4n4 molecule with pointgroup symmetry")
unittest.main()
Expand Down
88 changes: 45 additions & 43 deletions tests/lassi/test_excitations.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def setUpModule ():
lroots[idx] = 1
las.lasci (lroots=lroots.T)
lsi = LASSI (las)
lsi.kernel (opt=0)
lsi.kernel ()

op = (op_o0, op_o1)

Expand All @@ -81,7 +81,6 @@ def test_cs_excitation (self):
stdout=mol.stdout, verbose=mol.verbose, lroots=ncsf)
ci_ref = [c[0] for c in las.ci]
nelec_ref = [[1,1] for i in range (3)]
psexc = ExcitationPSFCISolver (psref, ci_ref, las.ncas_sub, nelec_ref)
charges, spins, smults, wfnsyms = get_space_info (lsi._las)
dneleca = (spins - charges) // 2
dnelecb = -(charges + spins) // 2
Expand Down Expand Up @@ -125,32 +124,34 @@ def lassi_ref (ci1, iroot):
# the VRV solver misses is just barely below 1e-8; that of the root which it catches is
# about 1e-6. The moral of the story is that we should probably not use the excitation
# solver for double excitations directly.
for iroot in range (1, 5): #lsi._las.nroots):
with self.subTest (rootspace=iroot):
for i in range (2):
weights = np.zeros (lroots[i,iroot])
weights[0] = 1
psexc.set_excited_fragment_(1+i, (neleca[iroot,i], nelecb[iroot,i]),
smults[iroot,i], weights=weights)
conv, energy_tot, ci1 = psexc.kernel (h1, h2, ecore=h0, _add_vrv_energy=True)
self.assertTrue (conv)
e_roots1, si1 = lassi_ref (ci1, iroot)
idx_match = np.argmin (np.abs (e_roots1-energy_tot))
self.assertAlmostEqual (energy_tot, e_roots1[idx_match], 6)
self.assertEqual (idx_match, 0) # local minimum problems
# In the no-coupling limit, the Excitation solver should give the same result as the normal
# ImpureProductStateFCISolver
psexc._deactivate_vrv = True # spoof the no-coupling limit
for iroot in range (1, lsi._las.nroots):
with self.subTest ('no-coupling limit', rootspace=iroot):
for i in range (2):
weights = np.zeros (lroots[i,iroot])
weights[0] = 1
psexc.set_excited_fragment_(1+i, (neleca[iroot,i], nelecb[iroot,i]),
smults[iroot,i], weights=weights)
conv, energy_tot, ci1 = psexc.kernel (h1, h2, ecore=h0, _add_vrv_energy=True)
self.assertTrue (conv)
self.assertAlmostEqual (energy_tot, lsi._las.e_states[iroot], 8)
for opt in (0,1):
psexc = ExcitationPSFCISolver (psref, ci_ref, las.ncas_sub, nelec_ref, opt=opt)
for iroot in range (1, 5): #lsi._las.nroots):
with self.subTest (opt=opt, rootspace=iroot):
for i in range (2):
weights = np.zeros (lroots[i,iroot])
weights[0] = 1
psexc.set_excited_fragment_(1+i, (neleca[iroot,i], nelecb[iroot,i]),
smults[iroot,i], weights=weights)
conv, energy_tot, ci1 = psexc.kernel (h1, h2, ecore=h0, _add_vrv_energy=True)
self.assertTrue (conv)
e_roots1, si1 = lassi_ref (ci1, iroot)
idx_match = np.argmin (np.abs (e_roots1-energy_tot))
self.assertAlmostEqual (energy_tot, e_roots1[idx_match], 6)
self.assertEqual (idx_match, 0) # local minimum problems
# In the no-coupling limit, the Excitation solver should give the same result as the normal
# ImpureProductStateFCISolver
psexc._deactivate_vrv = True # spoof the no-coupling limit
for iroot in range (1, lsi._las.nroots):
with self.subTest ('no-coupling limit', opt=opt, rootspace=iroot):
for i in range (2):
weights = np.zeros (lroots[i,iroot])
weights[0] = 1
psexc.set_excited_fragment_(1+i, (neleca[iroot,i], nelecb[iroot,i]),
smults[iroot,i], weights=weights)
conv, energy_tot, ci1 = psexc.kernel (h1, h2, ecore=h0, _add_vrv_energy=True)
self.assertTrue (conv)
self.assertAlmostEqual (energy_tot, lsi._las.e_states[iroot], 8)

def test_multiref (self):
# Similar to test_cs_excitation, but treating the triplet manifold as the reference
Expand Down Expand Up @@ -179,8 +180,6 @@ def test_multiref (self):
for i in range (3)]
ci_ref = las.ci
nelec_ref = [[1,1] for i in range (3)]
psexc = ExcitationPSFCISolver (psref, ci_ref, las.ncas_sub, nelec_ref,
stdout=mol.stdout, verbose=mol.verbose)
charges, spins, smults, wfnsyms = get_space_info (lsi._las)
dneleca = (spins - charges) // 2
dnelecb = -(charges + spins) // 2
Expand Down Expand Up @@ -221,19 +220,22 @@ def lassi_ref (ci1, iroot):
return e_roots1[idx], si1[:,idx]

h0, h1, h2 = LASSI (las).ham_2q ()
for iroot in range (1, 5):
with self.subTest (rootspace=iroot):
for i in range (2):
weights = np.ones (lroots[i,iroot]) / lroots[i,iroot]
psexc.set_excited_fragment_(1+i, (neleca[iroot,i], nelecb[iroot,i]),
smults[iroot,i], weights=weights)
conv, energy_tot, ci1 = psexc.kernel (h1, h2, ecore=h0,
_add_vrv_energy=True)
self.assertTrue (conv)
e_roots1, si1 = lassi_ref (ci1, iroot)
idx_match = np.argmin (np.abs (e_roots1-energy_tot))
self.assertAlmostEqual (energy_tot, e_roots1[idx_match], 6)
self.assertEqual (idx_match, 0) # local minimum problems
for opt in (0,1):
psexc = ExcitationPSFCISolver (psref, ci_ref, las.ncas_sub, nelec_ref,
stdout=mol.stdout, verbose=mol.verbose, opt=opt)
for iroot in range (1, 5):
with self.subTest (rootspace=iroot):
for i in range (2):
weights = np.ones (lroots[i,iroot]) / lroots[i,iroot]
psexc.set_excited_fragment_(1+i, (neleca[iroot,i], nelecb[iroot,i]),
smults[iroot,i], weights=weights)
conv, energy_tot, ci1 = psexc.kernel (h1, h2, ecore=h0,
_add_vrv_energy=True)
self.assertTrue (conv)
e_roots1, si1 = lassi_ref (ci1, iroot)
idx_match = np.argmin (np.abs (e_roots1-energy_tot))
self.assertAlmostEqual (energy_tot, e_roots1[idx_match], 6)
self.assertEqual (idx_match, 0) # local minimum problems

if __name__ == "__main__":
print("Full Tests for LASSI excitation constructor")
Expand Down

0 comments on commit 062a580

Please sign in to comment.