def bump_ij(c, i, n, env): # [i+1,n,i+1] <- [i,1,i] + [i,n,i] + [i,n+1,i] + [i,n+2,i] + [i,n,i-1] + [i,n+1,i-1] + [i-1,n,i-1] b, binv = env['b'], env['binv'] if n == 0 and c.force_orth: c[i + 1, n, i + 1] = c.eye.copy() return c tmp = c[i, n + 2, i].copy() tmp -= lib.hermi_sum(c.cb(i, n + 1, i - 1, env)) tmp -= lib.hermi_sum(c.mc(i, n + 1, i, env).T.conj()) tmp += lib.hermi_sum(np.dot(c[i, 1, i], c.cb(i, n, i - 1, env))) tmp += np.dot(b[i - 1], c.cb(i - 1, n, i - 1, env)) tmp += np.dot(c.mc(i, n, i, env), c[i, 1, i].T.conj()) c[i + 1, n, i + 1] = np.dot(np.dot(binv.T.conj(), tmp), binv) return c
def contract2(self, vPuv): ''' Contract the auxbasis and one AO basis indices with multiplicand vPuv, as when computing the exchange matrix of Hartree--Fock. Args: vPuv : np.ndarray of shape (nao, nao, naux) stored in row-major order. The FIRST index is contracted with self ; the output of contract1 must be TRANSPOSED ON THE FIRST 2 INDICES in order to generate the vk matrix Returns: vk : np.ndarray of shape (nao, nao) ''' if self.ndim == 3: return self.pack_mo() if not self.flags['F_CONTIGUOUS']: self = self.naux_fast() if self.nent_max is None: self.get_sparsity_() nao = self.nmo[0] vk = np.zeros((nao, nao), dtype=self.dtype) wrk = np.zeros((lib.num_threads(), self.nent_max, self.naux), dtype=self.dtype) libsint.SINT_SDCDERI_VK( self.ctypes.data_as(ctypes.c_void_p), vPuv.ctypes.data_as(ctypes.c_void_p), vk.ctypes.data_as(ctypes.c_void_p), wrk.ctypes.data_as(ctypes.c_void_p), self.iao_sort.ctypes.data_as(ctypes.c_void_p), self.iao_nent.ctypes.data_as(ctypes.c_void_p), self.iao_entlist.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(nao), ctypes.c_int(self.naux), ctypes.c_int(self.nent_max)) wrk = None vk = lib.hermi_sum(vk, inplace=True) vk[np.diag_indices(nao)] /= 2 return vk
def test_transpose_sum(self): a = numpy.random.random((3, 400, 400)) self.assertAlmostEqual( abs(a[0] + a[0].T - lib.hermi_sum(a[0])).max(), 0, 12) self.assertAlmostEqual( abs(a + a.transpose(0, 2, 1) - lib.hermi_sum(a, (0, 2, 1))).max(), 0, 12) self.assertAlmostEqual( abs(a + a.transpose(0, 2, 1) - lib.hermi_sum(a, (0, 2, 1), inplace=True)).max(), 0, 12) a = numpy.random.random((3, 400, 400)) + numpy.random.random( (3, 400, 400)) * 1j self.assertAlmostEqual( abs(a[0] + a[0].T.conj() - lib.hermi_sum(a[0])).max(), 0, 12) self.assertAlmostEqual( abs(a + a.transpose(0, 2, 1).conj() - lib.hermi_sum(a, (0, 2, 1))).max(), 0, 12) self.assertAlmostEqual( abs(a + a.transpose(0, 2, 1) - lib.hermi_sum(a, (0, 2, 1), hermi=3)).max(), 0, 12) self.assertAlmostEqual( abs(a + a.transpose(0, 2, 1).conj() - lib.hermi_sum(a, (0, 2, 1), inplace=True)).max(), 0, 12) a = numpy.random.random((400, 400)) b = a + a.T.conj() c = lib.transpose_sum(a) self.assertAlmostEqual(abs(b - c).max(), 0, 12) a = (a * 1000).astype(numpy.int32) b = a + a.T c = lib.transpose_sum(a) self.assertAlmostEqual(abs(b - c).max(), 0, 12) self.assertTrue(c.dtype == numpy.int32)
def test_transpose_sum(self): a = numpy.random.random((3,400,400)) self.assertAlmostEqual(abs(a[0]+a[0].T - lib.hermi_sum(a[0])).max(), 0, 12) self.assertAlmostEqual(abs(a+a.transpose(0,2,1) - lib.hermi_sum(a,(0,2,1))).max(), 0, 12) self.assertAlmostEqual(abs(a+a.transpose(0,2,1) - lib.hermi_sum(a,(0,2,1), inplace=True)).max(), 0, 12) a = numpy.random.random((3,400,400)) + numpy.random.random((3,400,400)) * 1j self.assertAlmostEqual(abs(a[0]+a[0].T.conj() - lib.hermi_sum(a[0])).max(), 0, 12) self.assertAlmostEqual(abs(a+a.transpose(0,2,1).conj() - lib.hermi_sum(a,(0,2,1))).max(), 0, 12) self.assertAlmostEqual(abs(a+a.transpose(0,2,1) - lib.hermi_sum(a,(0,2,1),hermi=3)).max(), 0, 12) self.assertAlmostEqual(abs(a+a.transpose(0,2,1).conj() - lib.hermi_sum(a,(0,2,1),inplace=True)).max(), 0, 12) a = numpy.random.random((400,400)) b = a + a.T.conj() c = lib.transpose_sum(a) self.assertAlmostEqual(abs(b-c).max(), 0, 12)
def compute_b(i, env, cond_tol=10, maxiter=20, method='eig'): c, b, t, nmo = env['c'], env['b'], env['t'], env['nmo'] if i == 0: b2 = t[0] else: b2 = c[i, 2, i].copy() #b2 -= lib.hermi_sum(np.dot(c[i,1,i-1], b[i-1].T.conj())) b2 -= lib.hermi_sum(c.cb(i, 1, i - 1, env)) b2 -= np.dot(c[i, 1, i], c[i, 1, i].T.conj()) if i > 1: b2 += np.dot(b[i - 1], b[i - 1].T.conj()) tol = 10 * np.finfo(c.dtype).eps if method == 'eig': w, v = np.linalg.eigh(b2) w[w < tol] = tol bi = np.dot(v * w[None]**0.5, v.T) binv = np.dot(v * w[None]**-0.5, v.T) elif method == 'chol' or method == 'chol-iter': bi = cholesky(force_posdef(b2, tol=tol)).T.conj() binv = inv(bi) elif method == 'shifted-chol' or method == 'shifted-chol-iter': # https://arxiv.org/pdf/1809.11085.pdf shift = np.finfo(dtype).eps shift *= 11 * (nmo * (nmo + (nmo // 2)**3) + nmo * (nmo + 1)) shift *= np.trace(b2) shift = np.dot(shift, np.eye(nmo)) bi = cholesky(force_posdef(b2, tol=tol)).T.conj() binv = inv(bi) if method.endswith('iter'): n = 0 b2_next = b2 while np.linalg.cond(b2_next) > cond_tol and n < maxiter: b2_next = np.dot(np.dot(binv.T.conj(), b2), binv) b_next = cholesky(force_posdef(b2_next, tol=tol)).T.conj() bi = np.dot(b_next, bi) binv = inv(bi) n += 1 return bi, binv
def incore(eri, dms, hermi=0, with_j=True, with_k=True): assert (eri.dtype == numpy.double) eri = numpy.asarray(eri, order='C') dms = numpy.asarray(dms, order='C') dms_shape = dms.shape nao = dms_shape[-1] dms = dms.reshape(-1, nao, nao) n_dm = dms.shape[0] vj = vk = None if with_j: vj = numpy.zeros((n_dm, nao, nao)) if with_k: vk = numpy.zeros((n_dm, nao, nao)) dmsptr = [] vjkptr = [] fjkptr = [] npair = nao * (nao + 1) // 2 if eri.ndim == 2 and npair * npair == eri.size: # 4-fold symmetry eri fdrv = getattr(libcvhf, 'CVHFnrs4_incore_drv') if with_j: # 'ijkl,kl->ij' fvj = _fpointer('CVHFics4_kl_s2ij') # or ## 'ijkl,ij->kl' #fvj = _fpointer('CVHFics4_ij_s2kl') for i, dm in enumerate(dms): dmsptr.append(dm.ctypes.data_as(ctypes.c_void_p)) vjkptr.append(vj[i].ctypes.data_as(ctypes.c_void_p)) fjkptr.append(fvj) if with_k: # 'ijkl,il->jk' fvk = _fpointer('CVHFics4_il_s1jk') # or ## 'ijkl,jk->il' #fvk = _fpointer('CVHFics4_jk_s1il') for i, dm in enumerate(dms): dmsptr.append(dm.ctypes.data_as(ctypes.c_void_p)) vjkptr.append(vk[i].ctypes.data_as(ctypes.c_void_p)) fjkptr.append(fvk) elif eri.ndim == 1 and npair * (npair + 1) // 2 == eri.size: # 8-fold symmetry eri fdrv = getattr(libcvhf, 'CVHFnrs8_incore_drv') if with_j: fvj = _fpointer('CVHFics8_tridm_vj') tridms = lib.pack_tril(lib.hermi_sum(dms, axes=(0, 2, 1))) idx = numpy.arange(nao) tridms[:, idx * (idx + 1) // 2 + idx] *= .5 for i, tridm in enumerate(tridms): dmsptr.append(tridm.ctypes.data_as(ctypes.c_void_p)) vjkptr.append(vj[i].ctypes.data_as(ctypes.c_void_p)) fjkptr.append(fvj) if with_k: if hermi == 1: fvk = _fpointer('CVHFics8_jk_s2il') else: fvk = _fpointer('CVHFics8_jk_s1il') for i, dm in enumerate(dms): dmsptr.append(dm.ctypes.data_as(ctypes.c_void_p)) vjkptr.append(vk[i].ctypes.data_as(ctypes.c_void_p)) fjkptr.append(fvk) else: raise RuntimeError('Array shape not consistent: DM %s, eri %s' % (dms_shape, eri.shape)) n_ops = len(dmsptr) fdrv(eri.ctypes.data_as(ctypes.c_void_p), (ctypes.c_void_p * n_ops)(*dmsptr), (ctypes.c_void_p * n_ops)(*vjkptr), ctypes.c_int(n_ops), ctypes.c_int(nao), (ctypes.c_void_p * n_ops)(*fjkptr)) if with_j: for i in range(n_dm): lib.hermi_triu(vj[i], 1, inplace=True) vj = vj.reshape(dms_shape) if with_k: if hermi != 0: for i in range(n_dm): lib.hermi_triu(vk[i], hermi, inplace=True) vk = vk.reshape(dms_shape) return vj, vk
def get_blocks(self): """Get on- and off-diagonal blocks of the block tridiagonalised Hamiltonian. """ α = np.zeros((self.niter+1, self.norb, self.norb), dtype=self.dtype) β = np.zeros((self.niter, self.norb, self.norb), dtype=self.dtype) v = V(self.zero) βsq = self.moments[0] β[0] = self.mat_sqrt(βsq) βinv = self.mat_isqrt(βsq) for i in range(self.nmom): v[1, i, 1] = np.linalg.multi_dot(( βinv.T.conj(), self.moments[i], βinv, )) def vb(i, n, j): return np.dot(v[i, n, j], β[j].T.conj()) def av(i, n, j): return np.dot(v[i, 1, i], v[i, n, j]) for i in range(1, self.niter): βsq = ( + v[i, 2, i] - lib.hermi_sum(vb(i, 1, i-1)) - np.dot(v[i, 1, i], v[i, 1, i].T.conj()) ) if i > 1: βsq += np.dot(β[i-1], β[i-1].T.conj()) β[i] = self.mat_sqrt(βsq) βinv = self.mat_isqrt(βsq) for n in range(2 * (self.niter-i)): if n != (2 * (self.niter-i) - 1): r = ( + v[i, n+1, i] - vb(i, n, i-1).T.conj() - av(i, n, i) ) v[i+1, n, i] = np.dot(βinv.T.conj(), r) r = ( + v[i, n+2, i] - lib.hermi_sum(vb(i, n+1, i-1)) - lib.hermi_sum(av(i, n+1, i)) + lib.hermi_sum(np.dot(v[i, 1, i], vb(i, n, i-1))) + np.dot(β[i-1], vb(i-1, n, i-1)) + np.dot(av(i, n, i), v[i, 1, i].T.conj()) ) v[i+1, n, i+1] = np.linalg.multi_dot((βinv.T.conj(), r, βinv)) for i in range(self.niter+1): α[i] = v[i, 1, i] return α, β