gpu4pyscf 1.3.1__tar.gz → 1.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/CHANGELOG +10 -0
- {gpu4pyscf-1.3.1/gpu4pyscf.egg-info → gpu4pyscf-1.3.2}/PKG-INFO +1 -1
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/__init__.py +1 -1
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/df.py +53 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/hessian/rhf.py +11 -10
- gpu4pyscf-1.3.2/gpu4pyscf/df/int3c2e_bdiv.py +485 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/gen_grid.py +7 -4
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/libxc.py +3 -2
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/numint.py +22 -18
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/rks.py +24 -1
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/uks.py +1 -1
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/drivers/dft_3c_driver.py +5 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/drivers/dft_driver.py +114 -119
- gpu4pyscf-1.3.2/gpu4pyscf/drivers/opt_driver.py +189 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/grad/rhf.py +18 -4
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/gto/mole.py +60 -18
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/hessian/rhf.py +26 -4
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/cupy_helper.py +13 -11
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/cutensor.py +16 -10
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/logger.py +6 -3
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/fft.py +10 -9
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/ft_ao.py +7 -5
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/int3c2e.py +3 -2
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/rsdf_builder.py +1 -1
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/dft/krks.py +44 -7
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/dft/kuks.py +30 -9
- gpu4pyscf-1.3.2/gpu4pyscf/pbc/dft/multigrid.py +998 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/dft/rks.py +43 -3
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/dft/uks.py +28 -8
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/int4c2e.py +1 -1
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/j_engine.py +4 -11
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/jk.py +3 -21
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/tdscf/_lr_eig.py +14 -12
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2/gpu4pyscf.egg-info}/PKG-INFO +1 -1
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf.egg-info/SOURCES.txt +2 -1
- gpu4pyscf-1.3.2/gpu4pyscf.egg-info/requires.txt +5 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/setup.py +2 -2
- gpu4pyscf-1.3.1/gpu4pyscf/drivers/opt_driver.py +0 -175
- gpu4pyscf-1.3.1/gpu4pyscf/pbc/gto/cell.py +0 -49
- gpu4pyscf-1.3.1/gpu4pyscf.egg-info/requires.txt +0 -5
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/LICENSE +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/MANIFEST.in +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/README.md +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/__config__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/cc/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/cc/ccsd_incore.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/cderi.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/df_jk.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/grad/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/grad/jk.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/grad/rhf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/grad/rks.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/grad/uhf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/grad/uks.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/hessian/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/hessian/jk.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/hessian/rks.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/hessian/uhf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/hessian/uks.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/int3c2e.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/gks.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/libxc_structs.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/radi.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/roks.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/xc_alias.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/xc_deriv.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/drivers/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/drivers/basis_vDZP_NWCHEM.dat +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/drivers/ecp_vDZP_NWCHEM.dat +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/drivers/opt_3c_driver.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/fci/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/fci/direct_spin1.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/grad/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/grad/dispersion.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/grad/rks.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/grad/uhf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/grad/uks.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/gto/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/gto/int3c1e.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/gto/int3c1e_ip.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/gto/int3c1e_ipip.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/hessian/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/hessian/dispersion.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/hessian/jk.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/hessian/rks.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/hessian/uhf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/hessian/uks.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/cublas.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/cusolver.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/diis.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/memcpy.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/multi_gpu.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/utils.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/mp/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/mp/dfmp2.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/mp/mp2.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/aft.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/aft_jk.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/df.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/df_jk.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/fft_jk.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/dft/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/dft/gen_grid.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/dft/numint.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/gto/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/lib/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/lib/kpts_helper.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/scf/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/scf/hf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/scf/khf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/scf/kuhf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/scf/uhf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/tools/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/tools/k2gamma.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/tools/pbc.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pop/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pop/esp.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/properties/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/properties/ir.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/properties/polarizability.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/properties/shielding.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/qmmm/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/qmmm/chelpg.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/qmmm/pbc/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/qmmm/pbc/itrf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/qmmm/pbc/mm_mole.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/qmmm/pbc/tools.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/_response_functions.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/cphf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/diis.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/dispersion.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/ghf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/hf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/hf_symm.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/int2c2e.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/rohf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/soscf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/ucphf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/uhf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/uhf_symm.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/_attach_solvent.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/grad/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/grad/pcm.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/grad/smd.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/grad/smd_experiment.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/hessian/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/hessian/pcm.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/hessian/smd.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/hessian/smd_experiment.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/pcm.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/smd.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/smd_experiment.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/tdscf/__init__.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/tdscf/_uhf_resp_sf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/tdscf/rhf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/tdscf/rks.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/tdscf/uhf.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/tdscf/uks.py +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf.egg-info/dependency_links.txt +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf.egg-info/top_level.txt +0 -0
- {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/setup.cfg +0 -0
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
v1.3.2 (2025-03-10)
|
|
2
|
+
-------------------
|
|
3
|
+
* Improvements
|
|
4
|
+
- Dump xc info and grids into to log file
|
|
5
|
+
- Optimize 4-center integral evalulation CUDA kernels using warp divergent algorithm
|
|
6
|
+
- Support up to I orbitals in DFT
|
|
7
|
+
- Fix out-of-bound issue in DFT hessian for heavy atoms (>=19)
|
|
8
|
+
* Deprecation
|
|
9
|
+
- SM60 is not supported in PyPi package
|
|
10
|
+
|
|
1
11
|
v1.3.1 (2025-02-04)
|
|
2
12
|
-------------------
|
|
3
13
|
* New Features
|
|
@@ -23,6 +23,7 @@ from pyscf.df import df, addons, incore
|
|
|
23
23
|
from gpu4pyscf.lib.cupy_helper import (cholesky, tag_array, get_avail_mem,
|
|
24
24
|
cart2sph, p2p_transfer, copy_array)
|
|
25
25
|
from gpu4pyscf.df import int3c2e, df_jk
|
|
26
|
+
from gpu4pyscf.df import int3c2e_bdiv
|
|
26
27
|
from gpu4pyscf.lib import logger
|
|
27
28
|
from gpu4pyscf import __config__
|
|
28
29
|
from gpu4pyscf.__config__ import _streams, num_devices
|
|
@@ -30,6 +31,7 @@ from gpu4pyscf.__config__ import _streams, num_devices
|
|
|
30
31
|
MIN_BLK_SIZE = getattr(__config__, 'min_ao_blksize', 128)
|
|
31
32
|
ALIGNED = getattr(__config__, 'ao_aligned', 32)
|
|
32
33
|
GB = 1024*1024*1024
|
|
34
|
+
INT3C2E_V2 = False
|
|
33
35
|
|
|
34
36
|
LINEAR_DEP_THR = incore.LINEAR_DEP_THR
|
|
35
37
|
GROUP_SIZE = 256
|
|
@@ -82,6 +84,42 @@ class DF(lib.StreamObject):
|
|
|
82
84
|
if auxmol is None:
|
|
83
85
|
self.auxmol = auxmol = addons.make_auxmol(mol, self.auxbasis)
|
|
84
86
|
|
|
87
|
+
if INT3C2E_V2:
|
|
88
|
+
self.intopt = intopt = int3c2e_bdiv.Int3c2eOpt(mol, auxmol)
|
|
89
|
+
self._cderi = {}
|
|
90
|
+
self._cderi[0] = _cholesky_eri_bdiv(intopt, omega=omega)
|
|
91
|
+
ao_pair_mapping = intopt.create_ao_pair_mapping(cart=mol.cart)
|
|
92
|
+
rows, cols = divmod(cupy.asarray(ao_pair_mapping), mol.nao)
|
|
93
|
+
intopt.cderi_row = rows
|
|
94
|
+
intopt.cderi_col = cols
|
|
95
|
+
|
|
96
|
+
# intopt.cderi_diag stores the indices for cderi_row that
|
|
97
|
+
# corresponds to the diagonal blocks. Note this index array can
|
|
98
|
+
# contain some of the off-diagonal elements which happen to be the
|
|
99
|
+
# off-diagonal elements while within the diagonal blocks.
|
|
100
|
+
uniq_l = intopt.uniq_l_ctr[:,0]
|
|
101
|
+
if mol.cart:
|
|
102
|
+
nf = (uniq_l + 1) * (uniq_l + 2) // 2
|
|
103
|
+
else:
|
|
104
|
+
nf = uniq_l * 2 + 1
|
|
105
|
+
n_groups = len(uniq_l)
|
|
106
|
+
ij_tasks = ((i, j) for i in range(n_groups) for j in range(i+1))
|
|
107
|
+
nbas = intopt.sorted_mol.nbas
|
|
108
|
+
offset = 0
|
|
109
|
+
cderi_diag = []
|
|
110
|
+
for (i, j), bas_ij_idx in zip(ij_tasks, intopt.shl_pair_idx):
|
|
111
|
+
nfi = nf[i]
|
|
112
|
+
nfj = nf[j]
|
|
113
|
+
if i == j: # the diagonal blocks
|
|
114
|
+
ish, jsh = divmod(bas_ij_idx, nbas)
|
|
115
|
+
idx = np.where(ish == jsh)[0]
|
|
116
|
+
addr = offset + idx[:,None] * (nfi*nfi) + np.arange(nfi*nfi)
|
|
117
|
+
cderi_diag.append(addr.ravel())
|
|
118
|
+
offset += bas_ij_idx.size * nfi * nfj
|
|
119
|
+
intopt.cderi_diag = cupy.asarray(np.hstack(cderi_diag))
|
|
120
|
+
log.timer_debug1('cholesky_eri', *t0)
|
|
121
|
+
return self
|
|
122
|
+
|
|
85
123
|
if omega and omega > 1e-10:
|
|
86
124
|
with auxmol.with_range_coulomb(omega):
|
|
87
125
|
j2c_cpu = auxmol.intor('int2c2e', hermi=1)
|
|
@@ -364,3 +402,18 @@ def _cderi_task(intopt, cd_low, task_list, _cderi, aux_blksize,
|
|
|
364
402
|
_cderi[0][:,ij0:ij1] = cderi_block
|
|
365
403
|
t1 = log.timer_debug1(f'transfer data for {cp_ij_id} / {nq} on Device {device_id}', *t1)
|
|
366
404
|
return
|
|
405
|
+
|
|
406
|
+
# Generate CDERI using the new int3c2e_bdiv algorithm
|
|
407
|
+
def _cholesky_eri_bdiv(intopt, omega=None):
|
|
408
|
+
assert isinstance(intopt, int3c2e_bdiv.Int3c2eOpt)
|
|
409
|
+
assert omega is None
|
|
410
|
+
eri3c = intopt.int3c2e_bdiv_kernel()
|
|
411
|
+
if intopt.mol.cart:
|
|
412
|
+
eri3c = intopt.orbital_pair_cart2sph(eri3c)
|
|
413
|
+
auxmol = intopt.auxmol
|
|
414
|
+
j2c = cupy.asarray(auxmol.intor('int2c2e', hermi=1), order='C')
|
|
415
|
+
cd_low = cholesky(j2c)
|
|
416
|
+
aux_coeff = cupy.array(intopt.aux_coeff, copy=True)
|
|
417
|
+
cd_low = solve_triangular(cd_low, aux_coeff.T, lower=True, overwrite_b=True)
|
|
418
|
+
cderi = cd_low.dot(eri3c.T)
|
|
419
|
+
return cderi
|
|
@@ -56,7 +56,7 @@ def _hk_ip1_ip1(rhok1_Pko, dm0, mocc_2):
|
|
|
56
56
|
hk_ao_ao = cupy.zeros([nao,nao,3,3])
|
|
57
57
|
cupy.get_default_memory_pool().free_all_blocks()
|
|
58
58
|
mem_avail = get_avail_mem()
|
|
59
|
-
blksize = int((mem_avail*0.4/(nao*nao*3*8)/ALIGNED))*ALIGNED
|
|
59
|
+
blksize = int(((mem_avail-hk_ao_ao.nbytes)*0.4/(nao*nao*3*8)/ALIGNED))*ALIGNED
|
|
60
60
|
for k0, k1 in lib.prange(0,nnz,blksize):
|
|
61
61
|
#rhok1_Pko_kslice = cupy.asarray(rhok1_Pko[k0:k1])
|
|
62
62
|
rhok1_Pko_kslice = copy_array(rhok1_Pko[k0:k1])
|
|
@@ -68,8 +68,9 @@ def _hk_ip1_ip1(rhok1_Pko, dm0, mocc_2):
|
|
|
68
68
|
|
|
69
69
|
# (10|0)(0|01) without response of RI basis
|
|
70
70
|
rhok1_Pkl_kslice = contract('piox,ko->pikx', rhok1_Pko_kslice, mocc_2)
|
|
71
|
+
rhok1_Pko_kslice = None
|
|
71
72
|
hk_ao_ao += contract('pikx,pkiy->ikxy', rhok1_Pkl_kslice, rhok1_Pkl_kslice)
|
|
72
|
-
rhok1_Pkl_kslice =
|
|
73
|
+
rhok1_Pkl_kslice = None
|
|
73
74
|
return hk_ao_ao
|
|
74
75
|
|
|
75
76
|
def _partial_hess_ejk(hessobj, mo_energy=None, mo_coeff=None, mo_occ=None, atmlst=None,
|
|
@@ -177,14 +178,14 @@ def _partial_hess_ejk(hessobj, mo_energy=None, mo_coeff=None, mo_occ=None, atmls
|
|
|
177
178
|
assert blksize > 0
|
|
178
179
|
if hessobj.auxbasis_response:
|
|
179
180
|
hk_ao_aux = cupy.zeros([nao,naux,3,3])
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
181
|
+
for i0, i1 in lib.prange(0,nao,blksize):
|
|
182
|
+
#wk1_Pko_islice = cupy.asarray(wk1_Pko[:,i0:i1])
|
|
183
|
+
wk1_Pko_islice = copy_array(wk1_Pko[:,i0:i1])
|
|
184
|
+
|
|
185
|
+
#rhok1_Pko = contract('pq,qiox->piox', int2c_inv, wk1_Pko_islice)
|
|
186
|
+
rhok1_Pko = solve_j2c(wk1_Pko_islice)
|
|
187
|
+
wk1_Pko_islice = None
|
|
183
188
|
|
|
184
|
-
#rhok1_Pko = contract('pq,qiox->piox', int2c_inv, wk1_Pko_islice)
|
|
185
|
-
rhok1_Pko = solve_j2c(wk1_Pko_islice)
|
|
186
|
-
wk1_Pko_islice = None
|
|
187
|
-
if hessobj.auxbasis_response:
|
|
188
189
|
# (10|0)(1|00)
|
|
189
190
|
wk_ip2_Ipo = contract('porx,io->pirx', wk_ip2_P__, mocc_2[i0:i1])
|
|
190
191
|
hk_ao_aux[i0:i1] += contract('piox,pioy->ipxy', rhok1_Pko, wk_ip2_Ipo)
|
|
@@ -200,7 +201,7 @@ def _partial_hess_ejk(hessobj, mo_energy=None, mo_coeff=None, mo_occ=None, atmls
|
|
|
200
201
|
wk1_I = contract('yqp,piox->qioxy', int2c_ip1, rhok1_Pko)
|
|
201
202
|
hk_ao_aux[i0:i1] -= contract('qoi,qioxy->iqxy', rhok0_P_I, wk1_I)
|
|
202
203
|
wk1_I = rhok0_P_I = None
|
|
203
|
-
|
|
204
|
+
rhok1_Pko = None
|
|
204
205
|
t1 = log.timer_debug1('contract int3c2e_ip1 with int2c_ip1', *t1)
|
|
205
206
|
|
|
206
207
|
rho2c_0 = contract('pij,qji->pq', rhok0_P__, rhok0_P__)
|
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
# Copyright 2025 The PySCF Developers. All Rights Reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
'''
|
|
16
|
+
3-center 2-electron Coulomb integral helper functions
|
|
17
|
+
'''
|
|
18
|
+
|
|
19
|
+
import ctypes
|
|
20
|
+
import math
|
|
21
|
+
import numpy as np
|
|
22
|
+
import cupy as cp
|
|
23
|
+
from pyscf import lib
|
|
24
|
+
from pyscf.lib.parameters import ANGULAR
|
|
25
|
+
from pyscf.gto.mole import ANG_OF, ATOM_OF, PTR_COORD, PTR_EXP, conc_env
|
|
26
|
+
from gpu4pyscf.lib import logger
|
|
27
|
+
from gpu4pyscf.lib.cupy_helper import load_library, contract
|
|
28
|
+
from gpu4pyscf.gto.mole import group_basis, PTR_BAS_COORD
|
|
29
|
+
from gpu4pyscf.scf.jk import g_pair_idx, _nearest_power2, _scale_sp_ctr_coeff, SHM_SIZE
|
|
30
|
+
from gpu4pyscf.gto.mole import basis_seg_contraction, extract_pgto_params, cart2sph_by_l
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
'aux_e2',
|
|
34
|
+
]
|
|
35
|
+
libgint_rys = load_library('libgint_rys')
|
|
36
|
+
libgint_rys.fill_int3c2e.restype = ctypes.c_int
|
|
37
|
+
libgint_rys.fill_int3c2e_bdiv.restype = ctypes.c_int
|
|
38
|
+
libgint_rys.init_constant.restype = ctypes.c_int
|
|
39
|
+
|
|
40
|
+
LMAX = 4
|
|
41
|
+
L_AUX_MAX = 6
|
|
42
|
+
GOUT_WIDTH = 45
|
|
43
|
+
THREADS = 256
|
|
44
|
+
|
|
45
|
+
def aux_e2(mol, auxmol):
|
|
46
|
+
r'''
|
|
47
|
+
Short-range 3-center integrals (ij|k). The auxiliary basis functions are
|
|
48
|
+
placed at the second electron.
|
|
49
|
+
'''
|
|
50
|
+
int3c2e_opt = Int3c2eOpt(mol, auxmol).build()
|
|
51
|
+
ao_pair_mapping = cp.asarray(int3c2e_opt.create_ao_pair_mapping())
|
|
52
|
+
nao, nao_orig = int3c2e_opt.coeff.shape
|
|
53
|
+
naux = int3c2e_opt.aux_coeff.shape[0]
|
|
54
|
+
out = cp.zeros((nao*nao, naux))
|
|
55
|
+
p0 = p1 = 0
|
|
56
|
+
for ij_shls, eri3c in int3c2e_opt.int3c2e_kernel():
|
|
57
|
+
p0, p1 = p1, p1 + eri3c.shape[0]
|
|
58
|
+
addr = ao_pair_mapping[p0:p1]
|
|
59
|
+
out[addr] = eri3c
|
|
60
|
+
i, j = divmod(addr, nao)
|
|
61
|
+
out[j*nao+i] = eri3c
|
|
62
|
+
log = logger.new_logger(mol)
|
|
63
|
+
t1 = log.init_timer()
|
|
64
|
+
out = out.reshape(nao, nao, naux)
|
|
65
|
+
aux_coeff = cp.asarray(int3c2e_opt.aux_coeff)
|
|
66
|
+
coeff = cp.asarray(int3c2e_opt.coeff)
|
|
67
|
+
out = contract('pqr,rk->pqk', out, aux_coeff)
|
|
68
|
+
out = contract('pqk,qj->pjk', out, coeff)
|
|
69
|
+
out = contract('pjk,pi->ijk', out, coeff)
|
|
70
|
+
t1 = log.timer_debug1('aux_e2: transform basis ordering', *t1)
|
|
71
|
+
return out
|
|
72
|
+
|
|
73
|
+
class Int3c2eOpt:
|
|
74
|
+
def __init__(self, mol, auxmol):
|
|
75
|
+
self.mol = mol
|
|
76
|
+
self.auxmol = auxmol
|
|
77
|
+
self.sorted_mol = None
|
|
78
|
+
|
|
79
|
+
def build(self, cutoff=1e-14):
|
|
80
|
+
log = logger.new_logger(self.mol)
|
|
81
|
+
t0 = log.init_timer()
|
|
82
|
+
# allow_replica=True to transform the general contracted basis sets into
|
|
83
|
+
# segment contracted sets
|
|
84
|
+
mol, c2s = basis_seg_contraction(self.mol, allow_replica=True)
|
|
85
|
+
mol, coeff, uniq_l_ctr, l_ctr_counts, bas_mapping = group_basis(
|
|
86
|
+
mol, tile=1, return_bas_mapping=True)
|
|
87
|
+
self.sorted_mol = mol
|
|
88
|
+
self.uniq_l_ctr = uniq_l_ctr
|
|
89
|
+
l_ctr_offsets = self.l_ctr_offsets = np.append(0, np.cumsum(l_ctr_counts))
|
|
90
|
+
self.coeff = coeff.dot(c2s).get()
|
|
91
|
+
# Sorted AO indices, allow using the fancyindices to transform tensors
|
|
92
|
+
# between sorted_mol and mol (see function sort_orbitals)
|
|
93
|
+
ao_loc = mol.ao_loc_nr(cart=self.mol.cart)
|
|
94
|
+
ao_idx = np.array_split(np.arange(self.mol.nao), ao_loc[1:-1])
|
|
95
|
+
self.ao_idx = np.hstack([ao_idx[i] for i in bas_mapping]).argsort()
|
|
96
|
+
|
|
97
|
+
auxmol, coeff, uniq_l_ctr_aux, l_ctr_aux_counts = group_basis(self.auxmol, tile=1)
|
|
98
|
+
self.sorted_auxmol = auxmol
|
|
99
|
+
self.uniq_l_ctr_aux = uniq_l_ctr_aux
|
|
100
|
+
l_ctr_aux_offsets = self.l_ctr_aux_offsets = np.append(0, np.cumsum(l_ctr_aux_counts))
|
|
101
|
+
self.aux_coeff = coeff.get()
|
|
102
|
+
|
|
103
|
+
_atm_cpu, _bas_cpu, _env_cpu = conc_env(
|
|
104
|
+
mol._atm, mol._bas, _scale_sp_ctr_coeff(mol),
|
|
105
|
+
auxmol._atm, auxmol._bas, _scale_sp_ctr_coeff(auxmol))
|
|
106
|
+
#NOTE: PTR_BAS_COORD is not updated in conc_env()
|
|
107
|
+
off = _bas_cpu[mol.nbas,PTR_EXP] - auxmol._bas[0,PTR_EXP]
|
|
108
|
+
_bas_cpu[mol.nbas:,PTR_BAS_COORD] += off
|
|
109
|
+
self._atm = _atm_cpu
|
|
110
|
+
self._bas = _bas_cpu
|
|
111
|
+
self._env = _env_cpu
|
|
112
|
+
|
|
113
|
+
ao_loc_cpu = mol.ao_loc
|
|
114
|
+
aux_loc = auxmol.ao_loc
|
|
115
|
+
|
|
116
|
+
_atm = cp.array(_atm_cpu, dtype=np.int32)
|
|
117
|
+
_bas = cp.array(_bas_cpu, dtype=np.int32)
|
|
118
|
+
_env = cp.array(_env_cpu, dtype=np.float64)
|
|
119
|
+
ao_loc = cp.asarray(_conc_locs(ao_loc_cpu, aux_loc), dtype=np.int32)
|
|
120
|
+
self.int3c2e_envs = Int3c2eEnvVars(
|
|
121
|
+
mol.natm, mol.nbas, _atm.data.ptr, _bas.data.ptr, _env.data.ptr,
|
|
122
|
+
ao_loc.data.ptr, math.log(cutoff),
|
|
123
|
+
)
|
|
124
|
+
# Keep a reference to these arrays, prevent releasing them upon returning the closure
|
|
125
|
+
self.int3c2e_envs._env_ref_holder = (_atm, _bas, _env, ao_loc)
|
|
126
|
+
|
|
127
|
+
nksh_per_block = 16
|
|
128
|
+
# the auxiliary function offset (address) in the output tensor for each blockIdx.y
|
|
129
|
+
ksh_offsets = []
|
|
130
|
+
for ksh0, ksh1 in zip(l_ctr_aux_offsets[:-1], l_ctr_aux_offsets[1:]):
|
|
131
|
+
ksh_offsets.append(np.arange(ksh0, ksh1, nksh_per_block, dtype=np.int32))
|
|
132
|
+
ksh_offsets.append(l_ctr_aux_offsets[-1])
|
|
133
|
+
ksh_offsets = np.hstack(ksh_offsets)
|
|
134
|
+
ksh_offsets += mol.nbas
|
|
135
|
+
self.ksh_offsets = ksh_offsets
|
|
136
|
+
|
|
137
|
+
uniq_l = uniq_l_ctr[:,0]
|
|
138
|
+
assert uniq_l.max() <= LMAX
|
|
139
|
+
n_groups = len(uniq_l)
|
|
140
|
+
ij_tasks = ((i, j) for i in range(n_groups) for j in range(i+1))
|
|
141
|
+
|
|
142
|
+
ovlp = estimate_shl_ovlp(mol)
|
|
143
|
+
mask = np.tril(ovlp > cutoff)
|
|
144
|
+
# The effective shell pair = ish*nbas+jsh
|
|
145
|
+
shl_pair_idx = []
|
|
146
|
+
# the bas_ij_idx offset for each blockIdx.x
|
|
147
|
+
shl_pair_offsets = []
|
|
148
|
+
# the AO-pair offset (address) in the output tensor for each blockIdx.x
|
|
149
|
+
ao_pair_loc = []
|
|
150
|
+
nao_pair0 = nao_pair = 0
|
|
151
|
+
sp0 = sp1 = 0
|
|
152
|
+
nbas = mol.nbas
|
|
153
|
+
for i, j in ij_tasks:
|
|
154
|
+
li = uniq_l[i]
|
|
155
|
+
lj = uniq_l[j]
|
|
156
|
+
ish0, ish1 = l_ctr_offsets[i], l_ctr_offsets[i+1]
|
|
157
|
+
jsh0, jsh1 = l_ctr_offsets[j], l_ctr_offsets[j+1]
|
|
158
|
+
ish, jsh = np.where(mask[ish0:ish1,jsh0:jsh1])
|
|
159
|
+
ish += ish0
|
|
160
|
+
jsh += jsh0
|
|
161
|
+
idx = ish * nbas + jsh
|
|
162
|
+
nshl_pair = idx.size
|
|
163
|
+
shl_pair_idx.append(idx)
|
|
164
|
+
nfi = (li + 1) * (li + 2) // 2
|
|
165
|
+
nfj = (lj + 1) * (lj + 2) // 2
|
|
166
|
+
nfij = nfi * nfj
|
|
167
|
+
nao_pair0, nao_pair = nao_pair, nao_pair + nfij * nshl_pair
|
|
168
|
+
|
|
169
|
+
sp0, sp1 = sp1, sp1 + nshl_pair
|
|
170
|
+
nsp_per_block = _estimate_shl_pairs_per_block(li, lj, nshl_pair)
|
|
171
|
+
shl_pair_offsets.append(np.arange(sp0, sp1, nsp_per_block, dtype=np.int32))
|
|
172
|
+
ao_pair_loc.append(
|
|
173
|
+
np.arange(nao_pair0, nao_pair, nsp_per_block*nfij, dtype=np.int32))
|
|
174
|
+
if log.verbose >= logger.DEBUG2:
|
|
175
|
+
log.debug2('group=(%d,%d), li,lj=(%d,%d), sp range(%d,%d,%d), '
|
|
176
|
+
'nao_pair offset=%d',
|
|
177
|
+
i, j, li, lj, sp0, sp1, nsp_per_block, nao_pair0)
|
|
178
|
+
|
|
179
|
+
self.shl_pair_idx = shl_pair_idx
|
|
180
|
+
shl_pair_offsets.append([sp1])
|
|
181
|
+
self.shl_pair_offsets = np.hstack(shl_pair_offsets)
|
|
182
|
+
ao_pair_loc.append(nao_pair)
|
|
183
|
+
self.ao_pair_loc = np.hstack(ao_pair_loc)
|
|
184
|
+
if log.verbose >= logger.DEBUG1:
|
|
185
|
+
log.timer_debug1('initialize int3c2e_kernel', *t0)
|
|
186
|
+
return self
|
|
187
|
+
|
|
188
|
+
def int3c2e_kernel(self, cutoff=1e-14, verbose=None):
|
|
189
|
+
if self.sorted_mol is None:
|
|
190
|
+
self.build(cutoff)
|
|
191
|
+
log = logger.new_logger(self.mol, verbose)
|
|
192
|
+
t0 = t1 = log.init_timer()
|
|
193
|
+
l_ctr_offsets = self.l_ctr_offsets
|
|
194
|
+
l_ctr_aux_offsets = self.l_ctr_aux_offsets
|
|
195
|
+
int3c2e_envs = self.int3c2e_envs
|
|
196
|
+
_atm_cpu = self._atm
|
|
197
|
+
_bas_cpu = self._bas
|
|
198
|
+
_env_cpu = self._env
|
|
199
|
+
mol = self.sorted_mol
|
|
200
|
+
aux_loc = self.sorted_auxmol.ao_loc
|
|
201
|
+
naux = aux_loc[-1]
|
|
202
|
+
|
|
203
|
+
uniq_l = self.uniq_l_ctr[:,0]
|
|
204
|
+
nfcart = (uniq_l + 1) * (uniq_l + 2) // 2
|
|
205
|
+
n_groups = len(uniq_l)
|
|
206
|
+
ij_tasks = [(i, j) for i in range(n_groups) for j in range(i+1)]
|
|
207
|
+
npair_ij = 0
|
|
208
|
+
for (i, j), bas_ij_idx in zip(ij_tasks, self.shl_pair_idx):
|
|
209
|
+
nfij = nfcart[i] * nfcart[j]
|
|
210
|
+
npair_ij = max(npair_ij, len(bas_ij_idx) * nfij)
|
|
211
|
+
buf = cp.empty((npair_ij, naux))
|
|
212
|
+
|
|
213
|
+
init_constant(mol)
|
|
214
|
+
kern = libgint_rys.fill_int3c2e
|
|
215
|
+
timing_collection = {}
|
|
216
|
+
kern_counts = 0
|
|
217
|
+
|
|
218
|
+
for (i, j), bas_ij_idx in zip(ij_tasks, self.shl_pair_idx):
|
|
219
|
+
ish0, ish1 = l_ctr_offsets[i], l_ctr_offsets[i+1]
|
|
220
|
+
jsh0, jsh1 = l_ctr_offsets[j], l_ctr_offsets[j+1]
|
|
221
|
+
npair_ij = len(bas_ij_idx)
|
|
222
|
+
bas_ij_idx = cp.asarray(bas_ij_idx, dtype=np.int32)
|
|
223
|
+
li = uniq_l[i]
|
|
224
|
+
lj = uniq_l[j]
|
|
225
|
+
nfij = nfcart[i] * nfcart[j]
|
|
226
|
+
eri3c = cp.ndarray((npair_ij*nfij, naux), dtype=np.float64, memptr=buf.data)
|
|
227
|
+
|
|
228
|
+
for k, lk in enumerate(self.uniq_l_ctr_aux[:,0]):
|
|
229
|
+
ksh0, ksh1 = l_ctr_aux_offsets[k:k+2]
|
|
230
|
+
shls_slice = ish0, ish1, jsh0, jsh1, ksh0, ksh1
|
|
231
|
+
lll = f'({ANGULAR[li]}{ANGULAR[lj]}|{ANGULAR[lk]})'
|
|
232
|
+
scheme = int3c2e_scheme(li, lj, lk)
|
|
233
|
+
log.debug2('int3c2e_scheme for %s: %s', lll, scheme)
|
|
234
|
+
err = kern(
|
|
235
|
+
ctypes.cast(eri3c.data.ptr, ctypes.c_void_p),
|
|
236
|
+
ctypes.byref(int3c2e_envs), (ctypes.c_int*3)(*scheme),
|
|
237
|
+
(ctypes.c_int*6)(*shls_slice), aux_loc.ctypes,
|
|
238
|
+
ctypes.c_int(naux), ctypes.c_int(npair_ij),
|
|
239
|
+
ctypes.cast(bas_ij_idx.data.ptr, ctypes.c_void_p),
|
|
240
|
+
_atm_cpu.ctypes, ctypes.c_int(mol.natm),
|
|
241
|
+
_bas_cpu.ctypes, ctypes.c_int(mol.nbas), _env_cpu.ctypes)
|
|
242
|
+
if err != 0:
|
|
243
|
+
raise RuntimeError(f'fill_int3c2e kernel for {lll} failed')
|
|
244
|
+
if log.verbose >= logger.DEBUG1:
|
|
245
|
+
t1, t1p = log.timer_debug1(f'processing {lll}', *t1), t1
|
|
246
|
+
if lll not in timing_collection:
|
|
247
|
+
timing_collection[lll] = 0
|
|
248
|
+
timing_collection[lll] += t1[1] - t1p[1]
|
|
249
|
+
kern_counts += 1
|
|
250
|
+
|
|
251
|
+
ij_shls = ish0, ish1, jsh0, jsh1
|
|
252
|
+
yield ij_shls, eri3c
|
|
253
|
+
|
|
254
|
+
if log.verbose >= logger.DEBUG1:
|
|
255
|
+
cp.cuda.Stream.null.synchronize()
|
|
256
|
+
log.timer('int3c2e', *t0)
|
|
257
|
+
log.debug1('kernel launches %d', kern_counts)
|
|
258
|
+
for lll, t in timing_collection.items():
|
|
259
|
+
log.debug1('%s wall time %.2f', lll, t)
|
|
260
|
+
|
|
261
|
+
def int3c2e_bdiv_kernel(self, cutoff=1e-14, verbose=None):
|
|
262
|
+
'''Construct the entire block using the block-divergent parallelism'''
|
|
263
|
+
if self.sorted_mol is None:
|
|
264
|
+
self.build(cutoff)
|
|
265
|
+
log = logger.new_logger(self.mol, verbose)
|
|
266
|
+
t0 = log.init_timer()
|
|
267
|
+
int3c2e_envs = self.int3c2e_envs
|
|
268
|
+
_atm_cpu = self._atm
|
|
269
|
+
_bas_cpu = self._bas
|
|
270
|
+
_env_cpu = self._env
|
|
271
|
+
mol = self.sorted_mol
|
|
272
|
+
aux_loc = self.sorted_auxmol.ao_loc
|
|
273
|
+
naux = aux_loc[-1]
|
|
274
|
+
nao_pair = self.ao_pair_loc[-1]
|
|
275
|
+
|
|
276
|
+
# nst_lookup stores the nst_per_block for each (li,lj,lk) pattern
|
|
277
|
+
nst_lookup = cp.asarray(create_nst_lookup_table(), dtype=np.int32)
|
|
278
|
+
|
|
279
|
+
shl_pair_idx = cp.asarray(np.hstack(self.shl_pair_idx), dtype=np.int32)
|
|
280
|
+
shl_pair_offsets = cp.asarray(self.shl_pair_offsets, dtype=np.int32)
|
|
281
|
+
ksh_offsets = cp.asarray(self.ksh_offsets, dtype=np.int32)
|
|
282
|
+
nbatches_shl_pair = len(shl_pair_offsets) - 1
|
|
283
|
+
nbatches_ksh = len(ksh_offsets) - 1
|
|
284
|
+
ao_pair_loc = cp.asarray(self.ao_pair_loc, dtype=np.int32)
|
|
285
|
+
log.debug1('sp_blocks = %d, ksh_blocks = %d', nbatches_shl_pair, nbatches_ksh)
|
|
286
|
+
|
|
287
|
+
init_constant(mol)
|
|
288
|
+
kern = libgint_rys.fill_int3c2e_bdiv
|
|
289
|
+
eri3c = cp.empty((nao_pair, naux))
|
|
290
|
+
err = kern(
|
|
291
|
+
ctypes.cast(eri3c.data.ptr, ctypes.c_void_p),
|
|
292
|
+
ctypes.byref(int3c2e_envs),
|
|
293
|
+
ctypes.c_int(SHM_SIZE), ctypes.c_int(naux),
|
|
294
|
+
ctypes.c_int(nbatches_shl_pair), ctypes.c_int(nbatches_ksh),
|
|
295
|
+
ctypes.cast(shl_pair_offsets.data.ptr, ctypes.c_void_p),
|
|
296
|
+
ctypes.cast(ao_pair_loc.data.ptr, ctypes.c_void_p),
|
|
297
|
+
ctypes.cast(ksh_offsets.data.ptr, ctypes.c_void_p),
|
|
298
|
+
ctypes.cast(shl_pair_idx.data.ptr, ctypes.c_void_p),
|
|
299
|
+
ctypes.cast(nst_lookup.data.ptr, ctypes.c_void_p),
|
|
300
|
+
_atm_cpu.ctypes, ctypes.c_int(mol.natm),
|
|
301
|
+
_bas_cpu.ctypes, ctypes.c_int(mol.nbas), _env_cpu.ctypes)
|
|
302
|
+
if err != 0:
|
|
303
|
+
raise RuntimeError('fill_int3c2e_bdiv kernel failed')
|
|
304
|
+
if log.verbose >= logger.DEBUG1:
|
|
305
|
+
cp.cuda.Stream.null.synchronize()
|
|
306
|
+
log.timer_debug1('processing int3c2e_bdiv_kernel', *t0)
|
|
307
|
+
return eri3c
|
|
308
|
+
|
|
309
|
+
def create_ao_pair_mapping(self, cart=True):
|
|
310
|
+
'''ao_pair_mapping stores AO-pair addresses in the nao x nao matrix,
|
|
311
|
+
which allows the decompression for the CUDA kernel generated compressed_eri3c:
|
|
312
|
+
sparse_eri3c[ao_pair_mapping] = compressed_eri3c
|
|
313
|
+
|
|
314
|
+
int3c2e CUDA kernel stores intgrals as [ij_shl,j,i,k,ksh].
|
|
315
|
+
ao_pair_mapping indicates the ij addresses in eri3c[k,i,j];
|
|
316
|
+
'''
|
|
317
|
+
mol = self.sorted_mol
|
|
318
|
+
ao_loc = mol.ao_loc_nr(cart)
|
|
319
|
+
nao = ao_loc[-1]
|
|
320
|
+
uniq_l = self.uniq_l_ctr[:,0]
|
|
321
|
+
if cart:
|
|
322
|
+
nf = (uniq_l + 1) * (uniq_l + 2) // 2
|
|
323
|
+
else:
|
|
324
|
+
nf = uniq_l * 2 + 1
|
|
325
|
+
n_groups = len(uniq_l)
|
|
326
|
+
ij_tasks = ((i, j) for i in range(n_groups) for j in range(i+1))
|
|
327
|
+
nbas = mol.nbas
|
|
328
|
+
ao_pair_mapping = []
|
|
329
|
+
for (i, j), bas_ij_idx in zip(ij_tasks, self.shl_pair_idx):
|
|
330
|
+
ish, jsh = divmod(bas_ij_idx, nbas)
|
|
331
|
+
nfi = nf[i]
|
|
332
|
+
nfj = nf[j]
|
|
333
|
+
iaddr = ao_loc[ish,None] + np.arange(nfi)
|
|
334
|
+
jaddr = ao_loc[jsh,None] + np.arange(nfj)
|
|
335
|
+
ao_pair_mapping.append((iaddr[:,None,:] * nao + jaddr[:,:,None]).ravel())
|
|
336
|
+
return np.hstack(ao_pair_mapping)
|
|
337
|
+
|
|
338
|
+
def orbital_pair_cart2sph(self, compressed_eri3c, inplace=True):
|
|
339
|
+
'''Transforms the AO of the compressed eri3c from Cartesian to spherical basis'''
|
|
340
|
+
if inplace:
|
|
341
|
+
out = compressed_eri3c
|
|
342
|
+
else:
|
|
343
|
+
out = compressed_eri3c.copy()
|
|
344
|
+
uniq_l = self.uniq_l_ctr[:,0]
|
|
345
|
+
n_groups = len(uniq_l)
|
|
346
|
+
ij_tasks = ((i, j) for i in range(n_groups) for j in range(i+1))
|
|
347
|
+
c2s = [cart2sph_by_l(l) for l in uniq_l]
|
|
348
|
+
naux = compressed_eri3c.shape[1]
|
|
349
|
+
npair0 = npair = 0
|
|
350
|
+
p0 = p1 = 0
|
|
351
|
+
for (i, j), bas_ij_idx in zip(ij_tasks, self.shl_pair_idx):
|
|
352
|
+
nshl_pair = bas_ij_idx.size
|
|
353
|
+
ci = c2s[i]
|
|
354
|
+
cj = c2s[j]
|
|
355
|
+
nfi, di = ci.shape
|
|
356
|
+
nfj, dj = cj.shape
|
|
357
|
+
npair0, npair = npair, npair + nfi*nfj * nshl_pair
|
|
358
|
+
p0, p1 = p1, p1 + di*dj * nshl_pair
|
|
359
|
+
if npair0 > len(compressed_eri3c):
|
|
360
|
+
raise RuntimeError('Size mismatch. The eri3c may have been transformed')
|
|
361
|
+
t = compressed_eri3c[npair0:npair].reshape(nshl_pair,nfj,nfi,naux)
|
|
362
|
+
t = contract('mpqr,pj->mjqr', t, cj)
|
|
363
|
+
t = contract('mjqr,qi->mjir', t, ci)
|
|
364
|
+
out[p0:p1] = t.reshape(p1-p0,naux)
|
|
365
|
+
return out[:p1]
|
|
366
|
+
|
|
367
|
+
def sort_orbitals(self, mat, axis=[]):
|
|
368
|
+
''' Transform given axis of a matrix into sorted AO'''
|
|
369
|
+
ndim_to_transform = len(axis)
|
|
370
|
+
assert ndim_to_transform <= 2
|
|
371
|
+
if ndim_to_transform == 0:
|
|
372
|
+
return mat
|
|
373
|
+
|
|
374
|
+
idx = self.ao_idx
|
|
375
|
+
fancy_index = [slice(None)] * mat.ndim
|
|
376
|
+
if ndim_to_transform == 1:
|
|
377
|
+
fancy_index[axis[0]] = idx
|
|
378
|
+
elif ndim_to_transform == 2:
|
|
379
|
+
assert abs(axis[0] - axis[1]) == 1, 'Must be adjacent axes'
|
|
380
|
+
fancy_index[axis[0]] = idx[:,None]
|
|
381
|
+
fancy_index[axis[1]] = idx
|
|
382
|
+
return mat[tuple(fancy_index)]
|
|
383
|
+
|
|
384
|
+
def unsort_orbitals(self, sorted_mat, axis=[]):
|
|
385
|
+
'''sort_orbitals reversed, transform the matrix in sorted AOs back to
|
|
386
|
+
the original matrix.
|
|
387
|
+
'''
|
|
388
|
+
ndim_to_transform = len(axis)
|
|
389
|
+
assert ndim_to_transform <= 2
|
|
390
|
+
if ndim_to_transform == 0:
|
|
391
|
+
return sorted_mat
|
|
392
|
+
|
|
393
|
+
idx = self.ao_idx
|
|
394
|
+
fancy_index = [slice(None)] * sorted_mat.ndim
|
|
395
|
+
if ndim_to_transform == 1:
|
|
396
|
+
fancy_index[axis[0]] = idx
|
|
397
|
+
elif ndim_to_transform == 2:
|
|
398
|
+
assert abs(axis[0] - axis[1]) == 1, 'Must be adjacent axes'
|
|
399
|
+
fancy_index[axis[0]] = idx[:,None]
|
|
400
|
+
fancy_index[axis[1]] = idx
|
|
401
|
+
mat = cp.empty_like(sorted_mat)
|
|
402
|
+
mat[tuple(fancy_index)] = sorted_mat
|
|
403
|
+
return mat
|
|
404
|
+
|
|
405
|
+
def _conc_locs(ao_loc1, ao_loc2):
|
|
406
|
+
return np.append(ao_loc1[:-1], ao_loc1[-1] + ao_loc2)
|
|
407
|
+
|
|
408
|
+
class Int3c2eEnvVars(ctypes.Structure):
|
|
409
|
+
_fields_ = [
|
|
410
|
+
('natm', ctypes.c_uint16),
|
|
411
|
+
('nbas', ctypes.c_uint16),
|
|
412
|
+
('atm', ctypes.c_void_p),
|
|
413
|
+
('bas', ctypes.c_void_p),
|
|
414
|
+
('env', ctypes.c_void_p),
|
|
415
|
+
('ao_loc', ctypes.c_void_p),
|
|
416
|
+
('log_cutoff', ctypes.c_float),
|
|
417
|
+
]
|
|
418
|
+
|
|
419
|
+
def init_constant(mol):
|
|
420
|
+
g_idx, offsets = g_pair_idx()
|
|
421
|
+
err = libgint_rys.init_constant(
|
|
422
|
+
g_idx.ctypes, offsets.ctypes, mol._env.ctypes, ctypes.c_int(mol._env.size),
|
|
423
|
+
ctypes.c_int(SHM_SIZE))
|
|
424
|
+
if err != 0:
|
|
425
|
+
raise RuntimeError('CUDA kernel initialization')
|
|
426
|
+
|
|
427
|
+
def int3c2e_scheme(li, lj, lk, shm_size=SHM_SIZE):
|
|
428
|
+
order = li + lj + lk
|
|
429
|
+
nroots = (order//2 + 1) * 2
|
|
430
|
+
|
|
431
|
+
g_size = (li+1)*(lj+1)*(lk+1)
|
|
432
|
+
unit = g_size*3 + nroots*2 + 7
|
|
433
|
+
nst_max = shm_size//(unit*8)
|
|
434
|
+
nst_max = _nearest_power2(nst_max)
|
|
435
|
+
|
|
436
|
+
nfi = (li + 1) * (li + 2) // 2
|
|
437
|
+
nfj = (lj + 1) * (lj + 2) // 2
|
|
438
|
+
nfk = (lk + 1) * (lk + 2) // 2
|
|
439
|
+
gout_size = nfi * nfj * nfk
|
|
440
|
+
gout_stride = (gout_size + GOUT_WIDTH-1) // GOUT_WIDTH
|
|
441
|
+
# Round up to the next 2^n
|
|
442
|
+
gout_stride = _nearest_power2(gout_stride, return_leq=False)
|
|
443
|
+
gout_stride = min(gout_stride, 64)
|
|
444
|
+
|
|
445
|
+
nst_per_block = min(nst_max, THREADS // gout_stride)
|
|
446
|
+
gout_stride = THREADS // nst_per_block
|
|
447
|
+
return nst_per_block, gout_stride
|
|
448
|
+
|
|
449
|
+
def _estimate_shl_pairs_per_block(li, lj, nshl_pair):
|
|
450
|
+
return _nearest_power2(THREADS*2 // ((li+1)*(lj+1)), return_leq=False)
|
|
451
|
+
|
|
452
|
+
def create_nst_lookup_table():
|
|
453
|
+
nst_lookup = np.empty([L_AUX_MAX+1]*3, dtype=np.int32)
|
|
454
|
+
for lk in range(L_AUX_MAX+1):
|
|
455
|
+
for li in range(lk+1):
|
|
456
|
+
for lj in range(li+1):
|
|
457
|
+
nst_lookup[lk,li,lj] = int3c2e_scheme(li, lj, lk)[0]
|
|
458
|
+
idx = np.arange(L_AUX_MAX+1)
|
|
459
|
+
z, y, x = np.sort(np.meshgrid(idx, idx, idx), axis=0)
|
|
460
|
+
nst_lookup = nst_lookup[x, y, z]
|
|
461
|
+
return nst_lookup[:,:LMAX+1,:LMAX+1]
|
|
462
|
+
|
|
463
|
+
def estimate_shl_ovlp(mol):
|
|
464
|
+
# consider only the most diffused component of a basis
|
|
465
|
+
exps, cs = extract_pgto_params(mol, 'diffused')
|
|
466
|
+
ls = mol._bas[:,ANG_OF]
|
|
467
|
+
bas_coords = mol.atom_coords()[mol._bas[:,ATOM_OF]]
|
|
468
|
+
|
|
469
|
+
norm = cs * ((2*ls+1)/(4*np.pi))**.5
|
|
470
|
+
aij = exps[:,None] + exps
|
|
471
|
+
fi = exps[:,None] / aij
|
|
472
|
+
fj = exps[None,:] / aij
|
|
473
|
+
theta = exps[:,None] * fj
|
|
474
|
+
|
|
475
|
+
rirj = bas_coords[:,None,:] - bas_coords
|
|
476
|
+
dr = np.linalg.norm(rirj, axis=2)
|
|
477
|
+
dri = fj * dr
|
|
478
|
+
drj = fi * dr
|
|
479
|
+
li = ls[:,None]
|
|
480
|
+
lj = ls[None,:]
|
|
481
|
+
fac_dri = (li * .5/aij + dri**2) ** (li*.5)
|
|
482
|
+
fac_drj = (lj * .5/aij + drj**2) ** (lj*.5)
|
|
483
|
+
fac_norm = norm[:,None]*norm * (np.pi/aij)**1.5
|
|
484
|
+
ovlp = fac_norm * np.exp(-theta*dr**2) * fac_dri * fac_drj
|
|
485
|
+
return ovlp
|
|
@@ -34,7 +34,6 @@ from pyscf.dft import gen_grid as gen_grid_cpu
|
|
|
34
34
|
from gpu4pyscf.lib import utils
|
|
35
35
|
from pyscf.gto.eval_gto import BLKSIZE, NBINS, CUTOFF, make_screen_index
|
|
36
36
|
from pyscf import __config__
|
|
37
|
-
from cupyx.scipy.spatial.distance import cdist
|
|
38
37
|
from gpu4pyscf.lib import logger
|
|
39
38
|
from gpu4pyscf.dft import radi
|
|
40
39
|
from gpu4pyscf.lib.cupy_helper import load_library
|
|
@@ -74,13 +73,17 @@ def sg1_prune(nuc, rads, n_ang, radii=radi.SG1RADII):
|
|
|
74
73
|
'''
|
|
75
74
|
# In SG1 the ang grids for the five regions
|
|
76
75
|
# 6 38 86 194 86
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
if nuc >= 19:
|
|
77
|
+
return 194 * numpy.ones_like(rads, dtype=numpy.int64)
|
|
78
|
+
|
|
79
|
+
leb_ngrid = numpy.array([6, 38, 86, 194, 86], dtype=numpy.int64)
|
|
80
|
+
alphas = numpy.array((
|
|
79
81
|
(0.25 , 0.5, 1.0, 4.5),
|
|
80
82
|
(0.1667, 0.5, 0.9, 3.5),
|
|
81
83
|
(0.1 , 0.4, 0.8, 2.5)))
|
|
84
|
+
|
|
82
85
|
r_atom = radii[nuc] + 1e-200
|
|
83
|
-
rads =
|
|
86
|
+
rads = numpy.asarray(rads)
|
|
84
87
|
if nuc <= 2: # H, He
|
|
85
88
|
place = ((rads/r_atom).reshape(-1,1) > alphas[0]).sum(axis=1)
|
|
86
89
|
elif nuc <= 10: # Li - Ne
|