gpu4pyscf 0.6.2__tar.gz → 0.6.3__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 (68) hide show
  1. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/MANIFEST.in +2 -1
  2. {gpu4pyscf-0.6.2/gpu4pyscf.egg-info → gpu4pyscf-0.6.3}/PKG-INFO +1 -1
  3. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/__init__.py +1 -1
  4. gpu4pyscf-0.6.3/gpu4pyscf/df/__init__.py +15 -0
  5. gpu4pyscf-0.6.3/gpu4pyscf/df/cderi.py +80 -0
  6. gpu4pyscf-0.6.3/gpu4pyscf/df/df.py +283 -0
  7. gpu4pyscf-0.6.3/gpu4pyscf/df/df_jk.py +390 -0
  8. gpu4pyscf-0.6.3/gpu4pyscf/df/grad/__init__.py +19 -0
  9. gpu4pyscf-0.6.3/gpu4pyscf/df/grad/rhf.py +255 -0
  10. gpu4pyscf-0.6.3/gpu4pyscf/df/grad/rks.py +137 -0
  11. gpu4pyscf-0.6.3/gpu4pyscf/df/hessian/__init__.py +19 -0
  12. gpu4pyscf-0.6.3/gpu4pyscf/df/hessian/rhf.py +517 -0
  13. gpu4pyscf-0.6.3/gpu4pyscf/df/hessian/rks.py +129 -0
  14. gpu4pyscf-0.6.3/gpu4pyscf/df/int3c2e.py +1439 -0
  15. gpu4pyscf-0.6.3/gpu4pyscf/df/patch_pyscf.py +29 -0
  16. gpu4pyscf-0.6.3/gpu4pyscf/gto/__init__.py +14 -0
  17. gpu4pyscf-0.6.3/gpu4pyscf/gto/mole.py +30 -0
  18. gpu4pyscf-0.6.3/gpu4pyscf/lib/__init__.py +20 -0
  19. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3/gpu4pyscf.egg-info}/PKG-INFO +1 -1
  20. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf.egg-info/SOURCES.txt +14 -0
  21. gpu4pyscf-0.6.2/gpu4pyscf/lib/__init__.py +0 -5
  22. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/LICENSE +0 -0
  23. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/README.md +0 -0
  24. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/__config__.py +0 -0
  25. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/__init__.py +0 -0
  26. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/gen_grid.py +0 -0
  27. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/gks.py +0 -0
  28. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/libxc.py +0 -0
  29. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/numint.py +0 -0
  30. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/patch_pyscf.py +0 -0
  31. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/radi.py +0 -0
  32. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/rks.py +0 -0
  33. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/roks.py +0 -0
  34. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/uks.py +0 -0
  35. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/xc_alias.py +0 -0
  36. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/xc_deriv.py +0 -0
  37. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/grad/__init__.py +0 -0
  38. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/grad/patch_pyscf.py +0 -0
  39. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/grad/rhf.py +0 -0
  40. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/grad/rks.py +0 -0
  41. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/hessian/__init__.py +0 -0
  42. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/hessian/rhf.py +0 -0
  43. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/hessian/rks.py +0 -0
  44. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/lib/cublas.py +0 -0
  45. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/lib/cupy_helper.py +0 -0
  46. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/lib/cusolver.py +0 -0
  47. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/lib/cutensor.py +0 -0
  48. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/lib/diis.py +0 -0
  49. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/lib/logger.py +0 -0
  50. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/lib/utils.py +0 -0
  51. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/patch_pyscf.py +0 -0
  52. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/scf/__init__.py +0 -0
  53. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/scf/cphf.py +0 -0
  54. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/scf/diis.py +0 -0
  55. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/scf/ghf.py +0 -0
  56. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/scf/hf.py +0 -0
  57. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/scf/int4c2e.py +0 -0
  58. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/scf/patch_pyscf.py +0 -0
  59. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/scf/rohf.py +0 -0
  60. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/scf/uhf.py +0 -0
  61. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/solvent/__init__.py +0 -0
  62. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/solvent/_attach_solvent.py +0 -0
  63. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/solvent/pcm.py +0 -0
  64. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf.egg-info/dependency_links.txt +0 -0
  65. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf.egg-info/requires.txt +0 -0
  66. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf.egg-info/top_level.txt +0 -0
  67. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/setup.cfg +0 -0
  68. {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/setup.py +0 -0
@@ -2,13 +2,14 @@ include MANIFEST.in
2
2
  include README.md setup.py CHANGELOG AUTHORS LICENSE NOTICE
3
3
 
4
4
  global-exclude *.py[cod]
5
+ global-exclude *~
5
6
  #global-exclude *.cu
6
7
  #global-exclude *.h
7
8
  #global-exclude *.c
8
9
  #global-exclude *.cuh
9
10
  #global-exclude *.sh
10
11
 
11
- prune */__pycache__
12
+ prune */__pycache__
12
13
  recursive-exclude */__pycache__ *
13
14
 
14
15
  prune gpu4pyscf/lib/build
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: gpu4pyscf
3
- Version: 0.6.2
3
+ Version: 0.6.3
4
4
  Summary: GPU extensions for PySCF
5
5
  Home-page: UNKNOWN
6
6
  Author: Qiming Sun
@@ -1,2 +1,2 @@
1
1
  from . import lib, grad, hessian, solvent, scf, dft
2
- __version__ = '0.6.2'
2
+ __version__ = '0.6.3'
@@ -0,0 +1,15 @@
1
+ # Copyright 2023 The GPU4PySCF Authors. All Rights Reserved.
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
@@ -0,0 +1,80 @@
1
+ # Copyright 2023 The GPU4PySCF Authors. All Rights Reserved.
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ import numpy as np
17
+ import cupy
18
+ import ctypes
19
+ from gpu4pyscf.lib.cupy_helper import load_library
20
+
21
+ libcupy_helper = load_library('libcupy_helper')
22
+
23
+ class CDERI_POINTER(ctypes.Structure):
24
+ pass
25
+
26
+ class CDERI():
27
+ """
28
+ CDERI object with sparsity in ij direction
29
+ """
30
+ def __init__(self, nao, naux, nblocks) -> None:
31
+ cderi_ptr = ctypes.POINTER(CDERI_POINTER)()
32
+ self.handle = cderi_ptr
33
+ self.nao = nao
34
+ self.naux = naux
35
+ self.row = []
36
+ self.col = []
37
+ self.data = []
38
+ libcupy_helper.init_cderi(
39
+ ctypes.byref(cderi_ptr),
40
+ ctypes.c_int(nblocks),
41
+ ctypes.c_int(nao))
42
+ return
43
+
44
+ def __del__(self):
45
+ self.row = []
46
+ self.col = []
47
+ self.data = []
48
+ libcupy_helper.delete_cderi(ctypes.byref(self.handle))
49
+
50
+ def add_block(self, data, rows, cols):
51
+ self.row.append(rows)
52
+ self.col.append(cols)
53
+ self.data.append(data)
54
+
55
+ rows = cupy.asarray(rows, dtype=cupy.int64)
56
+ cols = cupy.asarray(cols, dtype=cupy.int64)
57
+ assert rows.dtype == cupy.int64 and cols.dtype == cupy.int64
58
+ nij = len(rows)
59
+ err = libcupy_helper.add_block(
60
+ ctypes.byref(self.handle),
61
+ ctypes.c_int(nij),
62
+ ctypes.c_int(self.naux),
63
+ ctypes.cast(rows.data.ptr, ctypes.c_void_p),
64
+ ctypes.cast(cols.data.ptr, ctypes.c_void_p),
65
+ ctypes.cast(data.data.ptr, ctypes.c_void_p))
66
+ if err != 0:
67
+ raise RuntimeError('failed to add the block')
68
+ return
69
+
70
+ def unpack(self, p0, p1, out=None):
71
+ if out is None: out = cupy.zeros([p1-p0, self.nao, self.nao])
72
+
73
+ libcupy_helper.unpack(
74
+ ctypes.byref(self.handle),
75
+ ctypes.c_int(p0),
76
+ ctypes.c_int(p1),
77
+ ctypes.cast(out.data.ptr, ctypes.c_void_p)
78
+ )
79
+ return out
80
+
@@ -0,0 +1,283 @@
1
+ # Copyright 2023 The GPU4PySCF Authors. All Rights Reserved.
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+
17
+ import copy
18
+ import cupy
19
+ import ctypes
20
+ import numpy as np
21
+ from cupyx.scipy.linalg import solve_triangular
22
+ from pyscf import lib
23
+ from pyscf.df import df, addons
24
+ from gpu4pyscf.lib.cupy_helper import (
25
+ cholesky, tag_array, get_avail_mem, cart2sph)
26
+ from gpu4pyscf.df import int3c2e, df_jk
27
+ from gpu4pyscf.lib import logger
28
+ from gpu4pyscf import __config__
29
+ from cupyx import scipy
30
+
31
+ MIN_BLK_SIZE = getattr(__config__, 'min_ao_blksize', 128)
32
+ ALIGNED = getattr(__config__, 'ao_aligned', 32)
33
+ LINEAR_DEP_TOL = 1e-7
34
+
35
+ class DF(df.DF):
36
+ from gpu4pyscf.lib.utils import to_gpu, device
37
+
38
+ def __init__(self, mol, auxbasis=None):
39
+ super().__init__(mol, auxbasis)
40
+ self.auxmol = None
41
+ self.intopt = None
42
+ self.nao = None
43
+ self.naux = None
44
+ self.cd_low = None
45
+ self._cderi = None
46
+
47
+ def to_cpu(self):
48
+ from gpu4pyscf.lib.utils import to_cpu
49
+ obj = to_cpu(self)
50
+ return obj.reset()
51
+
52
+ def build(self, direct_scf_tol=1e-14, omega=None):
53
+ mol = self.mol
54
+ auxmol = self.auxmol
55
+ self.nao = mol.nao
56
+
57
+ # cache indices for better performance
58
+ nao = mol.nao
59
+ tril_row, tril_col = cupy.tril_indices(nao)
60
+ tril_row = cupy.asarray(tril_row)
61
+ tril_col = cupy.asarray(tril_col)
62
+
63
+ self.tril_row = tril_row
64
+ self.tril_col = tril_col
65
+
66
+ idx = np.arange(nao)
67
+ self.diag_idx = cupy.asarray(idx*(idx+1)//2+idx)
68
+
69
+ t0 = (logger.process_clock(), logger.perf_counter())
70
+ log = logger.new_logger(mol, mol.verbose)
71
+ if auxmol is None:
72
+ self.auxmol = auxmol = addons.make_auxmol(mol, self.auxbasis)
73
+
74
+ if omega and omega > 1e-10:
75
+ with auxmol.with_range_coulomb(omega):
76
+ j2c_cpu = auxmol.intor('int2c2e', hermi=1)
77
+ else:
78
+ j2c_cpu = auxmol.intor('int2c2e', hermi=1)
79
+ j2c = cupy.asarray(j2c_cpu)
80
+ t0 = log.timer_debug1('2c2e', *t0)
81
+ intopt = int3c2e.VHFOpt(mol, auxmol, 'int2e')
82
+ intopt.build(direct_scf_tol, diag_block_with_triu=False, aosym=True, group_size=256)
83
+ log.timer_debug1('prepare intopt', *t0)
84
+ self.j2c = j2c.copy()
85
+ j2c = j2c[cupy.ix_(intopt.sph_aux_idx, intopt.sph_aux_idx)]
86
+ try:
87
+ self.cd_low = cholesky(j2c)
88
+ self.cd_low = tag_array(self.cd_low, tag='cd')
89
+ except Exception:
90
+ w, v = cupy.linalg.eigh(j2c)
91
+ idx = w > LINEAR_DEP_TOL
92
+ self.cd_low = (v[:,idx] / cupy.sqrt(w[idx]))
93
+ self.cd_low = tag_array(self.cd_low, tag='eig')
94
+
95
+ v = w = None
96
+ naux = self.naux = self.cd_low.shape[1]
97
+ log.debug('size of aux basis %d', naux)
98
+
99
+ self._cderi = cholesky_eri_gpu(intopt, mol, auxmol, self.cd_low, omega=omega)
100
+ log.timer_debug1('cholesky_eri', *t0)
101
+ self.intopt = intopt
102
+
103
+ def get_jk(self, dm, hermi=1, with_j=True, with_k=True,
104
+ direct_scf_tol=getattr(__config__, 'scf_hf_SCF_direct_scf_tol', 1e-13),
105
+ omega=None):
106
+ if omega is None:
107
+ return df_jk.get_jk(self, dm, hermi, with_j, with_k, direct_scf_tol)
108
+ assert omega >= 0.0
109
+
110
+ # A temporary treatment for RSH-DF integrals
111
+ key = '%.6f' % omega
112
+ if key in self._rsh_df:
113
+ rsh_df = self._rsh_df[key]
114
+ else:
115
+ rsh_df = self._rsh_df[key] = copy.copy(self).reset()
116
+ logger.info(self, 'Create RSH-DF object %s for omega=%s', rsh_df, omega)
117
+
118
+ return df_jk.get_jk(rsh_df, dm, hermi, with_j, with_k, direct_scf_tol, omega=omega)
119
+
120
+ def get_blksize(self, extra=0, nao=None):
121
+ '''
122
+ extra for pre-calculated space for other variables
123
+ '''
124
+ if nao is None: nao = self.nao
125
+ mem_avail = get_avail_mem()
126
+ blksize = int(mem_avail*0.2/8/(nao*nao + extra) / ALIGNED) * ALIGNED
127
+ blksize = min(blksize, MIN_BLK_SIZE)
128
+ log = logger.new_logger(self.mol, self.mol.verbose)
129
+ log.debug(f"GPU Memory {mem_avail/1e9:.3f} GB available, block size = {blksize}")
130
+ if blksize < ALIGNED:
131
+ raise RuntimeError("Not enough GPU memory")
132
+ return blksize
133
+
134
+
135
+ def loop(self, blksize=None, unpack=True):
136
+ '''
137
+ loop over all cderi and unpack
138
+ '''
139
+ cderi_sparse = self._cderi
140
+ if blksize is None:
141
+ blksize = self.get_blksize()
142
+ nao = self.nao
143
+ naux = self.naux
144
+ rows = self.intopt.cderi_row
145
+ cols = self.intopt.cderi_col
146
+ buf_prefetch = None
147
+
148
+ data_stream = cupy.cuda.stream.Stream(non_blocking=True)
149
+ compute_stream = cupy.cuda.get_current_stream()
150
+ #compute_stream = cupy.cuda.stream.Stream()
151
+ for p0, p1 in lib.prange(0, naux, blksize):
152
+ p2 = min(naux, p1+blksize)
153
+ if isinstance(cderi_sparse, cupy.ndarray):
154
+ buf = cderi_sparse[p0:p1,:]
155
+ if isinstance(cderi_sparse, np.ndarray):
156
+ # first block
157
+ if buf_prefetch is None:
158
+ buf = cupy.asarray(cderi_sparse[p0:p1,:])
159
+ buf_prefetch = cupy.empty([p2-p1,cderi_sparse.shape[1]])
160
+ with data_stream:
161
+ if isinstance(cderi_sparse, np.ndarray) and p1 < p2:
162
+ buf_prefetch.set(cderi_sparse[p1:p2,:])
163
+ stop_event = data_stream.record()
164
+ if unpack:
165
+ buf2 = cupy.zeros([p1-p0,nao,nao])
166
+ buf2[:p1-p0,rows,cols] = buf
167
+ buf2[:p1-p0,cols,rows] = buf
168
+ else:
169
+ buf2 = None
170
+ yield buf2, buf.T
171
+ compute_stream.wait_event(stop_event)
172
+ cupy.cuda.Device().synchronize()
173
+
174
+ if buf_prefetch is not None:
175
+ buf = buf_prefetch
176
+
177
+ def reset(self, mol=None):
178
+ '''
179
+ reset object for scanner
180
+ '''
181
+ super().reset(mol)
182
+ self.intopt = None
183
+ self.nao = None
184
+ self.naux = None
185
+ self.cd_low = None
186
+ self._cderi = None
187
+ return self
188
+
189
+ def cholesky_eri_gpu(intopt, mol, auxmol, cd_low, omega=None, sr_only=False):
190
+ '''
191
+ Returns:
192
+ 2D array of (naux,nao*(nao+1)/2) in C-contiguous
193
+ '''
194
+ naoaux, naux = cd_low.shape
195
+ npair = len(intopt.cderi_row)
196
+ log = logger.new_logger(mol, mol.verbose)
197
+ nq = len(intopt.log_qs)
198
+
199
+ # if the matrix exceeds the limit, store CDERI in CPU memory
200
+ avail_mem = get_avail_mem()
201
+ use_gpu_memory = True
202
+ if naux * npair * 8 < 0.4 * avail_mem:
203
+ try:
204
+ cderi = cupy.empty([naux, npair], order='C')
205
+ except Exception:
206
+ use_gpu_memory = False
207
+ else:
208
+ use_gpu_memory = False
209
+ if(not use_gpu_memory):
210
+ import warnings
211
+ warnings.warn("Not enough GPU memory")
212
+ # TODO: async allocate memory
213
+ mem = cupy.cuda.alloc_pinned_memory(naux * npair * 8)
214
+ cderi = np.ndarray([naux, npair], dtype=np.float64, order='C', buffer=mem)
215
+
216
+ data_stream = cupy.cuda.stream.Stream(non_blocking=False)
217
+ count = 0
218
+ nq = len(intopt.log_qs)
219
+ for cp_ij_id, _ in enumerate(intopt.log_qs):
220
+ if len(intopt.ao_pairs_row[cp_ij_id]) == 0: continue
221
+ t1 = (logger.process_clock(), logger.perf_counter())
222
+ cpi = intopt.cp_idx[cp_ij_id]
223
+ cpj = intopt.cp_jdx[cp_ij_id]
224
+ li = intopt.angular[cpi]
225
+ lj = intopt.angular[cpj]
226
+ i0, i1 = intopt.cart_ao_loc[cpi], intopt.cart_ao_loc[cpi+1]
227
+ j0, j1 = intopt.cart_ao_loc[cpj], intopt.cart_ao_loc[cpj+1]
228
+ ni = i1 - i0
229
+ nj = j1 - j0
230
+ if sr_only:
231
+ # TODO: in-place implementation or short-range kernel
232
+ ints_slices = cupy.zeros([naoaux, nj, ni], order='C')
233
+ for cp_kl_id, _ in enumerate(intopt.aux_log_qs):
234
+ k0 = intopt.sph_aux_loc[cp_kl_id]
235
+ k1 = intopt.sph_aux_loc[cp_kl_id+1]
236
+ int3c2e.get_int3c2e_slice(intopt, cp_ij_id, cp_kl_id, out=ints_slices[k0:k1])
237
+ if omega is not None:
238
+ ints_slices_lr = cupy.zeros([naoaux, nj, ni], order='C')
239
+ for cp_kl_id, _ in enumerate(intopt.aux_log_qs):
240
+ k0 = intopt.sph_aux_loc[cp_kl_id]
241
+ k1 = intopt.sph_aux_loc[cp_kl_id+1]
242
+ int3c2e.get_int3c2e_slice(intopt, cp_ij_id, cp_kl_id, out=ints_slices[k0:k1], omega=omega)
243
+ ints_slices -= ints_slices_lr
244
+ else:
245
+ ints_slices = cupy.zeros([naoaux, nj, ni], order='C')
246
+ for cp_kl_id, _ in enumerate(intopt.aux_log_qs):
247
+ k0 = intopt.sph_aux_loc[cp_kl_id]
248
+ k1 = intopt.sph_aux_loc[cp_kl_id+1]
249
+ int3c2e.get_int3c2e_slice(intopt, cp_ij_id, cp_kl_id, out=ints_slices[k0:k1], omega=omega)
250
+
251
+ if lj>1: ints_slices = cart2sph(ints_slices, axis=1, ang=lj)
252
+ if li>1: ints_slices = cart2sph(ints_slices, axis=2, ang=li)
253
+
254
+ i0, i1 = intopt.sph_ao_loc[cpi], intopt.sph_ao_loc[cpi+1]
255
+ j0, j1 = intopt.sph_ao_loc[cpj], intopt.sph_ao_loc[cpj+1]
256
+
257
+ row = intopt.ao_pairs_row[cp_ij_id] - i0
258
+ col = intopt.ao_pairs_col[cp_ij_id] - j0
259
+ if cpi == cpj:
260
+ ints_slices = ints_slices + ints_slices.transpose([0,2,1])
261
+ ints_slices = ints_slices[:,col,row]
262
+
263
+ if cd_low.tag == 'eig':
264
+ cderi_block = cupy.dot(cd_low.T, ints_slices)
265
+ ints_slices = None
266
+ elif cd_low.tag == 'cd':
267
+ #cderi_block = solve_triangular(cd_low, ints_slices)
268
+ cderi_block = solve_triangular(cd_low, ints_slices, lower=True, overwrite_b=True)
269
+ ij0, ij1 = count, count+cderi_block.shape[1]
270
+ count = ij1
271
+ if isinstance(cderi, cupy.ndarray):
272
+ cderi[:,ij0:ij1] = cderi_block
273
+ else:
274
+ with data_stream:
275
+ for i in range(naux):
276
+ cderi_block[i].get(out=cderi[i,ij0:ij1])
277
+
278
+ t1 = log.timer_debug1(f'solve {cp_ij_id} / {nq}', *t1)
279
+
280
+ cupy.cuda.Device().synchronize()
281
+ return cderi
282
+
283
+