pyscf 2.6.2__py3-none-macosx_11_0_arm64.whl → 2.8.0__py3-none-macosx_11_0_arm64.whl

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 (360) hide show
  1. pyscf/__init__.py +2 -2
  2. pyscf/adc/__init__.py +3 -8
  3. pyscf/adc/dfadc.py +22 -6
  4. pyscf/adc/radc.py +106 -15
  5. pyscf/adc/radc_amplitudes.py +7 -1
  6. pyscf/adc/radc_ao2mo.py +4 -2
  7. pyscf/adc/radc_ea.py +524 -8
  8. pyscf/adc/radc_ip.py +492 -60
  9. pyscf/adc/radc_ip_cvs.py +4 -2
  10. pyscf/adc/uadc.py +116 -27
  11. pyscf/adc/uadc_amplitudes.py +215 -20
  12. pyscf/adc/uadc_ao2mo.py +30 -9
  13. pyscf/adc/uadc_ea.py +34 -44
  14. pyscf/adc/uadc_ip.py +9 -4
  15. pyscf/adc/uadc_ip_cvs.py +4 -1
  16. pyscf/agf2/__init__.py +2 -2
  17. pyscf/agf2/aux_space.py +1 -1
  18. pyscf/agf2/chkfile.py +1 -1
  19. pyscf/ao2mo/__init__.py +13 -2
  20. pyscf/ao2mo/_ao2mo.py +10 -1
  21. pyscf/ao2mo/incore.py +3 -0
  22. pyscf/ao2mo/nrr_outcore.py +2 -2
  23. pyscf/ao2mo/outcore.py +9 -7
  24. pyscf/ao2mo/r_outcore.py +2 -2
  25. pyscf/cc/__init__.py +21 -3
  26. pyscf/cc/bccd.py +0 -46
  27. pyscf/cc/ccsd.py +29 -13
  28. pyscf/cc/ccsd_rdm.py +6 -1
  29. pyscf/cc/gccsd.py +2 -2
  30. pyscf/cc/uccsd.py +7 -7
  31. pyscf/cc/uccsd_rdm.py +2 -2
  32. pyscf/data/elements.py +1 -1
  33. pyscf/df/__init__.py +2 -1
  34. pyscf/df/addons.py +79 -51
  35. pyscf/df/autoaux.py +195 -0
  36. pyscf/df/df.py +5 -1
  37. pyscf/df/df_jk.py +27 -25
  38. pyscf/df/grad/casscf.py +0 -41
  39. pyscf/df/grad/rhf.py +31 -1
  40. pyscf/df/hessian/rhf.py +2 -10
  41. pyscf/df/hessian/rks.py +1 -7
  42. pyscf/df/hessian/uhf.py +3 -13
  43. pyscf/df/hessian/uks.py +1 -8
  44. pyscf/df/incore.py +18 -6
  45. pyscf/df/outcore.py +6 -6
  46. pyscf/dft/dks.py +1 -1
  47. pyscf/dft/gks.py +25 -21
  48. pyscf/dft/libxc.py +91 -645
  49. pyscf/dft/numint.py +40 -19
  50. pyscf/dft/radi.py +48 -7
  51. pyscf/dft/rks.py +29 -25
  52. pyscf/dft/roks.py +7 -1
  53. pyscf/dft/uks.py +34 -25
  54. pyscf/dft/xc_deriv.py +1 -1
  55. pyscf/dft/xcfun.py +53 -2
  56. pyscf/eph/eph_fd.py +1 -1
  57. pyscf/eph/rhf.py +6 -36
  58. pyscf/eph/rks.py +0 -4
  59. pyscf/eph/uhf.py +1 -7
  60. pyscf/eph/uks.py +1 -7
  61. pyscf/fci/addons.py +117 -2
  62. pyscf/fci/cistring.py +1 -1
  63. pyscf/fci/direct_nosym.py +3 -3
  64. pyscf/fci/direct_spin0_symm.py +22 -43
  65. pyscf/fci/direct_spin1.py +65 -10
  66. pyscf/fci/direct_spin1_symm.py +49 -14
  67. pyscf/fci/direct_uhf.py +4 -4
  68. pyscf/fci/selected_ci_symm.py +1 -1
  69. pyscf/grad/ccsd.py +3 -7
  70. pyscf/grad/ccsd_slow.py +2 -3
  71. pyscf/grad/lagrange.py +11 -3
  72. pyscf/grad/mp2.py +13 -4
  73. pyscf/grad/sacasscf.py +1 -1
  74. pyscf/grad/tdrks.py +1 -1
  75. pyscf/grad/uccsd.py +3 -7
  76. pyscf/grad/ump2.py +2 -4
  77. pyscf/gto/basis/__init__.py +17 -4
  78. pyscf/gto/basis/bse.py +68 -15
  79. pyscf/gto/basis/def2-mtzvp.dat +4719 -0
  80. pyscf/gto/basis/def2-mtzvpp.dat +4739 -0
  81. pyscf/gto/basis/dyall-basis/__init__.py +0 -0
  82. pyscf/gto/basis/dyall-basis/dyall_2zp.py +6492 -0
  83. pyscf/gto/basis/dyall-basis/dyall_3zp.py +8343 -0
  84. pyscf/gto/basis/dyall-basis/dyall_4zp.py +10055 -0
  85. pyscf/gto/basis/dyall-basis/dyall_aae2z.py +1818 -0
  86. pyscf/gto/basis/dyall-basis/dyall_aae3z.py +2521 -0
  87. pyscf/gto/basis/dyall-basis/dyall_aae4z.py +3351 -0
  88. pyscf/gto/basis/dyall-basis/dyall_acv2z.py +1790 -0
  89. pyscf/gto/basis/dyall-basis/dyall_acv3z.py +2417 -0
  90. pyscf/gto/basis/dyall-basis/dyall_acv4z.py +3085 -0
  91. pyscf/gto/basis/dyall-basis/dyall_ae2z.py +6619 -0
  92. pyscf/gto/basis/dyall-basis/dyall_ae3z.py +9027 -0
  93. pyscf/gto/basis/dyall-basis/dyall_ae4z.py +11839 -0
  94. pyscf/gto/basis/dyall-basis/dyall_av2z.py +1742 -0
  95. pyscf/gto/basis/dyall-basis/dyall_av3z.py +2318 -0
  96. pyscf/gto/basis/dyall-basis/dyall_av4z.py +2905 -0
  97. pyscf/gto/basis/dyall-basis/dyall_cv2z.py +6558 -0
  98. pyscf/gto/basis/dyall-basis/dyall_cv3z.py +8767 -0
  99. pyscf/gto/basis/dyall-basis/dyall_cv4z.py +11098 -0
  100. pyscf/gto/basis/dyall-basis/dyall_v2z.py +6472 -0
  101. pyscf/gto/basis/dyall-basis/dyall_v3z.py +8539 -0
  102. pyscf/gto/basis/dyall-basis/dyall_v4z.py +10658 -0
  103. pyscf/gto/basis/ma-def2-qzvp.dat +5959 -0
  104. pyscf/gto/basis/ma-def2-qzvpp.dat +6195 -0
  105. pyscf/gto/basis/ma-def2-svp.dat +3504 -0
  106. pyscf/gto/basis/ma-def2-svpp.dat +3504 -0
  107. pyscf/gto/basis/ma-def2-tzvp.dat +4347 -0
  108. pyscf/gto/basis/ma-def2-tzvpp.dat +4549 -0
  109. pyscf/gto/basis/parse_cp2k.py +8 -7
  110. pyscf/gto/basis/parse_cp2k_pp.py +1 -1
  111. pyscf/gto/basis/parse_nwchem.py +26 -11
  112. pyscf/gto/basis/parse_nwchem_ecp.py +2 -1
  113. pyscf/gto/basis/sap_grasp_large.dat +2438 -0
  114. pyscf/gto/basis/sap_grasp_small.dat +1434 -0
  115. pyscf/gto/eval_gto.py +1 -1
  116. pyscf/gto/ft_ao.py +6 -6
  117. pyscf/gto/mole.py +123 -71
  118. pyscf/gto/moleintor.py +1 -1
  119. pyscf/gw/gw_ac.py +2 -2
  120. pyscf/gw/gw_cd.py +2 -2
  121. pyscf/gw/rpa.py +135 -246
  122. pyscf/gw/ugw_ac.py +2 -2
  123. pyscf/gw/urpa.py +80 -131
  124. pyscf/hessian/rhf.py +30 -128
  125. pyscf/hessian/rks.py +1 -6
  126. pyscf/hessian/uhf.py +28 -138
  127. pyscf/hessian/uks.py +1 -8
  128. pyscf/lib/CMakeLists.txt +6 -2
  129. pyscf/lib/ao2mo/nr_ao2mo.c +1 -1
  130. pyscf/lib/ao2mo/nrr_ao2mo.c +1 -1
  131. pyscf/lib/ao2mo/r_ao2mo.c +1 -1
  132. pyscf/lib/cc/ccsd_pack.c +1 -1
  133. pyscf/lib/cc/ccsd_t.c +6 -6
  134. pyscf/lib/cc/uccsd_t.c +4 -4
  135. pyscf/lib/config.h +0 -1
  136. pyscf/lib/config.h.in +0 -1
  137. pyscf/lib/deps/include/XCFun/XCFunExport.h +1 -0
  138. pyscf/lib/deps/include/xc.h +28 -18
  139. pyscf/lib/deps/include/xc_funcs.h +50 -2
  140. pyscf/lib/deps/include/xc_version.h +3 -3
  141. pyscf/lib/deps/lib/libcint.6.dylib +0 -0
  142. pyscf/lib/deps/lib/{libxc.12.dylib → libxc.15.dylib} +0 -0
  143. pyscf/lib/deps/lib/libxcfun.2.dylib +0 -0
  144. pyscf/lib/dft/grid_common.c +1 -1
  145. pyscf/lib/dft/libxc_itrf.c +10 -7
  146. pyscf/lib/dft/nr_numint_sparse.c +3 -3
  147. pyscf/lib/dft/xcfun_itrf.c +1 -1
  148. pyscf/lib/diis.py +2 -2
  149. pyscf/lib/exceptions.py +6 -0
  150. pyscf/lib/gto/fill_grids_int2c.c +11 -9
  151. pyscf/lib/gto/fill_int2e.c +7 -5
  152. pyscf/lib/gto/fill_r_4c.c +1 -1
  153. pyscf/lib/gto/ft_ao.c +1 -1
  154. pyscf/lib/gto/ft_ao.h +1 -1
  155. pyscf/lib/gto/gto.h +2 -2
  156. pyscf/lib/gto/nr_ecp.c +3 -2
  157. pyscf/lib/libagf2.dylib +0 -0
  158. pyscf/lib/libao2mo.dylib +0 -0
  159. pyscf/lib/libcc.dylib +0 -0
  160. pyscf/lib/libcgto.dylib +0 -0
  161. pyscf/lib/libcvhf.dylib +0 -0
  162. pyscf/lib/libdft.dylib +0 -0
  163. pyscf/lib/libfci.dylib +0 -0
  164. pyscf/lib/libmcscf.dylib +0 -0
  165. pyscf/lib/libmp.dylib +0 -0
  166. pyscf/lib/libnp_helper.dylib +0 -0
  167. pyscf/lib/libpbc.dylib +0 -0
  168. pyscf/lib/libri.dylib +0 -0
  169. pyscf/lib/libxc_itrf.dylib +0 -0
  170. pyscf/lib/libxcfun_itrf.dylib +0 -0
  171. pyscf/lib/linalg_helper.py +117 -198
  172. pyscf/lib/logger.py +2 -1
  173. pyscf/lib/mcscf/fci_contract.c +10 -3
  174. pyscf/lib/misc.py +63 -22
  175. pyscf/lib/mp/CMakeLists.txt +22 -0
  176. pyscf/lib/mp/mp2.c +518 -0
  177. pyscf/lib/mp/mp2.h +44 -0
  178. pyscf/lib/np_helper/CMakeLists.txt +1 -1
  179. pyscf/lib/np_helper/imatcopy.c +360 -0
  180. pyscf/lib/np_helper/np_helper.c +94 -0
  181. pyscf/lib/np_helper/np_helper.h +26 -0
  182. pyscf/lib/numpy_helper.py +195 -11
  183. pyscf/lib/pbc/nr_direct.c +2 -7
  184. pyscf/lib/pbc/nr_ecp.c +10 -3
  185. pyscf/lib/pbc/pbc.h +1 -1
  186. pyscf/lib/vhf/fblas.h +3 -0
  187. pyscf/lib/vhf/nr_sgx_direct.c +8 -6
  188. pyscf/lib/vhf/nr_sr_vhf.c +8 -12
  189. pyscf/lib/vhf/optimizer.c +2 -2
  190. pyscf/lib/vhf/rkb_screen.c +139 -0
  191. pyscf/lo/iao.py +1 -1
  192. pyscf/lo/ibo.py +3 -3
  193. pyscf/lo/pipek_jacobi.py +1 -1
  194. pyscf/mcscf/__init__.py +2 -2
  195. pyscf/mcscf/addons.py +3 -3
  196. pyscf/mcscf/apc.py +2 -2
  197. pyscf/mcscf/casci.py +13 -7
  198. pyscf/mcscf/chkfile.py +69 -41
  199. pyscf/mcscf/dmet_cas.py +2 -2
  200. pyscf/mcscf/mc1step.py +72 -44
  201. pyscf/mcscf/newton_casscf.py +5 -5
  202. pyscf/mcscf/ucasci.py +1 -1
  203. pyscf/mcscf/umc1step.py +49 -28
  204. pyscf/md/integrators.py +3 -3
  205. pyscf/mp/__init__.py +1 -0
  206. pyscf/mp/dfmp2.py +498 -59
  207. pyscf/mp/dfmp2_native.py +11 -1
  208. pyscf/mp/dfmp2_slow.py +133 -0
  209. pyscf/mp/dfump2.py +672 -0
  210. pyscf/mp/dfump2_native.py +9 -0
  211. pyscf/mp/dfump2_slow.py +161 -0
  212. pyscf/mp/gmp2.py +6 -47
  213. pyscf/mp/mp2.py +25 -10
  214. pyscf/mp/ump2.py +30 -24
  215. pyscf/pbc/adc/kadc_rhf.py +1 -1
  216. pyscf/pbc/adc/kadc_rhf_amplitudes.py +2 -2
  217. pyscf/pbc/ao2mo/eris.py +1 -1
  218. pyscf/pbc/cc/kccsd_rhf.py +3 -3
  219. pyscf/pbc/cc/kccsd_t_rhf.py +2 -2
  220. pyscf/pbc/ci/kcis_rhf.py +2 -2
  221. pyscf/pbc/df/aft.py +8 -9
  222. pyscf/pbc/df/aft_ao2mo.py +1 -1
  223. pyscf/pbc/df/df.py +85 -12
  224. pyscf/pbc/df/df_jk.py +6 -2
  225. pyscf/pbc/df/fft.py +9 -5
  226. pyscf/pbc/df/fft_ao2mo.py +4 -0
  227. pyscf/pbc/df/fft_jk.py +18 -10
  228. pyscf/pbc/df/ft_ao.py +4 -3
  229. pyscf/pbc/df/gdf_builder.py +5 -4
  230. pyscf/pbc/df/incore.py +2 -2
  231. pyscf/pbc/df/mdf.py +6 -3
  232. pyscf/pbc/df/mdf_jk.py +2 -1
  233. pyscf/pbc/df/outcore.py +10 -10
  234. pyscf/pbc/df/rsdf.py +2 -2
  235. pyscf/pbc/df/rsdf_builder.py +13 -8
  236. pyscf/pbc/df/rsdf_helper.py +6 -6
  237. pyscf/pbc/df/rsdf_jk.py +2 -1
  238. pyscf/pbc/dft/cdft.py +5 -5
  239. pyscf/pbc/dft/gen_grid.py +3 -2
  240. pyscf/pbc/dft/gks.py +14 -3
  241. pyscf/pbc/dft/kgks.py +15 -4
  242. pyscf/pbc/dft/krks.py +28 -10
  243. pyscf/pbc/dft/krks_ksymm.py +21 -9
  244. pyscf/pbc/dft/krkspu.py +1 -30
  245. pyscf/pbc/dft/krkspu_ksymm.py +0 -30
  246. pyscf/pbc/dft/kuks.py +30 -13
  247. pyscf/pbc/dft/kuks_ksymm.py +22 -10
  248. pyscf/pbc/dft/kukspu.py +0 -27
  249. pyscf/pbc/dft/kukspu_ksymm.py +0 -30
  250. pyscf/pbc/dft/multigrid/multigrid.py +36 -33
  251. pyscf/pbc/dft/multigrid/multigrid_pair.py +7 -2
  252. pyscf/pbc/dft/multigrid/pp.py +1 -1
  253. pyscf/pbc/dft/numint.py +56 -31
  254. pyscf/pbc/dft/rks.py +16 -24
  255. pyscf/pbc/dft/uks.py +21 -4
  256. pyscf/pbc/eph/eph_fd.py +1 -1
  257. pyscf/pbc/geomopt/geometric_solver.py +1 -1
  258. pyscf/pbc/gto/_pbcintor.py +1 -0
  259. pyscf/pbc/gto/cell.py +194 -23
  260. pyscf/pbc/gto/ecp.py +12 -12
  261. pyscf/pbc/gto/eval_gto.py +3 -3
  262. pyscf/pbc/gto/neighborlist.py +4 -1
  263. pyscf/pbc/gto/pseudo/pp.py +1 -1
  264. pyscf/pbc/gw/krgw_ac.py +4 -4
  265. pyscf/pbc/gw/krgw_cd.py +4 -4
  266. pyscf/pbc/gw/kugw_ac.py +3 -3
  267. pyscf/pbc/lib/kpts_helper.py +4 -3
  268. pyscf/pbc/lib/linalg_helper.py +1 -1
  269. pyscf/pbc/mp/kmp2.py +1 -1
  270. pyscf/pbc/mpitools/mpi.py +1 -1
  271. pyscf/pbc/scf/_response_functions.py +141 -34
  272. pyscf/pbc/scf/addons.py +15 -11
  273. pyscf/pbc/scf/cphf.py +1 -1
  274. pyscf/pbc/scf/ghf.py +1 -1
  275. pyscf/pbc/scf/hf.py +21 -32
  276. pyscf/pbc/scf/kghf.py +33 -29
  277. pyscf/pbc/scf/khf.py +103 -29
  278. pyscf/pbc/scf/khf_ksymm.py +15 -1
  279. pyscf/pbc/scf/krohf.py +5 -7
  280. pyscf/pbc/scf/kuhf.py +54 -23
  281. pyscf/pbc/scf/kuhf_ksymm.py +1 -1
  282. pyscf/pbc/scf/rsjk.py +14 -10
  283. pyscf/pbc/scf/scfint.py +1 -1
  284. pyscf/pbc/scf/stability.py +27 -15
  285. pyscf/pbc/scf/uhf.py +3 -1
  286. pyscf/pbc/symm/symmetry.py +2 -2
  287. pyscf/pbc/tdscf/krhf.py +238 -154
  288. pyscf/pbc/tdscf/krks.py +1 -45
  289. pyscf/pbc/tdscf/kuhf.py +319 -171
  290. pyscf/pbc/tdscf/kuks.py +0 -56
  291. pyscf/pbc/tdscf/rhf.py +116 -3
  292. pyscf/pbc/tdscf/rks.py +2 -1
  293. pyscf/pbc/tdscf/uhf.py +214 -1
  294. pyscf/pbc/tdscf/uks.py +2 -1
  295. pyscf/pbc/tools/k2gamma.py +20 -6
  296. pyscf/pbc/tools/lattice.py +3 -3
  297. pyscf/pbc/tools/pbc.py +111 -91
  298. pyscf/pbc/tools/pyscf_ase.py +0 -1
  299. pyscf/pbc/tools/pywannier90.py +1 -1
  300. pyscf/qmmm/mm_mole.py +1 -1
  301. pyscf/scf/_response_functions.py +87 -46
  302. pyscf/scf/_vhf.py +15 -10
  303. pyscf/scf/addons.py +29 -15
  304. pyscf/scf/cphf.py +14 -52
  305. pyscf/scf/dhf.py +121 -38
  306. pyscf/scf/dispersion.py +10 -9
  307. pyscf/scf/ghf.py +25 -13
  308. pyscf/scf/ghf_symm.py +2 -2
  309. pyscf/scf/hf.py +262 -30
  310. pyscf/scf/rohf.py +37 -5
  311. pyscf/scf/stability.py +142 -112
  312. pyscf/scf/ucphf.py +21 -16
  313. pyscf/scf/uhf.py +104 -61
  314. pyscf/sgx/sgx.py +1 -1
  315. pyscf/sgx/sgx_jk.py +4 -4
  316. pyscf/solvent/__init__.py +2 -2
  317. pyscf/solvent/_attach_solvent.py +2 -0
  318. pyscf/solvent/_ddcosmo_tdscf_grad.py +1 -1
  319. pyscf/solvent/cosmors.py +366 -0
  320. pyscf/solvent/ddcosmo.py +1 -1
  321. pyscf/solvent/pcm.py +4 -4
  322. pyscf/solvent/pol_embed.py +1 -1
  323. pyscf/solvent/smd.py +5 -3
  324. pyscf/soscf/ciah.py +3 -11
  325. pyscf/soscf/newton_ah.py +5 -2
  326. pyscf/symm/__init__.py +1 -1
  327. pyscf/symm/addons.py +5 -5
  328. pyscf/symm/geom.py +1 -5
  329. pyscf/tdscf/_lr_eig.py +1002 -0
  330. pyscf/tdscf/dhf.py +84 -87
  331. pyscf/tdscf/dks.py +0 -4
  332. pyscf/tdscf/ghf.py +139 -127
  333. pyscf/tdscf/gks.py +27 -25
  334. pyscf/tdscf/rhf.py +194 -147
  335. pyscf/tdscf/rks.py +26 -22
  336. pyscf/tdscf/uhf.py +166 -118
  337. pyscf/tdscf/uks.py +32 -31
  338. pyscf/tools/fcidump.py +3 -0
  339. pyscf/tools/qcschema.py +265 -0
  340. pyscf/x2c/sfx2c1e.py +1 -1
  341. pyscf/x2c/tdscf.py +41 -41
  342. pyscf/x2c/x2c.py +15 -11
  343. {pyscf-2.6.2.dist-info → pyscf-2.8.0.dist-info}/METADATA +39 -36
  344. {pyscf-2.6.2.dist-info → pyscf-2.8.0.dist-info}/NOTICE +14 -1
  345. {pyscf-2.6.2.dist-info → pyscf-2.8.0.dist-info}/RECORD +348 -316
  346. {pyscf-2.6.2.dist-info → pyscf-2.8.0.dist-info}/WHEEL +1 -1
  347. pyscf/dft/gen_libxc_param.py +0 -35
  348. pyscf/dft/gen_xcfun_param.py +0 -209
  349. pyscf/pbc/tdscf/kproxy.py +0 -189
  350. pyscf/pbc/tdscf/kproxy_supercell.py +0 -664
  351. pyscf/pbc/tdscf/krhf_slow.py +0 -300
  352. pyscf/pbc/tdscf/krhf_slow_gamma.py +0 -175
  353. pyscf/pbc/tdscf/krhf_slow_supercell.py +0 -250
  354. pyscf/pbc/tdscf/proxy.py +0 -39
  355. pyscf/pbc/tdscf/rhf_slow.py +0 -35
  356. pyscf/tdscf/common_slow.py +0 -799
  357. pyscf/tdscf/proxy.py +0 -258
  358. pyscf/tdscf/rhf_slow.py +0 -181
  359. {pyscf-2.6.2.dist-info → pyscf-2.8.0.dist-info}/LICENSE +0 -0
  360. {pyscf-2.6.2.dist-info → pyscf-2.8.0.dist-info}/top_level.txt +0 -0
@@ -1,664 +0,0 @@
1
- # Author: Artem Pulkin
2
- # flake8: noqa
3
- """
4
- This and other `proxy` modules implement the time-dependent mean-field procedure using the existing pyscf
5
- implementations as a black box. The main purpose of these modules is to overcome the existing limitations in pyscf
6
- (i.e. real-only orbitals, davidson diagonalizer, incomplete Bloch space, etc). The primary performance drawback is that,
7
- unlike the original pyscf routines with an implicit construction of the eigenvalue problem, these modules construct TD
8
- matrices explicitly by proxying to pyscf density response routines with a O(N^4) complexity scaling. As a result,
9
- regular `numpy.linalg.eig` can be used to retrieve TD roots. Several variants of proxy-TD are available:
10
-
11
- * `pyscf.tdscf.proxy`: the molecular implementation;
12
- * `pyscf.pbc.tdscf.proxy`: PBC (periodic boundary condition) Gamma-point-only implementation;
13
- * (this module) `pyscf.pbc.tdscf.kproxy_supercell`: PBC implementation constructing supercells. Works with an arbitrary number of
14
- k-points but has an overhead due to ignoring the momentum conservation law. In addition, works only with
15
- time reversal invariant (TRI) models: i.e. the k-point grid has to be aligned and contain at least one TRI momentum.
16
- * `pyscf.pbc.tdscf.kproxy`: same as the above but respect the momentum conservation and, thus, diagonlizes smaller
17
- matrices (the performance gain is the total number of k-points in the model).
18
- """
19
-
20
- # Convention for these modules:
21
- # * PhysERI is the proxying class constructing time-dependent matrices
22
- # * vector_to_amplitudes reshapes and normalizes the solution
23
- # * TDProxy provides a container
24
-
25
- from functools import reduce
26
- from pyscf.tdscf.common_slow import TDProxyMatrixBlocks, PeriodicMFMixin
27
- from pyscf.tdscf import proxy as mol_proxy
28
- from pyscf.pbc.tdscf import krhf_slow_supercell, KTDDFT, KTDHF
29
- from pyscf.lib import einsum, cartesian_prod, norm, logger
30
- from pyscf.pbc.tools.pbc import super_cell
31
-
32
- import numpy
33
- from scipy import sparse
34
-
35
- from warnings import warn
36
-
37
-
38
- def minus_k(model, threshold=None, degeneracy_threshold=None):
39
- """
40
- Retrieves an array of indexes of negative k.
41
- Args:
42
- model: a mean-field pbc model;
43
- threshold (float): a threshold for determining the negative;
44
- degeneracy_threshold (float): a threshold for assuming degeneracy;
45
-
46
- Returns:
47
- A list of integers with indexes of the corresponding k-points.
48
- """
49
- if threshold is None:
50
- threshold = 1e-8
51
- if degeneracy_threshold is None:
52
- degeneracy_threshold = 1e-6
53
- kpts = model.cell.get_scaled_kpts(model.kpts)
54
- result = []
55
- for id_k, k in enumerate(kpts):
56
- delta = norm(((kpts + k[numpy.newaxis, :]) - .5) % 1 - .5, axis=-1)
57
- i = numpy.argmin(delta)
58
- if delta[i] > threshold:
59
- raise RuntimeError("Could not find a negative k-point for k={} (ID: {:d}, best difference: {:.3e}, "
60
- "threshold: {:.3e}). Use the 'threshold' keyword to loosen the threshold or revise"
61
- "your model".format(
62
- repr(k), id_k, delta[i], threshold,
63
- ))
64
- delta = abs(model.mo_energy[id_k] - model.mo_energy[i]).max()
65
- if delta > degeneracy_threshold:
66
- raise RuntimeError("Non-symmetric band structure (time-reversal) at k={} (ID: {:d}) and k={} (ID: {:d}), "
67
- "max difference: {:.3e}, threshold: {:.3e}. This prevents composing real-valued "
68
- "orbitals. Use the 'degeneracy_threshold' keyword to loosen the threshold or revise"
69
- "your model".format(
70
- repr(k), id_k, repr(kpts[i]), i, delta, degeneracy_threshold,
71
- ))
72
- result.append(i)
73
- return result
74
-
75
-
76
- def assert_scf_converged(model, threshold=1e-7):
77
- """
78
- Tests if scf is converged.
79
- Args:
80
- model: a mean-field model to test;
81
- threshold (float): threshold for eigenvalue comparison;
82
-
83
- Returns:
84
- True if model is converged and False otherwise.
85
- """
86
- ovlp = model.get_ovlp()
87
- fock = model.get_fock(dm=model.make_rdm1())
88
- for k, (m, e, v, o) in enumerate(zip(fock, model.mo_energy, model.mo_coeff, ovlp)):
89
- delta = norm(numpy.dot(m, v) - e[numpy.newaxis, :] * numpy.dot(o, v), axis=0)
90
- nabove = (delta > threshold).sum()
91
-
92
- eye = reduce(numpy.dot, (v.conj().T, o, v))
93
- delta_o = abs(eye - numpy.eye(eye.shape[0])).max()
94
- if nabove > 0:
95
- warn("{:d} vectors at k={:d} are not converged, max difference: {:.3e}; orthogonality error: {:.3e} "
96
- "warning threshold: {:.3e}".format(
97
- nabove, k, max(delta), delta_o, threshold,
98
- ))
99
-
100
-
101
- def sparse_transform(m, *args):
102
- """
103
- Performs a sparse transform of a dense tensor.
104
- Args:
105
- m (ndarray): a tensor to transform;
106
- *args: alternating indexes and bases to transform into;
107
-
108
- Returns:
109
- The transformed tensor.
110
- """
111
- result = m
112
- for i, (index, basis) in enumerate(zip(args[::2], args[1::2])):
113
-
114
- if len(basis.shape) != 2:
115
- raise ValueError("Transform {:d} is not a matrix: shape = {}".format(
116
- i, repr(basis.shape)
117
- ))
118
- if result.shape[index] != basis.shape[0]:
119
- raise ValueError("Dimension mismatch of transform {:d}: m.shape[{:d}] = {:d} != basis.shape[0] = {:d}".format(
120
- i, index, result.shape[index], basis.shape[0],
121
- ))
122
- if "getcol" not in dir(basis):
123
- raise ValueError("No 'getcol' in the transform matrix {:d}: not a CSC sparse matrix?")
124
-
125
- result_shape = result.shape[:index] + (basis.shape[1],) + result.shape[index + 1:]
126
- new_result = numpy.zeros(result_shape, numpy.common_type(*(
127
- args[1::2] + (m,)
128
- )))
129
- for b2 in range(basis.shape[1]):
130
- slice_b2 = (slice(None),) * index + (b2,)
131
- col = basis.getcol(b2)
132
- for b1 in col.nonzero()[0]:
133
- slice_b1 = (slice(None),) * index + (b1,)
134
- new_result[slice_b2] += col[b1, 0] * result[slice_b1]
135
- result = new_result
136
-
137
- return result
138
-
139
-
140
- def k2s(model, grid_spec, mf_constructor, threshold=None, degeneracy_threshold=None, imaginary_threshold=None):
141
- """
142
- Converts k-point model into a supercell with real orbitals.
143
- Args:
144
- model: a mean-field pbc model;
145
- grid_spec (Iterable): integer dimensions of the k-grid in the mean-field model;
146
- mf_constructor (Callable): a function constructing the mean-field object;
147
- threshold (float): a threshold for determining the negative k-point index;
148
- degeneracy_threshold (float): a threshold for assuming degeneracy when composing real-valued orbitals;
149
- imaginary_threshold (float): a threshold for asserting real-valued supercell orbitals;
150
-
151
- Returns:
152
- The same class where the Cell object was replaced by the supercell and all fields were adjusted accordingly.
153
- """
154
- # This hack works as follows. Provided TRS Hamiltonian
155
- # H(k) = H(-k)*,
156
- # with same real eigenvalues and eigenfunctions related as
157
- # psi(k) = c psi(-k)*,
158
- # c - arbitrary phase, it is easy to construct real (non-Bloch) eigenvectors of the whole Hamiltonian
159
- # real1(|k|) = c* psi(k) + psi(-k) = psi(-k)* + psi(-k)
160
- # and
161
- # real2(|k|) = 1.j * (c* psi(k) - psi(-k)) = 1.j* (psi(-k)* - psi(-k)).
162
- # The coefficient c is determined as
163
- # psi(k) * psi(-k) = c psi(-k)* * psi(-k) = c
164
- if imaginary_threshold is None:
165
- imaginary_threshold = 1e-7
166
-
167
- mk = minus_k(model, threshold=threshold, degeneracy_threshold=degeneracy_threshold)
168
-
169
- # Fix phases
170
- ovlp = model.get_ovlp()
171
- phases = {}
172
- for k1, k2 in enumerate(mk):
173
- if k1 <= k2:
174
- c1 = model.mo_coeff[k1]
175
- c2 = model.mo_coeff[k2]
176
- o = ovlp[k1]
177
- r = reduce(numpy.dot, (c2.T, o, c1))
178
- delta = abs(abs(r) - numpy.eye(r.shape[0])).max()
179
- if delta > imaginary_threshold:
180
- raise RuntimeError("K-points connected by time reversal {:d} and {:d} are not complex conjugate: "
181
- "the difference {:.3e} is larger than the threshold {:.3e}".format(
182
- k1, k2, delta, imaginary_threshold,
183
- ))
184
- p = numpy.angle(numpy.diag(r))
185
- if k1 == k2:
186
- phases[k1] = numpy.exp(- .5j * p)[numpy.newaxis, :]
187
- else:
188
- phases[k1] = numpy.exp(- 1.j * p)[numpy.newaxis, :]
189
-
190
- nk = len(model.kpts)
191
- t_vecs = cartesian_prod(tuple(numpy.arange(i) for i in grid_spec))
192
- kpts_frac = model.cell.get_scaled_kpts(model.kpts)
193
-
194
- result = mf_constructor(super_cell(model.cell, grid_spec))
195
- result_ovlp = result.get_ovlp()[0]
196
-
197
- moe = numpy.concatenate(model.mo_energy)
198
- moo = numpy.concatenate(model.mo_occ)
199
-
200
- # Complex-valued wf in a supercell
201
- moc = []
202
- for mo_coeff, k in zip(model.mo_coeff, kpts_frac):
203
- psi = (
204
- mo_coeff[numpy.newaxis, ...] * numpy.exp(2.j * numpy.pi * t_vecs.dot(k))[:, numpy.newaxis, numpy.newaxis]
205
- ).reshape(-1, mo_coeff.shape[1])
206
- norms = einsum("ai,ab,bi->i", psi.conj(), result_ovlp, psi) ** .5
207
- psi /= norms[numpy.newaxis, :]
208
- moc.append(psi)
209
- moc = numpy.concatenate(moc, axis=1)
210
-
211
- rotation_matrix = sparse.dok_matrix(moc.shape, dtype=moc.dtype)
212
- inv_rotation_matrix = sparse.dok_matrix(moc.shape, dtype=moc.dtype)
213
- nvecs = (0,) + tuple(i.shape[1] for i in model.mo_coeff)
214
- nvecs = numpy.cumsum(nvecs)
215
- k_spaces = tuple(numpy.arange(i, j) for i, j in zip(nvecs[:-1], nvecs[1:]))
216
-
217
- for k in range(nk):
218
-
219
- i = k_spaces[k]
220
- j = k_spaces[mk[k]]
221
-
222
- if k == mk[k]:
223
- rotation_matrix[i, i] = phases[k]
224
- inv_rotation_matrix[i, i] = phases[k].conj()
225
-
226
- elif k < mk[k]:
227
- rotation_matrix[i, i] = .5**.5 * phases[k]
228
- rotation_matrix[j, i] = .5**.5
229
- rotation_matrix[i, j] = -1.j * .5**.5 * phases[k]
230
- rotation_matrix[j, j] = 1.j * .5**.5
231
-
232
- inv_rotation_matrix[i, i] = .5**.5 * phases[k].conj()
233
- inv_rotation_matrix[j, i] = 1.j * .5**.5 * phases[k].conj()
234
- inv_rotation_matrix[i, j] = .5**.5
235
- inv_rotation_matrix[j, j] = -1.j * .5**.5
236
-
237
- else:
238
- pass
239
-
240
- rotation_matrix = rotation_matrix.tocsc()
241
- inv_rotation_matrix = inv_rotation_matrix.tocsc()
242
-
243
- moc = sparse_transform(moc, 1, rotation_matrix)
244
- max_imag = abs(moc.imag).max()
245
- if max_imag > imaginary_threshold:
246
- raise RuntimeError("Failed to compose real-valued orbitals: imaginary part is {:.3e}".format(max_imag))
247
- moc = moc.real
248
-
249
- mok = numpy.concatenate(tuple([i] * len(j) for i, j in enumerate(model.mo_energy)))
250
- moi = numpy.concatenate(tuple(numpy.arange(len(j)) for j in model.mo_energy))
251
-
252
- order = numpy.argsort(moe)
253
-
254
- moe = moe[order]
255
- moc = moc[:, order]
256
- moo = moo[order]
257
- mok = mok[order]
258
- moi = moi[order]
259
- rotation_matrix = rotation_matrix[:, order]
260
- inv_rotation_matrix = inv_rotation_matrix[order, :]
261
-
262
- result.mo_occ = moo,
263
- result.mo_energy = moe,
264
- result.mo_coeff = moc,
265
- result.supercell_rotation = rotation_matrix
266
- result.supercell_inv_rotation = inv_rotation_matrix
267
- result.supercell_orig_k = mok
268
- result.supercell_orig_i = moi
269
-
270
- assert_scf_converged(result, model.conv_tol ** .5)
271
-
272
- p1 = abs(result.supercell_rotation.dot(result.supercell_inv_rotation) - numpy.eye(rotation_matrix.shape[0])).max()
273
- p2 = abs(result.supercell_inv_rotation.dot(result.supercell_rotation) - numpy.eye(rotation_matrix.shape[0])).max()
274
- if p1 > 1e-14 or p2 > 1e-14:
275
- raise RuntimeError("Rotation matrix error: {:.3e}, {:.3e}".format(p1, p2))
276
-
277
- return result
278
-
279
-
280
- def ko_mask(nocc, nmo):
281
- """
282
- Prepares a mask of an occupied space.
283
- Args:
284
- nocc (Iterable): occupation numbers per k-point;
285
- nmo (Iterable): numbers of orbitals per k-point;
286
-
287
- Returns:
288
- The mask where `True` denotes occupied orbitals. Basis order: [k, orb=o+v]
289
- """
290
- result = numpy.zeros(sum(nmo), dtype=bool)
291
- offset = 0
292
- for no, nm in zip(nocc, nmo):
293
- result[offset:offset+no] = True
294
- offset += nm
295
- return result
296
-
297
-
298
- def split_transform(transform, nocc, nmo, tolerance=1e-14):
299
- """
300
- Splits the transform into `oo` and `vv` blocks.
301
- Args:
302
- transform (numpy.ndarray): the original transform. The basis order for the transform is [real orb=o+v; k, orb=o+v];
303
- nocc (Iterable): occupation numbers per k-point;
304
- nmo (Iterable): the number of orbitals per k-point;
305
- tolerance (float): tolerance to check zeros at the `ov` block;
306
-
307
- Returns:
308
- `oo` and `vv` blocks of the transform.
309
- """
310
- o_mask = ko_mask(nocc, nmo)
311
- v_mask = ~o_mask
312
- ov = transform[:sum(nocc), v_mask]
313
- vo = transform[sum(nocc):, o_mask]
314
- if abs(ov).max() > tolerance or abs(vo).max() > tolerance:
315
- raise ValueError("Occupied and virtual spaces are coupled by the transformation")
316
- return transform[:sum(nocc), o_mask], transform[sum(nocc):, v_mask]
317
-
318
-
319
- def supercell_space_required(transform_oo, transform_vv, final_space):
320
- """
321
- For a given orbital transformation and a given `ov` mask in the transformed space, calculates a minimal `ov` mask
322
- in the original space required to achieve this transform.
323
- Args:
324
- transform_oo (ndarray): the transformation in the occupied space;
325
- transform_vv (ndarray): the transformation in the virtual space;
326
- final_space (ndarray): the final `ov` space. Basis order: [k_o, o, k_v, v];
327
-
328
- Returns:
329
- The initial active space. Basis order: [k_o, o, k_v, v].
330
- """
331
- final_space = numpy.asanyarray(final_space)
332
- final_space = final_space.reshape(final_space.shape[:-1] + (transform_oo.shape[1], transform_vv.shape[1]))
333
- result = einsum(
334
- "ao,bv,...ov->...ab",
335
- (transform_oo.toarray() != 0).astype(int),
336
- (transform_vv.toarray() != 0).astype(int),
337
- final_space.astype(int),
338
- ) != 0
339
- return result.reshape(result.shape[:-2] + (-1,))
340
-
341
-
342
- def get_sparse_ov_transform(oo, vv):
343
- """
344
- Retrieves a sparse `ovov` transform out of sparse `oo` and `vv` transforms.
345
- Args:
346
- oo (ndarray): the transformation in the occupied space;
347
- vv (ndarray): the transformation in the virtual space;
348
-
349
- Returns:
350
- The resulting matrix representing the sparse transform in the `ov` space.
351
- """
352
- i, a = oo.shape
353
- j, b = vv.shape
354
-
355
- # If the input is dense the result is simply
356
- # return (oo[:, numpy.newaxis, :, numpy.newaxis] * vv[numpy.newaxis, :, numpy.newaxis, :]).reshape(i*j, a*b)
357
-
358
- result_data = numpy.zeros(oo.nnz * vv.nnz, dtype=numpy.common_type(oo, vv))
359
- result_indices = numpy.zeros(len(result_data), dtype=int)
360
- result_indptr = numpy.zeros(a * b + 1, dtype=int)
361
-
362
- ptr_counter = 0
363
- for i_a in range(a):
364
- oo_col = oo.getcol(i_a)
365
- assert tuple(oo_col.indptr.tolist()) == (0, len(oo_col.data))
366
- i_i, oo_col_v = oo_col.indices, oo_col.data
367
- for i_b in range(b):
368
- vv_col = vv.getcol(i_b)
369
- assert tuple(vv_col.indptr.tolist()) == (0, len(vv_col.data))
370
- i_j, vv_col_v = vv_col.indices, vv_col.data
371
-
372
- data_length = len(i_i) * len(i_j)
373
- result_indices[ptr_counter:ptr_counter + data_length] = ((i_i * j)[:, numpy.newaxis] + i_j[numpy.newaxis, :]).reshape(-1)
374
- result_data[ptr_counter:ptr_counter + data_length] = (oo_col_v[:, numpy.newaxis] * vv_col_v[numpy.newaxis, :]).reshape(-1)
375
- result_indptr[i_a * b + i_b] = ptr_counter
376
-
377
- ptr_counter += data_length
378
-
379
- result_indptr[-1] = ptr_counter
380
- return sparse.csc_matrix((result_data, result_indices, result_indptr))
381
-
382
-
383
- def ov2orb(space, nocc, nmo):
384
- """
385
- Converts ov-pairs active space specification into orbital space spec.
386
- Args:
387
- space (ndarray): the ov space. Basis order: [k_o, o, k_v, v];
388
- nocc (Iterable): the numbers of occupied orbitals per k-point;
389
- nmo (Iterable): the total numbers of orbitals per k-point;
390
-
391
- Returns:
392
- The orbital space specification. Basis order: [k, orb=o+v].
393
- """
394
- nocc = numpy.asanyarray(nocc)
395
- nmo = numpy.asanyarray(nmo)
396
- nvirt = nmo - nocc
397
-
398
- space = numpy.asanyarray(space)
399
- space = space.reshape(space.shape[:-1] + (sum(nocc), sum(nvirt))) # [k_o, o; k_v, v]
400
-
401
- s_o = numpy.any(space, axis=-1) # [k_o, o]
402
- s_v = numpy.any(space, axis=-2) # [k_v, v]
403
-
404
- o_offset = numpy.cumsum(numpy.concatenate(([0], nocc)))
405
- v_offset = numpy.cumsum(numpy.concatenate(([0], nvirt)))
406
- result = []
407
- for o_fr, o_to, v_fr, v_to in zip(o_offset[:-1], o_offset[1:], v_offset[:-1], v_offset[1:]):
408
- result.append(s_o[..., o_fr:o_to])
409
- result.append(s_v[..., v_fr:v_to])
410
- return numpy.concatenate(result, axis=-1) # [k, orb=o+v]
411
-
412
-
413
- def supercell_response_ov(vind, space_ov, nocc, nmo, double, rot_bloch, log_dest):
414
- """
415
- Retrieves a raw response matrix.
416
- Args:
417
- vind (Callable): a pyscf matvec routine;
418
- space_ov (ndarray): the active `ov` space mask: either the same mask for both rows and columns (1D array) or
419
- separate `ov` masks for rows and columns (2D array). Basis order: [k_o, o, k_v, v];
420
- nocc (ndarray): the numbers of occupied orbitals (frozen and active) per k-point;
421
- nmo (ndarray): the total number of orbitals per k-point;
422
- double (bool): set to True if `vind` returns the double-sized (i.e. full) matrix;
423
- rot_bloch (ndarray): a matrix specifying the rotation from real orbitals returned from pyscf to Bloch
424
- functions;
425
- log_dest (object): pyscf logging;
426
-
427
- Returns:
428
- The TD matrix.
429
- """
430
- if not double:
431
- raise NotImplementedError("Not implemented for MK-type matrixes")
432
-
433
- nocc_full = sum(nocc)
434
- nmo_full = sum(nmo)
435
- nvirt_full = nmo_full - nocc_full
436
- size_full = nocc_full * nvirt_full
437
-
438
- space_ov = numpy.array(space_ov)
439
-
440
- if space_ov.shape == (size_full,):
441
- space_ov = numpy.repeat(space_ov[numpy.newaxis, :], 2, axis=0)
442
-
443
- elif space_ov.shape != (2, size_full):
444
- raise ValueError(
445
- "The 'space_ov' argument should be a 1D array with dimension {size_full:d} or a 2D array with"
446
- " dimensions 2x{size_full:d}, found: {actual}".format(
447
- size_full=size_full,
448
- actual=space_ov.shape,
449
- ))
450
-
451
- oo, vv = split_transform(rot_bloch, nocc, nmo)
452
- space_real_ov = supercell_space_required(oo, vv, space_ov)
453
-
454
- logger.debug1(log_dest, "Performing a supercell proxy response calculation ...")
455
- logger.debug1(log_dest, " Total ov space size: {:d} requested elements: {} real elements to calculate: {}".format(
456
- size_full,
457
- "x".join(map(str, space_ov.sum(axis=-1))),
458
- "x".join(map(str, space_real_ov.sum(axis=-1))),
459
- ))
460
-
461
- logger.debug1(log_dest, " collecting the A, B matrices ...")
462
- response_real_a, response_real_b = mol_proxy.molecular_response_ov(
463
- vind,
464
- space_real_ov,
465
- nocc_full,
466
- nmo_full,
467
- double,
468
- log_dest,
469
- )
470
- logger.debug1(log_dest, " done, shapes: {} and {}".format(
471
- response_real_a.shape,
472
- response_real_b.shape,
473
- ))
474
-
475
- logger.debug1(log_dest, "Transforming into Bloch basis ...")
476
-
477
- ovov_nc = get_sparse_ov_transform(oo, vv.conj())
478
- ovov_cn = get_sparse_ov_transform(oo.conj(), vv)
479
-
480
- ovov_row = ovov_nc[:, space_ov[0]][space_real_ov[0]]
481
- ovov_col_a = ovov_cn[:, space_ov[1]][space_real_ov[1]]
482
- ovov_col_b = ovov_nc[:, space_ov[1]][space_real_ov[1]]
483
-
484
- # Rotate
485
- logger.debug1(log_dest, " rotating A ...")
486
- response_bloch_a = sparse_transform(response_real_a, 0, ovov_row, 1, ovov_col_a)
487
- logger.debug1(log_dest, " rotating B ...")
488
- response_bloch_b = sparse_transform(response_real_b, 0, ovov_row, 1, ovov_col_b)
489
- logger.debug1(log_dest, " shapes: {} and {}".format(response_bloch_a.shape, response_bloch_b.shape))
490
-
491
- return response_bloch_a, response_bloch_b
492
-
493
-
494
- def orb2ov(space, nocc, nmo):
495
- """
496
- Converts orbital active space specification into ov-pairs space spec.
497
- Args:
498
- space (ndarray): the obital space. Basis order: [k, orb=o+v];
499
- nocc (Iterable): the numbers of occupied orbitals per k-point;
500
- nmo (Iterable): the total numbers of orbitals per k-point;
501
-
502
- Returns:
503
- The ov space specification. Basis order: [k_o, o, k_v, v].
504
- """
505
- space = numpy.asanyarray(space)
506
- m = ko_mask(nocc, nmo) # [k, orb=o+v]
507
- o = space[..., m] # [k, o]
508
- v = space[..., ~m] # [k, v]
509
- return (o[..., numpy.newaxis] * v[..., numpy.newaxis, :]).reshape(space.shape[:-1] + (-1,)) # [k_o, o, k_v, v]
510
-
511
-
512
- def supercell_response(vind, space, nocc, nmo, double, rot_bloch, log_dest):
513
- """
514
- Retrieves a raw response matrix.
515
- Args:
516
- vind (Callable): a pyscf matvec routine;
517
- space (ndarray): the active space: either for both rows and columns (1D array) or for rows and columns
518
- separately (2D array). Basis order: [k, orb=o+v];
519
- nocc (ndarray): the numbers of occupied orbitals (frozen and active) per k-point;
520
- nmo (ndarray): the total number of orbitals per k-point;
521
- double (bool): set to True if `vind` returns the double-sized (i.e. full) matrix;
522
- rot_bloch (ndarray): a matrix specifying the rotation from real orbitals returned from pyscf to Bloch
523
- functions;
524
- log_dest (object): pyscf logging;
525
-
526
- Returns:
527
- The TD matrix.
528
- """
529
- if not double:
530
- raise NotImplementedError("Not implemented for MK-type matrixes")
531
-
532
- # Full space dims
533
- nmo_full = sum(nmo)
534
- space = numpy.array(space)
535
-
536
- if space.shape == (nmo_full,):
537
- space = numpy.repeat(space[numpy.newaxis, :], 2, axis=0)
538
- elif space.shape != (2, nmo_full):
539
- raise ValueError("The 'space' argument should a 1D array with dimension {:d} or a 2D array with dimensions {},"
540
- " found: {}".format(nmo_full, (2, nmo_full), space.shape))
541
-
542
- return supercell_response_ov(vind, orb2ov(space, nocc, nmo), nocc, nmo, double, rot_bloch, log_dest)
543
-
544
-
545
- class PhysERI(PeriodicMFMixin, TDProxyMatrixBlocks):
546
- proxy_choices = {
547
- "hf": KTDHF,
548
- "dft": KTDDFT,
549
- }
550
-
551
- def __init__(self, model, proxy, x, mf_constructor, frozen=None, **kwargs):
552
- """
553
- A proxy class for calculating TD matrix blocks (supercell version).
554
-
555
- Args:
556
- model: the base model with a time reversal-invariant k-point grid;
557
- proxy: a pyscf proxy with TD response function, one of 'hf', 'dft';
558
- x (Iterable): the original k-grid dimensions (numbers of k-points per each axis);
559
- mf_constructor (Callable): a function constructing the mean-field object;
560
- frozen (int, Iterable): the number of frozen valence orbitals or the list of frozen orbitals;
561
- **kwargs: arguments to `k2s` function constructing supercells;
562
- """
563
- model_super = k2s(model, x, mf_constructor, **kwargs)
564
- TDProxyMatrixBlocks.__init__(self, self.proxy_choices[proxy](model_super))
565
- PeriodicMFMixin.__init__(self, model, frozen=frozen)
566
- self.model_super = model_super
567
-
568
- def proxy_is_double(self):
569
- """
570
- Determines if double-sized matrices are proxied.
571
- Returns:
572
- True if double-sized matrices are proxied.
573
- """
574
- nocc_full = sum(self.nocc_full)
575
- nmo_full = sum(self.nmo_full)
576
- size_full = nocc_full * (nmo_full - nocc_full)
577
- size_hdiag = len(self.proxy_diag)
578
-
579
- if size_full == size_hdiag:
580
- return False
581
-
582
- elif 2 * size_full == size_hdiag:
583
- return True
584
-
585
- else:
586
- raise RuntimeError("Do not recognize the size of TD diagonal: {:d}. The size of ov-space is {:d}".format(
587
- size_hdiag, size_full
588
- ))
589
-
590
- def proxy_response(self):
591
- """
592
- A raw response matrix.
593
- Returns:
594
- A raw response matrix.
595
- """
596
- return supercell_response(
597
- self.proxy_vind,
598
- numpy.concatenate(self.space),
599
- self.nocc_full,
600
- self.nmo_full,
601
- self.proxy_is_double(),
602
- self.model_super.supercell_inv_rotation,
603
- self.model,
604
- )
605
-
606
- def tdhf_primary_form(self, *args, **kwargs):
607
- """
608
- A primary form of TD matrixes.
609
-
610
- Returns:
611
- Output type: "full", "ab", or "mk" and the corresponding matrix(es).
612
- """
613
- a, b = self.proxy_response()
614
-
615
- # Transform into supercell convention: [k_o, o, k_v, v] -> [k_o, k_v, o, v]
616
- nocc_k = self.nocc[0]
617
- nk = len(self.nocc)
618
- nvirt_k = self.nmo[0] - self.nocc[0]
619
- size = nk * nk * nocc_k * nvirt_k
620
-
621
- a = a.reshape((nk, nocc_k, nk, nvirt_k) * 2).transpose(0, 2, 1, 3, 4, 6, 5, 7)
622
- b = b.reshape((nk, nocc_k, nk, nvirt_k) * 2).transpose(0, 2, 1, 3, 4, 6, 5, 7)
623
- return "ab", a.reshape(size, size), b.reshape(size, size)
624
-
625
-
626
- vector_to_amplitudes = krhf_slow_supercell.vector_to_amplitudes
627
-
628
-
629
- class TDProxy(mol_proxy.TDProxy):
630
- v2a = staticmethod(vector_to_amplitudes)
631
- proxy_eri = PhysERI
632
-
633
- def __init__(self, mf, proxy, x, mf_constructor, frozen=None, **kwargs):
634
- """
635
- Performs TD calculation. Roots and eigenvectors are stored in `self.e`, `self.xy`.
636
- Args:
637
- mf: the base model with a time reversal-invariant k-point grid;
638
- proxy: a pyscf proxy with TD response function, one of 'hf', 'dft';
639
- x (Iterable): the original k-grid dimensions (numbers of k-points per each axis);
640
- mf_constructor (Callable): a function constructing the mean-field object;
641
- frozen (int, Iterable): the number of frozen valence orbitals or the list of frozen orbitals;
642
- **kwargs: arguments to `k2s` function constructing supercells;
643
- """
644
- super(TDProxy, self).__init__(mf, proxy, frozen=frozen)
645
- self.fast = False
646
- self.x = x
647
- self.mf_constructor = mf_constructor
648
- self.__k2s_kwargs__ = kwargs
649
-
650
- def ao2mo(self):
651
- """
652
- Prepares ERI.
653
-
654
- Returns:
655
- A suitable ERI.
656
- """
657
- return self.proxy_eri(
658
- self._scf,
659
- self.__proxy__,
660
- x=self.x,
661
- mf_constructor=self.mf_constructor,
662
- frozen=self.frozen,
663
- **self.__k2s_kwargs__
664
- )