Skip to content

[Work in progress] LNOCC #115

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open

[Work in progress] LNOCC #115

wants to merge 8 commits into from

Conversation

hongzhouye
Copy link

@hongzhouye hongzhouye commented Feb 25, 2025

This PR adds the molecular and periodic LNO-CCSD/CCSD(T). The LNO method was originally introduced by Kállay and co-workers:

  • J. Chem. Phys. 139, 094105 (2013) (link)
  • J. Chem. Phys. 135, 104111 (2011) (link)

And this PR is particularly based on a recent extension:

  • J. Chem. Theory Comput. 2024, 20, 20, 8948–8959 (link)

for spin-restricted molecular & periodic LNO-CC and an unpublished work for spin-unrestricted references (@fishjojo, @MoleOrbitalHybridAnalyst).

The PR is still work in progress with the following to-do's:

  • add examples and more unit tests (me and @tberkel)
  • make the C library pyscf-forge/pyscf/lib/lno compatible with regular pyscf (@fishjojo)
  • remove redundant functions in lno/lnoccsd.py for precomputation (perhaps need to slightly refactor pyscf's CCSD code) (@fishjojo )
  • add support for spin-unrestricted references (@fishjojo, @MoleOrbitalHybridAnalyst)

@tberkel
Copy link

tberkel commented Apr 25, 2025

I'm working on adding examples, but frozen seems broken with unrestricted LNO. @fishjojo or @MoleOrbitalHybridAnalyst have you tested frozen orbitals? Skimming the code suggests that you did, but I get a correlation energy of 0 when I freeze orbitals. Example is below. Works fine when frozen = 0.

from pyscf import gto, scf, mp, lo
from pyscf.data import elements
from pyscf import lno

mol = gto.Mole()
mol.atom = '''
    O   -1.485163346097   -0.114724564047    0.000000000000
    H   -1.868415346097    0.762298435953    0.000000000000
    H   -0.533833346097    0.040507435953    0.000000000000
    O    1.416468653903    0.111264435953    0.000000000000
    H    1.746241653903   -0.373945564047   -0.758561000000
    H    1.746241653903   -0.373945564047    0.758561000000
'''
mol.basis = 'ccpvdz'
mol.verbose = 7
mol.spin = 0
mol.build()

mf = scf.UHF(mol).density_fit()
mf.kernel()

frozen = elements.chemcore(mol)
# frozen = 0

mymp = mp.MP2(mf, frozen=frozen)
mymp.kernel(with_t2=False)

thresh = [1e-4] * 2

nocca, noccb = mymp.get_nocc()
moidxa, moidxb = mymp.get_frozen_mask()
mo_coeff = mf.mo_coeff[0][:, moidxa], mf.mo_coeff[1][:, moidxb]
orbocca = mo_coeff[0][:, :nocca]
lo_coeff_a = lo.PipekMezey(mf.mol, orbocca).kernel()
orboccb = mo_coeff[1][:, :noccb]
lo_coeff_b = lo.PipekMezey(mf.mol, orboccb).kernel()
lo_coeff = [lo_coeff_a, lo_coeff_b]

frag_lolist_a = [[[i], []] for i in range(nocca)]
frag_lolist_b = [[[], [i]] for i in range(noccb)]
frag_lolist = frag_lolist_a + frag_lolist_b

mlcc = lno.ULNOCCSD(mf, lo_coeff, frag_lolist, frozen=frozen,
                    lno_thresh=thresh)
mlcc.kernel()
# E(LNOMP2) = -152.062490646908  E_corr = 0
# E(LNOCCSD) = -152.062490646908  E_corr = 0

@tberkel
Copy link

tberkel commented May 6, 2025

I fixed the ULNO frozen orbitals problem (help from @hczhai) and cleaned up the unittest for ULNO.

@tberkel
Copy link

tberkel commented May 6, 2025

Another question for @fishjojo and/or @MoleOrbitalHybridAnalyst - I notice that the results for ULNO and (R)LNO are different for the same thresholds, even when the reference doesn't break spin symmetry. Did you observe the same? I guess the issue is that the orbital-specific DMs treat up and down differently (e.g., commonly a different number of up and down orbitals are included in the active space). I wonder if there's a way to spin average, so that the results agree in the limit of no spin symmetry breaking.

@fishjojo
Copy link
Collaborator

fishjojo commented May 6, 2025 via email

@hongzhouye
Copy link
Author

@fishjojo @tberkel Could it be related to this line? I had updated the local MP2 DM definition at some point to better align with the canonical MP2 DM definition, which is twice the value of what the earlier version produced. I’m okay with defaulting to either convention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants