-
Notifications
You must be signed in to change notification settings - Fork 1
fix(orbit): use spatial orbital optimization to preserve spin symmetry #223
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -48,60 +48,71 @@ def main( | |||||||||||||||||||||
| n_orbit = typing.cast(typing.Any, model).n_qubits // 2 | ||||||||||||||||||||||
| calculator = NaturalOrbitCalculator(n_orbit) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # 2. Calculate 1-RDM and Unitary transformation | ||||||||||||||||||||||
| rdm = calculator.calculate_rdm(configs, psi) | ||||||||||||||||||||||
| logging.info("1-RDM calculated. Diagonalizing...") | ||||||||||||||||||||||
| # 2. Calculate spatial 1-RDM and Unitary transformation | ||||||||||||||||||||||
| rdm_spatial = calculator.calculate_rdm(configs, psi) | ||||||||||||||||||||||
| logging.info("Spatial 1-RDM calculated. Diagonalizing...") | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Natural orbitals diagonalize the RDM | ||||||||||||||||||||||
| eigvals, U = torch.linalg.eigh(rdm) | ||||||||||||||||||||||
| # U_spatial is now a (n_orbit, n_orbit) matrix for spatial orbitals only | ||||||||||||||||||||||
| eigvals, U_spatial = torch.linalg.eigh(rdm_spatial) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # 3. Load original integrals | ||||||||||||||||||||||
| # 3. Load original integrals (these are spatial orbital integrals from FCIDUMP) | ||||||||||||||||||||||
| (norb, nelec, nspin), e0, h1, h2 = _read_fcidump_tensors(self.src_fcidump) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
||||||||||||||||||||||
| # Validate that the FCIDUMP corresponds to a closed-shell, spin-restricted reference. | |
| # For a restricted calculation we require MS2 == 0 and an even number of electrons. | |
| if nspin != 0 or (nelec % 2) != 0: | |
| raise ValueError( | |
| "Orbit optimization currently assumes a spin-restricted (closed-shell) reference, " | |
| f"but FCIDUMP header reports nelec={nelec}, MS2={nspin}. " | |
| "Support for open-shell / unrestricted inputs is not yet implemented." | |
| ) |
Copilot
AI
Mar 27, 2026
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 updated calculate_rdm doc/comments say the spatial RDM is formed by “summing” / D_aa + D_bb, but the implementation actually averages the blocks: (rdm_aa + rdm_bb) / 2. Please make the docstring and inline comments consistent with the chosen convention (sum vs average), and clarify what the resulting eigenvalues represent (per-spin occupations vs spatial occupations).
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.
Orbital optimization here is now implemented as spin-restricted (shared
U_spatialfor α/β and spatial-RDM-based rotation), but the FCIDUMPnspin(MS2) / electron parity isn’t checked before applying it. To avoid silently producing incorrect results on open-shell/non-restricted cases, add an explicit validation (or a fallback to the previous spin-orbital/unrestricted transformation) when MS2 != 0 / when α and β occupations differ.