Skip to content

Commit

Permalink
Fix a dimension bug in direct_spin1_cyl_sym. Update example for issue p…
Browse files Browse the repository at this point in the history
  • Loading branch information
sunqm committed Jul 8, 2024
1 parent 2b369a5 commit beb7b1b
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 24 deletions.
57 changes: 34 additions & 23 deletions examples/mcscf/18-o2_spatial_spin_symmetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,53 @@

from pyscf import gto, scf, mcscf, fci

#
# Starting from a triplet SCF calculation
#
mol = gto.M(atom='O; O 1 1.2', basis='ccpvdz', spin=2, symmetry=1)
mf = scf.RHF(mol).run()
norb = 4
nelec = 6
nelec = 6 # leads to 4 alpha electrons and 2 beta electons due to spin=2 (Sz=1)
mc = mcscf.CASSCF(mf, norb, nelec)
try:
mc.kernel()
except IndexError as e:
except RuntimeError as e:
print('When symmetry is enabled, FCI solver optimize the wfn of A1g symmetry by default.')
print('In this CAS space, wfn of A1g symmetry does not exist. This leads to error')
print('In this CAS space, wfn of A1g (Sigma^+_g) symmetry for Sz=1 does not exist.')
print(e)

# Ground state is A2g
# Target the ground state is A2g (Sigma^-_g) with Sz=0.
# Specify 3 alpha electrons and 3 beta electrons for CASSCF calculation.
# The Sz value for CASCI/CASSCF does not have to be the same to the mol.spin.
nelec = (3, 3)
mc = mcscf.CASSCF(mf, norb, nelec)
mc.fcisolver.wfnsym = 'A2g'
mc.kernel()

#
# Starting from a singlet SCF calculation
# Print out the largest CI coefficients
#
# SCF calculation for singlet state does not converge if mol.symmetry is
# enabled. Starting from a symmetry-broken SCF initial guess, the CASSCF
# solver can converge to the solution with correct symmetry, with more
# iterations.
mol = gto.M(atom='O; O 1 1.2', basis='ccpvdz', spin=0)
mf = scf.RHF(mol).run()
nalpha = 4
nbeta = 2
mc = mcscf.CASSCF(mf, norb, (nalpha,nbeta))
mc.kernel()
for c, deta, detb in fci.addons.large_ci(mc.ci, norb, nelec, tol=.01, return_strs=False):
print(deta.tolist(), detb.tolist(), c)

#
# Print out the largest CI coefficients
# The default FCI solver utilize the D2h symmetry to mimic the cylindrical symmetry.
# It may incorrectly remove the initial guess of A2g symmetry with Sz=1 or Sz=-1 .
# direct_spin1_cyl_sym can be used to solve this problem. This module is
# designed for the cylindrical symmetry. By specifying the different Sz and
# wfnsym, the CASSCF can produce three degenerated results.
#
for c, deta, detb in fci.addons.large_ci(mc.ci, norb, (nalpha, nbeta),
tol=.01, return_strs=False):
print(deta.tolist(), detb.tolist(), c)
from pyscf.fci import direct_spin1_cyl_sym
nelec = (4, 2) # Sz=1
mc = mcscf.CASSCF(mf, norb, nelec)
mc.fcisolver = direct_spin1_cyl_sym.FCI(mol)
mc.fcisolver.wfnsym = 'A2g'
mc.kernel()

nelec = (3, 3) # Sz=0
mc = mcscf.CASSCF(mf, norb, nelec)
mc.fcisolver = direct_spin1_cyl_sym.FCI(mol)
mc.fcisolver.wfnsym = 'A2g'
mc.kernel()

nelec = (2, 4) # Sz=-1
mc = mcscf.CASSCF(mf, norb, nelec)
mc.fcisolver = direct_spin1_cyl_sym.FCI(mol)
mc.fcisolver.wfnsym = 'A2g'
mc.kernel()
7 changes: 7 additions & 0 deletions pyscf/fci/direct_spin1_symm.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,13 @@ def get_init_guess_cyl_sym(norb, nelec, nroots, hdiag, orbsym, wfnsym=0):
addra1, sign_a = _sv_associated_det(strsa[addra], degen_mapping)
addrb1, sign_b = _sv_associated_det(strsb[addrb], degen_mapping)
if wfnsym in (1, 4) and addra == addra1 and addrb == addrb1:
# Remove the A1 repr from initial guess.
# The product of two E reprs can produce A1, A2 and another E repr.
# addra == addra1 and addrb == addrb1 can be found in the A1 repr.
# However, this may also incorrectly remove the A2 repr, see the
# explanation in issue #2291.
# In this case, the direct_spin1_cyl_sym solver can be used to
# solve A2. See example mcscf/18-o2_spatial_spin_symmetry.py
continue
x = ca[:,None] * cb

Expand Down
16 changes: 16 additions & 0 deletions pyscf/fci/test/test_spin1_cyl_sym.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,22 @@ def test_incomplete_orbsym(self):
with self.assertRaises(lib.exceptions.PointGroupSymmetryError):
sol.kernel(h1, h2, no, ne, orbsym=orbsym)

# issue 2291
def test_triplet_degeneracy(self):
mol = gto.M(atom='O; O 1 1.2', basis='631g', spin=2, symmetry=1)
mf = mol.RHF().run()

def casci(nelec):
norb = 4
mc = mcscf.CASCI(mf, norb, nelec)
mc.fcisolver = direct_spin1_cyl_sym.FCI(mol)
mc.fcisolver.wfnsym = 'A2g'
mc.kernel()
return mc.e_tot
self.assertAlmostEqual(casci((4, 2)), -149.56827649707, 9)
self.assertAlmostEqual(casci((3, 3)), -149.56827649707, 9)
self.assertAlmostEqual(casci((2, 4)), -149.56827649707, 9)

if __name__ == "__main__":
print("Full Tests for spin1-symm")
unittest.main()
2 changes: 1 addition & 1 deletion pyscf/lib/mcscf/fci_contract.c
Original file line number Diff line number Diff line change
Expand Up @@ -1003,7 +1003,7 @@ void FCIcontract_2e_cyl_sym(double *eris, double *ci0, double *ci1,
strb_ir = IRREP_OF(strb_l, strb_g);
mb = nbs[strb_ir];
}
if (nas[intera_ir] > 0 && nas[interb_ir] > 0 &&
if (nas[intera_ir] > 0 && nbs[interb_ir] > 0 &&
(ma > 0 || mb > 0)) {
// clinka for intera*ai -> stra.
pick_link_by_irrep(clinka, linka+linka_loc[intera_ir], nas[intera_ir], nlinka, ai_ir);
Expand Down

0 comments on commit beb7b1b

Please sign in to comment.