Skip to content

Add GPU density-fitted CASCI and diagonal-Hessian CASSCF - #869

Open
wtpeter wants to merge 4 commits into
pyscf:masterfrom
wtpeter:feat/df-casscf
Open

Add GPU density-fitted CASCI and diagonal-Hessian CASSCF#869
wtpeter wants to merge 4 commits into
pyscf:masterfrom
wtpeter:feat/df-casscf

Conversation

@wtpeter

@wtpeter wtpeter commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR adds initial GPU support for density-fitted CASCI and CASSCF.

The main additions are:

  • An in-core GPU direct_spin1 FCI solver with GPU Hamiltonian contraction, Davidson diagonalization, and RDM construction.
  • GPU density-fitting AO-to-MO integral transformation through DF.ao2mo.
  • DFCASCI support for restricted HF and KS references.
  • A diagonal-Hessian DFCASSCF orbital optimizer.
  • Timing information for AO2MO, effective one-electron integrals, FCI, RDM construction, orbital derivatives, and orbital rotations.
  • Unit tests and a CPU/GPU DF-CASSCF comparison example.

The CASSCF orbital step uses a positive diagonal-Hessian model with a common level shift. The final orbital rotation parameters are limited by max_stepsize without increasing the level shift solely to enforce the step limit.

Current limitations

  • Only density-fitted CASCI/CASSCF is supported.
  • Only restricted HF/KS references are supported.
  • The GPU FCI solver is in-core only and raises MemoryError when GPU memory is insufficient.
  • CASSCF uses an approximate diagonal Hessian rather than the full augmented-Hessian optimizer.
  • Canonicalization, natural orbitals, frozen orbitals, symmetry-adapted FCI, and state-averaged CASSCF are not implemented.

This implementation is intended as a lightweight GPU CASSCF fallback rather than a replacement for the more robust second-order CPU optimizer.

required_memory = ((2 * max_space + work_vectors) * vector_bytes +
max_space**2 * x0.dtype.itemsize)
available_memory = get_avail_mem()
memory_limit = min(max_memory * 1e6, available_memory)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

max_memory in pyscf controls CPU memory. Since GPU memory is assumed to be dedicated to a single process, we can ignore max_memory when estimating GPU memory usage.

f'Failed to allocate GPU Davidson subspace of size {max_space}') \
from err

converged = cp.zeros(nroots, dtype=bool)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

converged can be put on host memory, as a numpy array

Comment thread gpu4pyscf/mcscf/casci.py
out += (corevhf,)
timing = getattr(casci, 'timing', None)
if isinstance(timing, dict):
timing['h1e_wall'] = (timing.get('h1e_wall', 0.) +

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wall time is inaccurate in the GPU code.
If you just need to print cost of individual step, it's recommended to use gpu4pyscf.lib.logger.timer functions. If you want to collect the timing data, you need to use the cupy Event object, see also gpu4pyscf.scf.jk._TimingCollector

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.

2 participants