Skip to content

Commit c8ae173

Browse files
committed
A guard to prevent errors in cutensor when handling 0-size tensors (fix #542)
1 parent 3556fe7 commit c8ae173

File tree

3 files changed

+36
-12
lines changed

3 files changed

+36
-12
lines changed

gpu4pyscf/df/int3c2e_bdiv.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,8 @@ def orbital_pair_cart2sph(self, compressed_eri3c, inplace=True):
494494
p0 = p1 = 0
495495
for (i, j), bas_ij_idx in zip(ij_tasks, self.shl_pair_idx):
496496
nshl_pair = bas_ij_idx.size
497+
if nshl_pair == 0:
498+
continue
497499
ci = c2s[i]
498500
cj = c2s[j]
499501
nfi, di = ci.shape

gpu4pyscf/df/tests/test_df_int3c2e.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,19 @@ def test_int3c2e_sparse1():
192192
dat = int3c2e_bdiv.aux_e2(mol, mol)
193193
ref = incore.aux_e2(mol, mol)
194194
assert abs(dat.get() - ref).max() < 1e-9
195+
196+
int3c2e_opt = int3c2e_bdiv.Int3c2eOpt(mol, mol).build()
197+
ao_pair_mapping = int3c2e_opt.create_ao_pair_mapping()
198+
nao = mol.nao
199+
i, j = divmod(ao_pair_mapping, nao)
200+
coeff = cp.asarray(int3c2e_opt.coeff)
201+
aux_coeff = cp.asarray(int3c2e_opt.coeff)
202+
for eri3c_batch in int3c2e_opt.int3c2e_bdiv_generator():
203+
eri3c_batch = int3c2e_opt.orbital_pair_cart2sph(eri3c_batch, inplace=True)
204+
dat = cp.zeros((nao*nao, nao))
205+
dat[i*nao+j] = dat[j*nao+i] = eri3c_batch
206+
dat = dat.reshape(nao,nao,nao)
207+
dat = contract('pqr,rk->pqk', dat, aux_coeff)
208+
dat = contract('pqk,qj->pjk', dat, coeff)
209+
dat = contract('pjk,pi->ijk', dat, coeff)
210+
assert abs(dat.get() - ref).max() < 1e-9

gpu4pyscf/lib/cutensor.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,20 @@ def _auto_create_mode(array, mode):
5656
# cutensor_dtype, alignment_req=alignment_req)
5757
# return _tensor_descriptors[key]
5858

59+
def _contract_einsum(pattern, a, b, alpha, beta, out=None, einsum=cupy.einsum):
60+
if out is None:
61+
out = einsum(pattern, a, b)
62+
out *= alpha
63+
elif beta == 0.:
64+
out[:] = einsum(pattern, a, b)
65+
out *= alpha
66+
else:
67+
out *= beta
68+
tmp = einsum(pattern, a, b)
69+
tmp *= alpha
70+
out += tmp
71+
return cupy.asarray(out, order='C')
72+
5973
def contraction(
6074
pattern, a, b, alpha, beta,
6175
out=None,
@@ -67,6 +81,9 @@ def contraction(
6781
compute_desc=0,
6882
ws_pref=WORKSPACE_RECOMMENDED
6983
):
84+
if a.size == 0 or b.size == 0:
85+
# cutensor does not support the 0-sized operands
86+
return _contract_einsum(pattern, a, b, alpha, beta, out)
7087

7188
pattern = pattern.replace(" ", "")
7289
str_a, rest = pattern.split(',')
@@ -138,22 +155,11 @@ def contraction(
138155
warnings.warn(f'using {contract_engine} as the tensor contraction engine.')
139156
def contract(pattern, a, b, alpha=1.0, beta=0.0, out=None):
140157
try:
141-
if out is None:
142-
out = einsum(pattern, a, b)
143-
out *= alpha
144-
elif beta == 0.:
145-
out[:] = einsum(pattern, a, b)
146-
out *= alpha
147-
else:
148-
out *= beta
149-
tmp = einsum(pattern, a, b)
150-
tmp *= alpha
151-
out += tmp
158+
return _contract_einsum(pattern, a, b, alpha, beta, out, einsum)
152159
except cupy.cuda.memory.OutOfMemoryError:
153160
print('Out of memory error caused by cupy.einsum. '
154161
'It is recommended to install cutensor to resolve this.')
155162
raise
156-
return cupy.asarray(out, order='C')
157163
else:
158164
def contract(pattern, a, b, alpha=1.0, beta=0.0, out=None):
159165
'''

0 commit comments

Comments
 (0)