Skip to content

Commit 2bfa79e

Browse files
committed
Handle smearing-ROHF
1 parent 548009d commit 2bfa79e

2 files changed

Lines changed: 64 additions & 6 deletions

File tree

pyscf/scf/smearing.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,28 @@ def smearing(mf, sigma=None, method=SMEARING_METHOD, mu0=None, fix_spin=False):
3131
mf.fix_spin = fix_spin
3232
return mf
3333

34-
assert not mf.istype('KSCF')
35-
if mf.istype('ROHF'):
36-
# ROHF leads to two Fock matrices. It's not clear how to define the
37-
# Roothaan effective Fock matrix from the two.
38-
raise NotImplementedError('Smearing-ROHF')
34+
if mf.istype('_CIAH_SOSCF'):
35+
raise NotImplementedError('Smearing with second order SCF is not supported')
36+
37+
if mf.istype('KSCF'):
38+
from pyscf.pbc.scf.smearing import smearing
39+
return smearing(mf, sigma, method, mu0, fix_spin)
3940

41+
if mf.istype('ROHF'):
42+
if fix_spin:
43+
raise RuntimeError('Smearing-ROHF with fix_spin not supported. Use UHF instead.')
44+
# Roothaan Fock matrix for ROHF is not supported by the smearing method.
45+
# The single occupancy can be handled using the regular RHF class
46+
from pyscf.scf.addons import _object_without_soscf
47+
from pyscf import scf
48+
from pyscf import dft
49+
known_class = {
50+
dft.rks_symm.ROKS: dft.rks_symm.RKS,
51+
dft.roks.ROKS : dft.rks.RKS ,
52+
scf.hf_symm.ROHF : scf.hf_symm.RHF ,
53+
scf.rohf.ROHF : scf.hf.RHF ,
54+
}
55+
mf = _object_without_soscf(mf, known_class)
4056
return lib.set_class(_SmearingSCF(mf, sigma, method, mu0, fix_spin),
4157
(_SmearingSCF, mf.__class__))
4258

@@ -136,8 +152,12 @@ def get_occ(self, mo_energy=None, mo_coeff=None):
136152
mo_occ = super().get_occ(mo_energy, mo_coeff)
137153
return mo_occ
138154

155+
if self.istype('ROHF'):
156+
# ROHF leads to two Fock matrices. It's not clear how to define the
157+
# Roothaan effective Fock matrix from the two.
158+
raise NotImplementedError('Smearing-ROHF')
139159
is_uhf = self.istype('UHF')
140-
is_rhf = self.istype('RHF')
160+
is_rhf = not is_uhf
141161

142162
sigma = self.sigma
143163
if self.smearing_method.lower() == 'fermi':

pyscf/scf/test/test_addons.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,44 @@ def test_remove_lindep(self):
413413
lindep=1e-9).run()
414414
self.assertAlmostEqual(mf.e_tot, -1.6291001503057689, 7)
415415

416+
@unittest.skip('Smearing ROHF with fix_spin does not work')
417+
def test_rohf_smearing(self):
418+
# Fe2 from https://doi.org/10.1021/acs.jpca.1c05769
419+
mol = gto.M(
420+
atom='''
421+
Fe 0. 0. 0.
422+
Fe 2.01 0. 0.
423+
''', basis="lanl2dz", ecp="lanl2dz", symmetry=False, unit='Angstrom',
424+
spin=6, charge=0, verbose=0)
425+
myhf_s = scf.ROHF(mol)
426+
myhf_s = addons.smearing(myhf_s, sigma=0.01, method='gaussian', fix_spin=True)
427+
myhf_s.kernel()
428+
# macos py3.7 CI -242.4828982467762
429+
# linux py3.11 CI -242.48289824670388
430+
self.assertAlmostEqual(myhf_s.e_tot, -242.482898246, 6)
431+
self.assertAlmostEqual(myhf_s.entropy, 0.45197, 4)
432+
myhf2 = myhf_s.undo_smearing().newton()
433+
myhf2.kernel(myhf_s.make_rdm1())
434+
# FIXME: note 16mHa lower energy than myhf
435+
self.assertAlmostEqual(myhf2.e_tot, -244.9808750, 6)
436+
437+
myhf_s.smearing_method = 'fermi'
438+
myhf_s.kernel()
439+
self.assertAlmostEqual(myhf_s.e_tot, -244.200255453, 6)
440+
self.assertAlmostEqual(myhf_s.entropy, 3.585155, 4)
441+
442+
def test_rohf_smearing1(self):
443+
mol = gto.M(atom = '''
444+
7 0. 0 -0.7
445+
7 0. 0 0.7''',
446+
charge = -1,
447+
spin = 1)
448+
mf = mol.RHF()
449+
mf = addons.smearing(mf, sigma=0.1)
450+
mf.kernel()
451+
self.assertAlmostEqual(mf.mo_occ.sum(), 15, 8)
452+
self.assertAlmostEqual(mf.e_tot, -106.9310800402, 8)
453+
416454
def test_uhf_smearing(self):
417455
mol = gto.M(
418456
atom='''

0 commit comments

Comments
 (0)