-
Notifications
You must be signed in to change notification settings - Fork 47
[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
base: master
Are you sure you want to change the base?
Conversation
|
I'm working on adding examples, but |
|
I fixed the ULNO frozen orbitals problem (help from @hczhai) and cleaned up the unittest for ULNO. |
|
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. |
|
@tberkel, thanks for the fix for frozen orbitals. The ULNO results match
those of RLNO from the old implementation. I notice there are some changes
to the RLNO code for determining the LNOs, and I’m not sure the default is
still the original ‘ie’ flavor for building the LNOs. Currently, ULNO only
works for ‘ie’, as there is difficulty matching the RLNO results using
other flavors. Maybe Hongzhou could provide some insights of this.
Timothy Berkelbach ***@***.***>于2025年5月6日 周二上午6:18写道:
… *tberkel* left a comment (pyscf/pyscf-forge#115)
<#115 (comment)>
Another question for @fishjojo <https://github.com/fishjojo> and/or
@MoleOrbitalHybridAnalyst <https://github.com/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.
—
Reply to this email directly, view it on GitHub
<#115 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ACCZ6FRLAEPZ6D7G2VSY74L25CZD7AVCNFSM6AAAAABX3R2U7SVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDQNJUGU2TKMBSGU>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
- update k2s_scf to include hcore from kpts calculation
…maginary parts in `k2s_iao`.
…n results with lno.py
Update to unrestricted lno code
Improve k2s utilities
…sh for large molecules, I've corrected the contractions to fix this.
Bug Fix: Density Matrix Calculation for ulno
|
I think this is ready to merge and meets the bar for forge. We have some more small updates, but they'll be easier to add in future PRs once this is merged. |
| orbocc = mf.mo_coeff[:,frozen:np.count_nonzero(mf.mo_occ)] | ||
| mlo = lo.PipekMezey(mol, orbocc) | ||
| lo_coeff = mlo.kernel() | ||
| while True: # always performing jacobi sweep to avoid trapping in local minimum/saddle point |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you implement this as a for loop with a maxiter? It should behave for now but this is scary to me.
| lo_coeff1 = mlo.stability_jacobi()[1] | ||
| if lo_coeff1 is lo_coeff: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The discarded first return argument literally should evaluate to the same value as the conditional. It's more readable and "sane" if you just use that, since who knows how stability_jacobi may be refactored in the future?
| while True: # always performing jacobi sweep to avoid trapping in local minimum/saddle point | ||
| lo_coeff1_s = mlo.stability_jacobi()[1] | ||
| if lo_coeff1_s is lo_coeff_s: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comments as in test_lnoccsd.py
| ex = ex.real | ||
| ess = ed*0.5 + ex | ||
| eos = ed*0.5 | ||
| return lib.tag_array(ess+eos, spin_comp=np.array((ess, eos))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aren't we trying to move away from lib.tag_array?
| # def mo_splitter(self, kind='mask'): | ||
| # r''' Return index arrays that split MOs into | ||
| # - frozen occupieds | ||
| # - active occupieds | ||
| # - active virtuals | ||
| # - frozen virtuals | ||
| # | ||
| # Args: | ||
| # kind (str): | ||
| # 'mask' : return masks each of length nmo | ||
| # 'index' : return index arrays | ||
| # 'idx' : same as 'index' | ||
| # ''' | ||
| # maskact = self.get_frozen_mask() | ||
| # maskocc = self.mo_occ > 1e-10 | ||
| # return mo_splitter(maskact, maskocc, kind=kind) | ||
| # | ||
| # def split_mo_coeff(self): | ||
| # r''' Return the four components of MOs specified in :func:`mo_splitter` | ||
| # ''' | ||
| # mo = self.mo_coeff | ||
| # masks = self.mo_splitter() | ||
| # return [mo[:,m] for m in masks] | ||
| # | ||
| # def split_mo_energy(self): | ||
| # moe = self.mo_energy | ||
| # masks = self.mo_splitter() | ||
| # return [moe[m] for m in masks] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cleanup on aisle 3
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's probably a good idea to have unittest coverage for a file like this, in which many functions which are different variations on a single theme are implemented. That way, the next time numpy or scipy changes something and breaks all of these functions simultaneously, you immediately get a checklist of all the places you need to update whatever it is.
| del cls.cell, cls.kmf, cls.frozen | ||
| del cls.scell, cls.smf | ||
|
|
||
| # def test_lno_pm_by_thresh(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use @unittest.skip ('reason') if you intend to enable this test in the future; or delete it if not.
| # def contract1(LbraR, LbraI, LketR, LketI): | ||
| # out_shape = (LbraR.shape[1], LketR.shape[1]) | ||
| # out = np.zeros(out_shape, dtype=REAL) | ||
| # for q1,q2 in enumerate(k2sdf.qconserv): | ||
| # i0,i1 = k2sdf.get_auxslice(q1) | ||
| # j0,j1 = k2sdf.get_auxslice(q2) | ||
| # zdotNNtoR(LbraR[i0:i1].T, LbraI[i0:i1].T, LketR[j0:j1], LketI[j0:j1], 1, out, 1) | ||
| # return out | ||
| # | ||
| # eris.oooo[:] = contract1(LooR, LooI, LooR, LooI).reshape(nocc,nocc,nocc,nocc) | ||
| # eris.ovoo[:] = contract1(LovR, LovI, LooR, LooI).reshape(nocc,nvir,nocc,nocc) | ||
| # eris.oovv[:] = lib.unpack_tril( | ||
| # contract1(LooR, LooI, LvvR, LvvI)).reshape(nocc,nocc,nvir,nvir) | ||
| # eris.ovvo[:] = contract1(LovR, LovI, LvoR, LvoI).reshape(nocc,nvir,nvir,nocc) | ||
| # eris.ovov[:] = contract1(LovR, LovI, LovR, LovI).reshape(nocc,nvir,nocc,nvir) | ||
| # eris.ovvv[:] = contract1(LovR, LovI, LvvR, LvvI).reshape(nocc,nvir,nvir_pair) | ||
| # eris.vvvv[:] = contract1(LvvR, LvvI, LvvR, LvvI).reshape(nvir_pair,nvir_pair) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cleanup?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same comment as for the OBC version
MatthewRHermes
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we get a quick and dirty example input script or two?
|
|
||
| @property | ||
| def e_corr_pt2_scs(self): | ||
| e_corr = 0.333*self.e_corr_pt2_ss + 1.2*self.e_corr_pt2_os |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe the ss, os factor can be configurable arguments, like the DF SCS-MP2 does
This PR adds the molecular and periodic LNO-CCSD/CCSD(T). The LNO method was originally introduced by Kállay and co-workers:
And this PR is particularly based on a recent extension:
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:
pyscf-forge/pyscf/lib/lnocompatible with regular pyscf (@fishjojo)lno/lnoccsd.pyfor precomputation (perhaps need to slightly refactor pyscf's CCSD code) (@fishjojo )