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.
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/MANIFEST.in +2 -1
- {gpu4pyscf-0.6.2/gpu4pyscf.egg-info → gpu4pyscf-0.6.3}/PKG-INFO +1 -1
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/__init__.py +1 -1
- gpu4pyscf-0.6.3/gpu4pyscf/df/__init__.py +15 -0
- gpu4pyscf-0.6.3/gpu4pyscf/df/cderi.py +80 -0
- gpu4pyscf-0.6.3/gpu4pyscf/df/df.py +283 -0
- gpu4pyscf-0.6.3/gpu4pyscf/df/df_jk.py +390 -0
- gpu4pyscf-0.6.3/gpu4pyscf/df/grad/__init__.py +19 -0
- gpu4pyscf-0.6.3/gpu4pyscf/df/grad/rhf.py +255 -0
- gpu4pyscf-0.6.3/gpu4pyscf/df/grad/rks.py +137 -0
- gpu4pyscf-0.6.3/gpu4pyscf/df/hessian/__init__.py +19 -0
- gpu4pyscf-0.6.3/gpu4pyscf/df/hessian/rhf.py +517 -0
- gpu4pyscf-0.6.3/gpu4pyscf/df/hessian/rks.py +129 -0
- gpu4pyscf-0.6.3/gpu4pyscf/df/int3c2e.py +1439 -0
- gpu4pyscf-0.6.3/gpu4pyscf/df/patch_pyscf.py +29 -0
- gpu4pyscf-0.6.3/gpu4pyscf/gto/__init__.py +14 -0
- gpu4pyscf-0.6.3/gpu4pyscf/gto/mole.py +30 -0
- gpu4pyscf-0.6.3/gpu4pyscf/lib/__init__.py +20 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3/gpu4pyscf.egg-info}/PKG-INFO +1 -1
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf.egg-info/SOURCES.txt +14 -0
- gpu4pyscf-0.6.2/gpu4pyscf/lib/__init__.py +0 -5
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/LICENSE +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/README.md +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/__config__.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/__init__.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/gen_grid.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/gks.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/libxc.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/numint.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/patch_pyscf.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/radi.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/rks.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/roks.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/uks.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/xc_alias.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/dft/xc_deriv.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/grad/__init__.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/grad/patch_pyscf.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/grad/rhf.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/grad/rks.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/hessian/__init__.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/hessian/rhf.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/hessian/rks.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/lib/cublas.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/lib/cupy_helper.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/lib/cusolver.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/lib/cutensor.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/lib/diis.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/lib/logger.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/lib/utils.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/patch_pyscf.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/scf/__init__.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/scf/cphf.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/scf/diis.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/scf/ghf.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/scf/hf.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/scf/int4c2e.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/scf/patch_pyscf.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/scf/rohf.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/scf/uhf.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/solvent/__init__.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/solvent/_attach_solvent.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf/solvent/pcm.py +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf.egg-info/dependency_links.txt +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf.egg-info/requires.txt +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/gpu4pyscf.egg-info/top_level.txt +0 -0
- {gpu4pyscf-0.6.2 → gpu4pyscf-0.6.3}/setup.cfg +0 -0
- {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,2 +1,2 @@
|
|
|
1
1
|
from . import lib, grad, hessian, solvent, scf, dft
|
|
2
|
-
__version__ = '0.6.
|
|
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
|
+
|