Пример #1
0
 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
Пример #2
0
    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
Пример #3
0
    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)
Пример #4
0
    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)
Пример #5
0
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
Пример #6
0
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
Пример #7
0
    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 α, β