Пример #1
0
 def ci0():
     x0 = transform_civec_det2csf(fci.get_init_guess(
         norb, nelec, nroots, hdiag_csf),
                                  norb,
                                  neleca,
                                  nelecb,
                                  smult,
                                  csd_mask=fci.csd_mask)[0]
     return pack_sym_ci(x0, idx_sym)
Пример #2
0
 def contract_2e_csf(x):
     x_det = transform_civec_csf2det(csf.unpack_sym_ci(x, idx_sym),
                                     norb,
                                     neleca,
                                     nelecb,
                                     smult,
                                     csd_mask=fci.csd_mask)[0]
     hx = contract_2e(x_det)
     hx = transform_civec_det2csf(hx,
                                  norb,
                                  neleca,
                                  nelecb,
                                  smult,
                                  csd_mask=fci.csd_mask,
                                  do_normalize=False)[0]
     return csf.pack_sym_ci(hx, idx_sym).ravel()
Пример #3
0
 def hop(x):
     x_det = transform_civec_csf2det(unpack_sym_ci(x, idx_sym),
                                     norb,
                                     neleca,
                                     nelecb,
                                     smult,
                                     csd_mask=fci.csd_mask)[0]
     hx = fci.contract_2e(h2e, x_det, norb, nelec,
                          (link_indexa, link_indexb))
     hx = transform_civec_det2csf(hx,
                                  norb,
                                  neleca,
                                  nelecb,
                                  smult,
                                  csd_mask=fci.csd_mask,
                                  do_normalize=False)[0]
     return pack_sym_ci(hx, idx_sym).ravel()
Пример #4
0
 def avg_orb_wgt_ci(x_roots):
     x_orb = sum([
         x_iroot[:ngorb] * w for x_iroot, w in zip(x_roots, casscf.weights)
     ])
     x_ci = np.stack([
         x_iroot[ngorb:] * w for x_iroot, w in zip(x_roots, casscf.weights)
     ],
                     axis=0)
     if is_csf:
         x_ci = csf.pack_sym_ci(
             transform_civec_det2csf(x_ci,
                                     ncas,
                                     neleca,
                                     nelecb,
                                     smult,
                                     csd_mask=mc_fci.csd_mask,
                                     do_normalize=False)[0], idx_sym)
     x_all = np.append(x_orb, x_ci.ravel()).ravel()
     return x_all
Пример #5
0
def kernel(fci,
           h1e,
           eri,
           norb,
           nelec,
           smult=None,
           idx_sym=None,
           ci0=None,
           tol=None,
           lindep=None,
           max_cycle=None,
           max_space=None,
           nroots=None,
           davidson_only=None,
           pspace_size=None,
           max_memory=None,
           orbsym=None,
           wfnsym=None,
           ecore=0,
           **kwargs):
    t0 = (time.clock(), time.time())
    if 'verbose' in kwargs:
        verbose = kwargs['verbose']
        kwargs.pop('verbose')
    else:
        verbose = lib.logger.Logger(stdout=fci.stdout, verbose=fci.verbose)
    if (isinstance(verbose, lib.logger.Logger)
            and verbose.verbose >= lib.logger.WARN) or (isinstance(
                verbose, int) and verbose >= lib.logger.WARN):
        fci.check_sanity()
    if nroots is None: nroots = fci.nroots
    if pspace_size is None: pspace_size = fci.pspace_size
    if davidson_only is None: davidson_only = fci.davidson_only
    nelec = _unpack_nelec(nelec, fci.spin)
    neleca, nelecb = nelec
    t0 = lib.logger.timer(fci, "csf.kernel: throat-clearing", *t0)
    hdiag_det = fci.make_hdiag(h1e, eri, norb, nelec)
    t0 = lib.logger.timer(fci, "csf.kernel: hdiag_det", *t0)
    hdiag_csf = fci.make_hdiag_csf(h1e, eri, norb, nelec, hdiag_det=hdiag_det)
    t0 = lib.logger.timer(fci, "csf.kernel: hdiag_csf", *t0)
    ncsf_all = count_all_csfs(norb, neleca, nelecb, smult)
    if idx_sym is None:
        ncsf_sym = ncsf_all
    else:
        ncsf_sym = np.count_nonzero(idx_sym)
    nroots = min(ncsf_sym, nroots)
    if nroots is not None:
        assert (ncsf_sym >=
                nroots), "Can't find {} roots among only {} CSFs".format(
                    nroots, ncsf_sym)
    link_indexa, link_indexb = _unpack(norb, nelec, None)
    na = link_indexa.shape[0]
    nb = link_indexb.shape[0]

    t0 = lib.logger.timer(fci, "csf.kernel: throat-clearing", *t0)
    addr, h0 = fci.pspace(h1e,
                          eri,
                          norb,
                          nelec,
                          idx_sym=idx_sym,
                          hdiag_det=hdiag_det,
                          hdiag_csf=hdiag_csf,
                          npsp=max(pspace_size, nroots))
    lib.logger.debug(fci, 'csf.kernel: error of hdiag_csf: %s',
                     np.amax(np.abs(hdiag_csf[addr] - np.diag(h0))))
    t0 = lib.logger.timer(fci, "csf.kernel: make pspace", *t0)
    if pspace_size > 0:
        pw, pv = fci.eig(h0)
    else:
        pw = pv = None

    if pspace_size >= ncsf_sym and not davidson_only:
        if ncsf_sym == 1:
            civec = unpack_sym_ci(pv[:, 0].reshape(1, 1), idx_sym)
            civec = transform_civec_csf2det(civec,
                                            norb,
                                            neleca,
                                            nelecb,
                                            smult,
                                            csd_mask=fci.csd_mask)[0]
            return pw[0] + ecore, civec
        elif nroots > 1:
            civec = np.empty((nroots, ncsf_all))
            civec[:, addr] = pv[:, :nroots].T
            civec = transform_civec_csf2det(civec,
                                            norb,
                                            neleca,
                                            nelecb,
                                            smult,
                                            csd_mask=fci.csd_mask)[0]
            return pw[:nroots] + ecore, [c.reshape(na, nb) for c in civec]
        elif abs(pw[0] - pw[1]) > 1e-12:
            civec = np.empty((ncsf_all))
            civec[addr] = pv[:, 0]
            civec = transform_civec_csf2det(civec,
                                            norb,
                                            neleca,
                                            nelecb,
                                            smult,
                                            csd_mask=fci.csd_mask)[0]
            return pw[0] + ecore, civec.reshape(na, nb)

    t0 = lib.logger.timer(fci, "csf.kernel: throat-clearing", *t0)
    if idx_sym is None:
        precond = fci.make_precond(hdiag_csf, pw, pv, addr)
    else:
        addr_bool = np.zeros(ncsf_all, dtype=np.bool)
        addr_bool[addr] = True
        precond = fci.make_precond(hdiag_csf[idx_sym], pw, pv,
                                   addr_bool[idx_sym])
    t0 = lib.logger.timer(fci, "csf.kernel: make preconditioner", *t0)
    '''
    fci.eci, fci.ci = \
            kernel_ms1(fci, h1e, eri, norb, nelec, ci0, None,
                       tol, lindep, max_cycle, max_space, nroots,
                       davidson_only, pspace_size, ecore=ecore, **kwargs)
    '''
    h2e = fci.absorb_h1e(h1e, eri, norb, nelec, .5)
    t0 = lib.logger.timer(fci, "csf.kernel: h2e", *t0)

    def hop(x):
        x_det = transform_civec_csf2det(unpack_sym_ci(x, idx_sym),
                                        norb,
                                        neleca,
                                        nelecb,
                                        smult,
                                        csd_mask=fci.csd_mask)[0]
        hx = fci.contract_2e(h2e, x_det, norb, nelec,
                             (link_indexa, link_indexb))
        hx = transform_civec_det2csf(hx,
                                     norb,
                                     neleca,
                                     nelecb,
                                     smult,
                                     csd_mask=fci.csd_mask,
                                     do_normalize=False)[0]
        return pack_sym_ci(hx, idx_sym).ravel()

    t0 = lib.logger.timer(fci, "csf.kernel: make hop", *t0)
    if ci0 is None:
        if hasattr(fci, 'get_init_guess'):

            def ci0():
                x0 = transform_civec_det2csf(fci.get_init_guess(
                    norb, nelec, nroots, hdiag_csf),
                                             norb,
                                             neleca,
                                             nelecb,
                                             smult,
                                             csd_mask=fci.csd_mask)[0]
                return pack_sym_ci(x0, idx_sym)

        else:

            def ci0():  # lazy initialization to reduce memory footprint
                x0 = []
                for i in range(nroots):
                    x = np.zeros(ncsf_sym)
                    x[addr[i]] = 1
                    x0.append(x)
                return x0
    else:
        if isinstance(ci0, np.ndarray) and ci0.size == na * nb:
            ci0 = pack_sym_ci([
                transform_civec_det2csf(ci0.ravel(),
                                        norb,
                                        neleca,
                                        nelecb,
                                        smult,
                                        csd_mask=fci.csd_mask)[0]
            ], idx_sym)
        else:
            nrow = len(ci0)
            ci0 = np.asarray(ci0).reshape(nrow, -1, order='C')
            ci0 = np.ascontiguousarray(ci0)
            ci0 = pack_sym_ci(
                transform_civec_det2csf(ci0,
                                        norb,
                                        neleca,
                                        nelecb,
                                        smult,
                                        csd_mask=fci.csd_mask)[0], idx_sym)
    t0 = lib.logger.timer(fci, "csf.kernel: ci0 handling", *t0)

    if tol is None: tol = fci.conv_tol
    if lindep is None: lindep = fci.lindep
    if max_cycle is None: max_cycle = fci.max_cycle
    if max_space is None: max_space = fci.max_space
    if max_memory is None: max_memory = fci.max_memory
    tol_residual = getattr(fci, 'conv_tol_residual', None)

    #with lib.with_omp_threads(fci.threads):
    #e, c = lib.davidson(hop, ci0, precond, tol=fci.conv_tol, lindep=fci.lindep)
    e, c = fci.eig(hop,
                   ci0,
                   precond,
                   tol=tol,
                   lindep=lindep,
                   max_cycle=max_cycle,
                   max_space=max_space,
                   nroots=nroots,
                   max_memory=max_memory,
                   verbose=verbose,
                   follow_state=True,
                   tol_residual=tol_residual,
                   **kwargs)
    t0 = lib.logger.timer(fci, "csf.kernel: running fci.eig", *t0)
    c = transform_civec_csf2det(unpack_sym_ci(c, idx_sym),
                                norb,
                                neleca,
                                nelecb,
                                smult,
                                csd_mask=fci.csd_mask,
                                vec_on_cols=False)[0]
    t0 = lib.logger.timer(fci, "csf.kernel: transforming final ci vector", *t0)
    if nroots > 1:
        return e + ecore, [ci.reshape(na, nb) for ci in c]
    else:
        return e + ecore, c.reshape(na, nb)
Пример #6
0
def solve_approx_ci_csf(mc, h1, h2, ci0, ecore, e_cas, envs):
    ''' This is identical to pyscf.mcscf.mc1step.CASSCF.solve_approx_ci
    (with %s/self/mc/g) as of 03/24/2019 for the first 48 lines '''
    ncas = mc.ncas
    nelecas = mc.nelecas
    ncore = mc.ncore
    nocc = ncore + ncas
    if 'norm_gorb' in envs:
        tol = max(mc.conv_tol, envs['norm_gorb']**2 * .1)
    else:
        tol = None
    if getattr(mc.fcisolver, 'approx_kernel', None):
        fn = mc.fcisolver.approx_kernel
        e, ci1 = fn(h1,
                    h2,
                    ncas,
                    nelecas,
                    ecore=ecore,
                    ci0=ci0,
                    tol=tol,
                    max_memory=mc.max_memory)
        return ci1, None
    elif not (getattr(mc.fcisolver, 'contract_2e', None)
              and getattr(mc.fcisolver, 'absorb_h1e', None)):
        fn = mc.fcisolver.kernel
        e, ci1 = fn(h1,
                    h2,
                    ncas,
                    nelecas,
                    ecore=ecore,
                    ci0=ci0,
                    tol=tol,
                    max_memory=mc.max_memory,
                    max_cycle=mc.ci_response_space)
        return ci1, None

    h2eff = mc.fcisolver.absorb_h1e(h1, h2, ncas, nelecas, .5)

    # Be careful with the symmetry adapted contract_2e function. When the
    # symmetry adapted FCI solver is used, the symmetry of ci0 may be
    # different to fcisolver.wfnsym. This function may output 0.
    if getattr(mc.fcisolver, 'guess_wfnsym', None):
        wfnsym = mc.fcisolver.guess_wfnsym(mc.ncas, mc.nelecas, ci0)
    else:
        wfnsym = None

    def contract_2e(c):
        if wfnsym is None:
            hc = mc.fcisolver.contract_2e(h2eff, c, ncas, nelecas)
        else:
            with lib.temporary_env(mc.fcisolver, wfnsym=wfnsym):
                hc = mc.fcisolver.contract_2e(h2eff, c, ncas, nelecas)
        return hc.ravel()

    hc = contract_2e(ci0)
    g = hc - (e_cas - ecore) * ci0.ravel()

    if mc.ci_response_space > 7:
        logger.debug(mc, 'CI step by full response')
        # full response
        max_memory = max(400, mc.max_memory - lib.current_memory()[0])
        e, ci1 = mc.fcisolver.kernel(h1,
                                     h2,
                                     ncas,
                                     nelecas,
                                     ecore=ecore,
                                     ci0=ci0,
                                     tol=tol,
                                     max_memory=max_memory)
    else:
        # MRH 03/24/2019: this is where I intervene to enforce CSFs
        fci = mc.fcisolver
        smult = fci.smult
        neleca, nelecb = _unpack_nelec(nelecas)
        norb = np.asarray(h1).shape[-1]
        if hasattr(fci, 'wfnsym') and hasattr(fci, 'confsym'):
            idx_sym = fci.confsym[fci.econf_csf_mask] == fci.wfnsym
        else:
            idx_sym = None
        xs = [
            csf.pack_sym_ci(
                transform_civec_det2csf(ci0,
                                        norb,
                                        neleca,
                                        nelecb,
                                        smult,
                                        csd_mask=fci.csd_mask,
                                        do_normalize=True)[0], idx_sym)
        ]
        nd = min(max(mc.ci_response_space, 2), xs[0].size)
        logger.debug(mc, 'CI step by %dD subspace response', nd)

        def contract_2e_csf(x):
            x_det = transform_civec_csf2det(csf.unpack_sym_ci(x, idx_sym),
                                            norb,
                                            neleca,
                                            nelecb,
                                            smult,
                                            csd_mask=fci.csd_mask)[0]
            hx = contract_2e(x_det)
            hx = transform_civec_det2csf(hx,
                                         norb,
                                         neleca,
                                         nelecb,
                                         smult,
                                         csd_mask=fci.csd_mask,
                                         do_normalize=False)[0]
            return csf.pack_sym_ci(hx, idx_sym).ravel()

        ax = [contract_2e_csf(xs[0])]
        heff = np.empty((nd, nd))
        seff = np.empty((nd, nd))
        heff[0, 0] = np.dot(xs[0], ax[0])
        seff[0, 0] = 1
        for i in range(1, nd):
            xs.append(ax[i - 1] - xs[i - 1] * e_cas)
            ax.append(contract_2e_csf(xs[i]))
            for j in range(i + 1):
                heff[i, j] = heff[j, i] = (xs[i] * ax[j]).sum()
                seff[i, j] = seff[j, i] = (xs[i] * xs[j]).sum()
        e, v = lib.safe_eigh(heff, seff)[:2]
        ci1 = xs[0] * v[0, 0]
        for i in range(1, nd):
            ci1 += xs[i] * v[i, 0]
        ci1 = transform_civec_csf2det(csf.unpack_sym_ci(ci1, idx_sym),
                                      norb,
                                      neleca,
                                      nelecb,
                                      smult,
                                      csd_mask=fci.csd_mask,
                                      do_normalize=True)[0]
    return ci1, g