Skip to content

Commit

Permalink
create test_22_soc.py
Browse files Browse the repository at this point in the history
This implicitly evaluates the sign/transposition choices of some
additional lassi o1 functions. Still missing 1c1d and 2c for 3 and
4 fragments, for which memory consumption of soc is too high in the
existing tests.
  • Loading branch information
MatthewRHermes committed Sep 11, 2024
1 parent 6fc75b3 commit 8c11f40
Showing 1 changed file with 170 additions and 0 deletions.
170 changes: 170 additions & 0 deletions tests/lassi/test_22_soc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#!/usr/bin/env python
# Copyright 2014-2020 The PySCF Developers. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import copy
import unittest
import numpy as np
from scipy import linalg
from pyscf import lib, gto, scf, mcscf, fci, ao2mo
from mrh.my_pyscf.mcscf.lasscf_o0 import LASSCF
from mrh.my_pyscf.lassi import LASSI, LASSIrq, LASSIrqCT
from mrh.my_pyscf.lassi.lassi import root_make_rdm12s, make_stdm12s
from mrh.my_pyscf.lassi.spaces import all_single_excitations
from mrh.my_pyscf.mcscf.lasci import get_space_info
from mrh.my_pyscf.lassi import op_o0, op_o1, 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, lsi, las, mc, op, old_compute_hso
xyz='''H 0 0 0
H 1 0 0
H 3 0 0
H 4 0 0'''
mol = gto.M (atom=xyz, basis='sto3g', symmetry=False, verbose=0, output='/dev/null')
mf = scf.RHF (mol).run ()

# Random Hamiltonian
rng = np.random.default_rng ()
mf._eri = rng.random (mf._eri.shape)
hcore = rng.random ((4,4))
hcore = hcore + hcore.T
mf.get_hcore = lambda *args: hcore
hso = rng.random ((3,4,4))
hso = hso + hso.transpose (0,2,1)
from mrh.my_pyscf.mcscf import soc_int
old_compute_hso = soc_int.compute_hso
soc_int.compute_hso = lambda *args, **kwargs: hso

# LASSCF with CASCI-limit model space
las = LASSCF (mf, (2,2), (2,2), spin_sub=(1,1))
las.lasci ()
# TODO: automate this state selection
las1 = las.state_average (
weights = [1,] + [0 for i in range (15)],
spins = [[0,0], [-2,0], [0,0], [2,0],
[0,-2],[-2,-2],[0,-2],[2,-2],
[0,0], [-2,0], [0,0], [2,0],
[0,2], [-2,2], [0,2], [2,2]],
smults = [[1,1],[3,1],[3,1],[3,1],
[1,3],[3,3],[3,3],[3,3],
[1,3],[3,3],[3,3],[3,3],
[1,3],[3,3],[3,3],[3,3]])
for i in range (2): las1 = all_single_excitations (las1)
las1.conv_tol_grad = las.conv_tol_self = 9e99
las1.lasci (lroots=las1.get_ugg ().ncsf_sub)
#las1.dump_spaces ()
lsi = LASSI (las1, soc=1, break_symmetry=True, opt=0)
lsi.kernel ()

# CASCI limit (I have to spoof this sadly)
mc = mcscf.CASCI (mf, 4, 4).run ()
mc.ncas = 8
mc.nelecas = (4,0)
h0, h1, h2_ = lsi.ham_2q (soc=1)
h2 = np.zeros ((8,8,8,8), dtype=h1.dtype)
h2[:4,:4,:4,:4] = h2[4:,4:,:4,:4] = h2[:4,:4,4:,4:] = h2[4:,4:,4:,4:] = h2_[:]
mc.fcisolver = fci.fci_dhf_slow.FCI()
mc.e_tot, mc.ci = mc.fcisolver.kernel (h1, h2, 8, nelec=4, ecore=h0)
dm1s, dm2s_ = mc.fcisolver.make_rdm12 (mc.ci, 8, 4)
dm2s = np.zeros ((2,4,4,2,4,4), dtype=dm2s_.dtype)
dm2s[0,:,:,0,:,:] = dm2s_[:4,:4,:4,:4]
dm2s[1,:,:,0,:,:] = dm2s_[4:,4:,:4,:4]
dm2s[0,:,:,1,:,:] = dm2s_[:4,:4,4:,4:]
dm2s[1,:,:,1,:,:] = dm2s_[4:,4:,4:,4:]
mc.fcisolver.dm1s = dm1s
mc.fcisolver.dm2s = dm2s
e_check = h0 + np.tensordot (dm1s, h1, axes=2) + .5*np.tensordot (dm2s_, h2, axes=4)
assert (abs (e_check.imag) < 1e-8)
assert (abs (e_check.real - mc.e_tot) < 1e-8)

op = (op_o0, op_o1)

def tearDownModule():
global mol, mf, lsi, las, mc, op, old_compute_hso
from mrh.my_pyscf.mcscf import soc_int
soc_int.compute_hso = old_compute_hso
mol.stdout.close ()
del mol, mf, lsi, las, mc, op, old_compute_hso

class KnownValues(unittest.TestCase):

def test_op_o1 (self):
lsi1 = LASSI (lsi._las, opt=1, soc=1, break_symmetry=True).run ()
with self.subTest ("total energy"):
self.assertAlmostEqual (lib.fp (lsi1.e_roots), lib.fp (lsi.e_roots), 8)
ovlp = lsi1.si.conj ().T @ lsi.si
u, svals, vh = linalg.svd (ovlp)
with self.subTest ("sivec space"):
self.assertAlmostEqual (lib.fp (svals), lib.fp (np.ones (len (svals))), 8)
ham_o0 = (lsi.si * lsi.e_roots[None,:]) @ lsi.si.conj ().T
ham_o1 = (lsi1.si * lsi1.e_roots[None,:]) @ lsi1.si.conj ().T
with self.subTest ("Hamiltonian including phase"):
self.assertAlmostEqual (lib.fp (ham_o0), lib.fp (ham_o1), 8)

def test_casci_limit (self):
# CASCI limit
casdm1s, casdm2s = mc.fcisolver.dm1s, mc.fcisolver.dm2s

# LASSI in the CASCI limit
las, e_roots, si = lsi._las, lsi.e_roots, lsi.si
with self.subTest ("total energy"):
self.assertAlmostEqual (e_roots[0], mc.e_tot, 8)
for opt in range (2):
with self.subTest (opt=opt):
lasdm1s, lasdm2s = root_make_rdm12s (las, las.ci, si, state=0, opt=opt)
with self.subTest ("casdm1s"):
self.assertAlmostEqual (lib.fp (lasdm1s), lib.fp (casdm1s), 4)
with self.subTest ("casdm2s"):
self.assertAlmostEqual (lib.fp (lasdm2s), lib.fp (casdm2s), 4)

#def test_lassirq (self):
# lsi1 = LASSIrq (las, 2, 3).run ()
# self.assertAlmostEqual (lsi1.e_roots[0], mc.e_tot, 8)

#def test_lassirqct (self):
# lsi1 = LASSIrqCT (las, 2, 3).run ()
# self.assertAlmostEqual (lsi1.e_roots[0], -4.2879945248402445, 8)

#def test_contract_hlas_ci (self):
# e_roots, si, las = lsi.e_roots, lsi.si, lsi._las
# h0, h1, h2 = lsi.ham_2q ()
# case_contract_hlas_ci (self, las, h0, h1, h2, las.ci, lsi.get_nelec_frs ())

#def test_lassis (self):
# for opt in (0,1):
# with self.subTest (opt=opt):
# lsis = lassis.LASSIS (las).run (opt=opt)
# e_upper = las.e_states[0]
# e_lower = lsi.e_roots[0]
# self.assertLessEqual (e_lower, lsis.e_roots[0])
# self.assertLessEqual (lsis.e_roots[0], e_upper)
# self.assertEqual (len (lsis.e_roots), 20)
# # Reference depends on rng seed obviously b/c this is not casci limit
# self.assertAlmostEqual (lsis.e_roots[0], -4.134472877702426, 8)

#def test_fdm1 (self):
# make_fdm1 = get_fdm1_maker (lsi, lsi.ci, lsi.get_nelec_frs (), lsi.si)
# for iroot in range (lsi.nroots):
# for ifrag in range (lsi.nfrags):
# with self.subTest (iroot=iroot, ifrag=ifrag):
# fdm1 = make_fdm1 (iroot, ifrag)
# sdm1 = make_sdm1 (lsi, iroot, ifrag)
# self.assertAlmostEqual (lib.fp (fdm1), lib.fp (sdm1), 7)

if __name__ == "__main__":
print("Full Tests for LASSI of random 2,2 system")
unittest.main()

0 comments on commit 8c11f40

Please sign in to comment.