Ejemplo n.º 1
0
def uhf_external(mf, with_symmetry=True, verbose=None):
    log = logger.new_logger(mf, verbose)
    hop1, hdiag1, hop2, hdiag2 = _gen_hop_uhf_external(mf, with_symmetry)

    def precond(dx, e, x0):
        hdiagd = hdiag1 - e
        hdiagd[abs(hdiagd) < 1e-8] = 1e-8
        return dx / hdiagd

    x0 = numpy.zeros_like(hdiag1)
    x0[hdiag1 > 1e-5] = 1. / hdiag1[hdiag1 > 1e-5]
    if not with_symmetry:  # allow to break point group symmetry
        x0[numpy.argmin(hdiag1)] = 1
    e1, v = lib.davidson(hop1, x0, precond, tol=1e-4, verbose=log)
    if e1 < -1e-5:
        log.note('UHF/UKS wavefunction has a real -> complex instability')
    else:
        log.note(
            'UHF/UKS wavefunction is stable in the real -> complex stability analysis'
        )

    def precond(dx, e, x0):
        hdiagd = hdiag2 - e
        hdiagd[abs(hdiagd) < 1e-8] = 1e-8
        return dx / hdiagd

    x0 = numpy.zeros_like(hdiag2)
    x0[hdiag2 > 1e-5] = 1. / hdiag2[hdiag2 > 1e-5]
    if not with_symmetry:  # allow to break point group symmetry
        x0[numpy.argmin(hdiag2)] = 1
    e3, v = lib.davidson(hop2, x0, precond, tol=1e-4, verbose=log)
    log.debug('uhf_external: lowest eigs of H = %s', e3)
    mo = scipy.linalg.block_diag(*mf.mo_coeff)
    if e3 < -1e-5:
        stable_e = False  # added by qingchun 3/13 2018
        log.note('UHF/UKS wavefunction has an UHF/UKS -> GHF/GKS instability.')
        occidxa = numpy.where(mf.mo_occ[0] > 0)[0]
        viridxa = numpy.where(mf.mo_occ[0] == 0)[0]
        occidxb = numpy.where(mf.mo_occ[1] > 0)[0]
        viridxb = numpy.where(mf.mo_occ[1] == 0)[0]
        nocca = len(occidxa)
        nvira = len(viridxa)
        noccb = len(occidxb)
        nvirb = len(viridxb)
        nmo = nocca + nvira
        dx = numpy.zeros((nmo * 2, nmo * 2))
        dx[viridxa[:, None],
           nmo + occidxb] = v[:nvira * noccb].reshape(nvira, noccb)
        dx[nmo + viridxb[:, None],
           occidxa] = v[nvira * noccb:].reshape(nvirb, nocca)
        u = newton_ah.expmat(dx - dx.T)
        mo = numpy.dot(mo, u)
    else:
        stable_e = True  # added by qingchun 3/13 2018
        log.note(
            'UHF/UKS wavefunction is stable in the UHF/UKS -> GHF/GKS stability analysis'
        )
    return mo, stable_e
Ejemplo n.º 2
0
            def update_rotate_matrix(self, dx, mo_occ, u0=1):
                p0 = 0
                u = []
                for k, occ in enumerate(mo_occ):
                    occidx = occ > 0
                    viridx = ~occidx
                    nocc = occidx.sum()
                    nvir = viridx.sum()
                    nmo = nocc + nvir
                    dr = numpy.zeros((nmo, nmo), dtype=dx.dtype)
                    dr[viridx[:, None] & occidx] = dx[p0:p0 + nocc * nvir]
                    dr = dr - dr.T.conj()
                    p0 += nocc * nvir

                    u1 = newton_ah.expmat(dr)
                    if isinstance(u0, int) and u0 == 1:
                        u.append(u1)
                    else:
                        u.append(numpy.dot(u0[k], u1))
                return lib.asarray(u)
Ejemplo n.º 3
0
            def update_rotate_matrix(self, dx, mo_occ, u0=1):
                nmo = mo_occ.shape[-1]
                p0 = 0
                u = []
                for k, occ in enumerate(mo_occ):
                    occidx = occ > 0
                    viridx = ~occidx
                    nocc = occidx.sum()
                    nvir = nmo - nocc
                    dr = numpy.zeros((nmo,nmo), dtype=dx.dtype)
                    dr[viridx[:,None]&occidx] = dx[p0:p0+nocc*nvir]
                    dr = dr - dr.T.conj()
                    p0 += nocc * nvir

                    u1 = newton_ah.expmat(dr)
                    if isinstance(u0, int) and u0 == 1:
                        u.append(u1)
                    else:
                        u.append(numpy.dot(u0[k], u1))
                return lib.asarray(u)
Ejemplo n.º 4
0
 def update_rotate_matrix(self, dx, mo_occ, u0=1):
     nkpts = len(mo_occ[0])
     nmo = mo_occ[0].shape[-1]
     p0 = 0
     u = []
     for occ in mo_occ:
         ua = []
         for k in range(nkpts):
             occidx = occ[k] > 0
             viridx = ~occidx
             nocc = occidx.sum()
             nvir = nmo - nocc
             dr = numpy.zeros((nmo, nmo), dtype=dx.dtype)
             dr[viridx[:, None] & occidx] = dx[p0:p0 + nocc * nvir]
             dr = dr - dr.T.conj()
             p0 += nocc * nvir
             u1 = newton_ah.expmat(dr)
             if isinstance(u0, int) and u0 == 1:
                 ua.append(u1)
             else:
                 ua.append(numpy.dot(u0[k], u1))
         u.append(ua)
     return lib.asarray(u)
Ejemplo n.º 5
0
def _rotate_mo(mo_coeff, mo_occ, dx):
    dr = hf.unpack_uniq_var(dx, mo_occ)
    u = newton_ah.expmat(dr)
    return numpy.dot(mo_coeff, u)