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.
Files changed (168) hide show
  1. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/CHANGELOG +10 -0
  2. {gpu4pyscf-1.3.1/gpu4pyscf.egg-info → gpu4pyscf-1.3.2}/PKG-INFO +1 -1
  3. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/__init__.py +1 -1
  4. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/df.py +53 -0
  5. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/hessian/rhf.py +11 -10
  6. gpu4pyscf-1.3.2/gpu4pyscf/df/int3c2e_bdiv.py +485 -0
  7. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/gen_grid.py +7 -4
  8. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/libxc.py +3 -2
  9. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/numint.py +22 -18
  10. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/rks.py +24 -1
  11. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/uks.py +1 -1
  12. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/drivers/dft_3c_driver.py +5 -0
  13. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/drivers/dft_driver.py +114 -119
  14. gpu4pyscf-1.3.2/gpu4pyscf/drivers/opt_driver.py +189 -0
  15. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/grad/rhf.py +18 -4
  16. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/gto/mole.py +60 -18
  17. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/hessian/rhf.py +26 -4
  18. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/cupy_helper.py +13 -11
  19. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/cutensor.py +16 -10
  20. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/logger.py +6 -3
  21. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/fft.py +10 -9
  22. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/ft_ao.py +7 -5
  23. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/int3c2e.py +3 -2
  24. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/rsdf_builder.py +1 -1
  25. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/dft/krks.py +44 -7
  26. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/dft/kuks.py +30 -9
  27. gpu4pyscf-1.3.2/gpu4pyscf/pbc/dft/multigrid.py +998 -0
  28. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/dft/rks.py +43 -3
  29. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/dft/uks.py +28 -8
  30. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/int4c2e.py +1 -1
  31. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/j_engine.py +4 -11
  32. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/jk.py +3 -21
  33. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/tdscf/_lr_eig.py +14 -12
  34. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2/gpu4pyscf.egg-info}/PKG-INFO +1 -1
  35. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf.egg-info/SOURCES.txt +2 -1
  36. gpu4pyscf-1.3.2/gpu4pyscf.egg-info/requires.txt +5 -0
  37. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/setup.py +2 -2
  38. gpu4pyscf-1.3.1/gpu4pyscf/drivers/opt_driver.py +0 -175
  39. gpu4pyscf-1.3.1/gpu4pyscf/pbc/gto/cell.py +0 -49
  40. gpu4pyscf-1.3.1/gpu4pyscf.egg-info/requires.txt +0 -5
  41. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/LICENSE +0 -0
  42. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/MANIFEST.in +0 -0
  43. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/README.md +0 -0
  44. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/__config__.py +0 -0
  45. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/cc/__init__.py +0 -0
  46. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/cc/ccsd_incore.py +0 -0
  47. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/__init__.py +0 -0
  48. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/cderi.py +0 -0
  49. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/df_jk.py +0 -0
  50. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/grad/__init__.py +0 -0
  51. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/grad/jk.py +0 -0
  52. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/grad/rhf.py +0 -0
  53. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/grad/rks.py +0 -0
  54. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/grad/uhf.py +0 -0
  55. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/grad/uks.py +0 -0
  56. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/hessian/__init__.py +0 -0
  57. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/hessian/jk.py +0 -0
  58. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/hessian/rks.py +0 -0
  59. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/hessian/uhf.py +0 -0
  60. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/hessian/uks.py +0 -0
  61. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/df/int3c2e.py +0 -0
  62. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/__init__.py +0 -0
  63. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/gks.py +0 -0
  64. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/libxc_structs.py +0 -0
  65. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/radi.py +0 -0
  66. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/roks.py +0 -0
  67. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/xc_alias.py +0 -0
  68. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/dft/xc_deriv.py +0 -0
  69. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/drivers/__init__.py +0 -0
  70. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/drivers/basis_vDZP_NWCHEM.dat +0 -0
  71. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/drivers/ecp_vDZP_NWCHEM.dat +0 -0
  72. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/drivers/opt_3c_driver.py +0 -0
  73. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/fci/__init__.py +0 -0
  74. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/fci/direct_spin1.py +0 -0
  75. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/grad/__init__.py +0 -0
  76. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/grad/dispersion.py +0 -0
  77. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/grad/rks.py +0 -0
  78. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/grad/uhf.py +0 -0
  79. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/grad/uks.py +0 -0
  80. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/gto/__init__.py +0 -0
  81. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/gto/int3c1e.py +0 -0
  82. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/gto/int3c1e_ip.py +0 -0
  83. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/gto/int3c1e_ipip.py +0 -0
  84. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/hessian/__init__.py +0 -0
  85. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/hessian/dispersion.py +0 -0
  86. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/hessian/jk.py +0 -0
  87. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/hessian/rks.py +0 -0
  88. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/hessian/uhf.py +0 -0
  89. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/hessian/uks.py +0 -0
  90. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/__init__.py +0 -0
  91. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/cublas.py +0 -0
  92. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/cusolver.py +0 -0
  93. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/diis.py +0 -0
  94. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/memcpy.py +0 -0
  95. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/multi_gpu.py +0 -0
  96. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/lib/utils.py +0 -0
  97. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/mp/__init__.py +0 -0
  98. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/mp/dfmp2.py +0 -0
  99. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/mp/mp2.py +0 -0
  100. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/__init__.py +0 -0
  101. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/__init__.py +0 -0
  102. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/aft.py +0 -0
  103. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/aft_jk.py +0 -0
  104. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/df.py +0 -0
  105. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/df_jk.py +0 -0
  106. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/df/fft_jk.py +0 -0
  107. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/dft/__init__.py +0 -0
  108. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/dft/gen_grid.py +0 -0
  109. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/dft/numint.py +0 -0
  110. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/gto/__init__.py +0 -0
  111. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/lib/__init__.py +0 -0
  112. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/lib/kpts_helper.py +0 -0
  113. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/scf/__init__.py +0 -0
  114. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/scf/hf.py +0 -0
  115. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/scf/khf.py +0 -0
  116. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/scf/kuhf.py +0 -0
  117. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/scf/uhf.py +0 -0
  118. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/tools/__init__.py +0 -0
  119. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/tools/k2gamma.py +0 -0
  120. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pbc/tools/pbc.py +0 -0
  121. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pop/__init__.py +0 -0
  122. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/pop/esp.py +0 -0
  123. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/properties/__init__.py +0 -0
  124. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/properties/ir.py +0 -0
  125. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/properties/polarizability.py +0 -0
  126. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/properties/shielding.py +0 -0
  127. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/qmmm/__init__.py +0 -0
  128. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/qmmm/chelpg.py +0 -0
  129. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/qmmm/pbc/__init__.py +0 -0
  130. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/qmmm/pbc/itrf.py +0 -0
  131. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/qmmm/pbc/mm_mole.py +0 -0
  132. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/qmmm/pbc/tools.py +0 -0
  133. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/__init__.py +0 -0
  134. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/_response_functions.py +0 -0
  135. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/cphf.py +0 -0
  136. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/diis.py +0 -0
  137. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/dispersion.py +0 -0
  138. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/ghf.py +0 -0
  139. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/hf.py +0 -0
  140. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/hf_symm.py +0 -0
  141. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/int2c2e.py +0 -0
  142. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/rohf.py +0 -0
  143. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/soscf.py +0 -0
  144. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/ucphf.py +0 -0
  145. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/uhf.py +0 -0
  146. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/scf/uhf_symm.py +0 -0
  147. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/__init__.py +0 -0
  148. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/_attach_solvent.py +0 -0
  149. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/grad/__init__.py +0 -0
  150. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/grad/pcm.py +0 -0
  151. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/grad/smd.py +0 -0
  152. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/grad/smd_experiment.py +0 -0
  153. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/hessian/__init__.py +0 -0
  154. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/hessian/pcm.py +0 -0
  155. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/hessian/smd.py +0 -0
  156. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/hessian/smd_experiment.py +0 -0
  157. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/pcm.py +0 -0
  158. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/smd.py +0 -0
  159. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/solvent/smd_experiment.py +0 -0
  160. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/tdscf/__init__.py +0 -0
  161. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/tdscf/_uhf_resp_sf.py +0 -0
  162. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/tdscf/rhf.py +0 -0
  163. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/tdscf/rks.py +0 -0
  164. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/tdscf/uhf.py +0 -0
  165. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf/tdscf/uks.py +0 -0
  166. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf.egg-info/dependency_links.txt +0 -0
  167. {gpu4pyscf-1.3.1 → gpu4pyscf-1.3.2}/gpu4pyscf.egg-info/top_level.txt +0 -0
  168. {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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: gpu4pyscf
3
- Version: 1.3.1
3
+ Version: 1.3.2
4
4
  Summary: GPU extensions for PySCF
5
5
  Author: PySCF developers
6
6
  License: Apache-2.0
@@ -12,6 +12,6 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- __version__ = '1.3.1'
15
+ __version__ = '1.3.2'
16
16
 
17
17
  from . import lib, grad, hessian, solvent, scf, dft
@@ -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 = rhok1_Pko_kslice = None
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
- for i0, i1 in lib.prange(0,nao,blksize):
181
- #wk1_Pko_islice = cupy.asarray(wk1_Pko[:,i0:i1])
182
- wk1_Pko_islice = copy_array(wk1_Pko[:,i0:i1])
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
- rhok1_Pko = None
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
- leb_ngrid = cupy.array([6, 38, 86, 194, 86])
78
- alphas = cupy.array((
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 = cupy.asarray(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