Esempio n. 1
0
def test_walker_energy():
    numpy.random.seed(7)
    nelec = (2, 2)
    nmo = 5
    h1e, chol, enuc, eri = generate_hamiltonian(nmo, nelec, cplx=False)
    system = Generic(nelec=nelec,
                     h1e=h1e,
                     chol=chol,
                     ecore=enuc,
                     inputs={'integral_tensor': False})
    (e0, ev), (d, oa, ob) = simple_fci(system, gen_dets=True)
    na = system.nup
    init = get_random_wavefunction(nelec, nmo)
    init[:, :na], R = reortho(init[:, :na])
    init[:, na:], R = reortho(init[:, na:])
    trial = MultiSlater(system, (ev[:, 0], oa, ob), init=init)
    trial.calculate_energy(system)
    walker = MultiDetWalker({}, system, trial)
    nume = 0
    deno = 0
    for i in range(trial.ndets):
        psia = trial.psi[i, :, :na]
        psib = trial.psi[i, :, na:]
        oa = numpy.dot(psia.conj().T, init[:, :na])
        ob = numpy.dot(psib.conj().T, init[:, na:])
        isa = numpy.linalg.inv(oa)
        isb = numpy.linalg.inv(ob)
        ovlp = numpy.linalg.det(oa) * numpy.linalg.det(ob)
        ga = numpy.dot(init[:, :system.nup], numpy.dot(isa, psia.conj().T)).T
        gb = numpy.dot(init[:, system.nup:], numpy.dot(isb, psib.conj().T)).T
        e = local_energy(system, numpy.array([ga, gb]), opt=False)[0]
        nume += trial.coeffs[i].conj() * ovlp * e
        deno += trial.coeffs[i].conj() * ovlp
    print(nume / deno, nume, deno, e0[0])
Esempio n. 2
0
def back_propagate_single(phi_in,
                          configs,
                          weights,
                          system,
                          nstblz,
                          BT2,
                          store=False):
    r"""Perform back propagation for single walker.

    Parameters
    ---------
    phi_in : :class:`pauxy.walkers.Walker` object
        Walker.
    configs : :class:`numpy.ndarray`
        Auxilliary field configurations.
    weights : :class:`numpy.ndarray`
        Not used. For interface consistency.
    system : system object in general.
        Container for model input options.
    nstblz : int
        Number of steps between GS orthogonalisation.
    BT2 : :class:`numpy.ndarray`
        One body propagator.
    store : bool
        If true the the back propagated wavefunctions are stored along the back
        propagation path.

    Returns
    -------
    psi_store : list of :class:`pauxy.walker.Walker` objects
        Back propagated list of walkers.
    """
    nup = system.nup
    psi_store = []
    for (i, c) in enumerate(configs[::-1]):
        B = construct_propagator_matrix(system, BT2, c, conjt=True)
        phi_in[:, :nup] = B[0].dot(phi_in[:, :nup])
        phi_in[:, nup:] = B[1].dot(phi_in[:, nup:])
        if i != 0 and i % nstblz == 0:
            (phi_in[:, :nup], R) = reortho(phi_in[:, :nup])
            (phi_in[:, nup:], R) = reortho(phi_in[:, nup:])
        if store:
            psi_store.append(copy.deepcopy(phi_in))

    return psi_store
Esempio n. 3
0
def back_propagate_planewave(phi, stack, system, nstblz, BT2, dt, store=False):
    r"""Perform back propagation for RHF/UHF style wavefunction.

    For use with generic system hamiltonian.

    Parameters
    ---------
    system : system object in general.
        Container for model input options.
    psi : :class:`pauxy.walkers.Walkers` object
        CPMC wavefunction.
    trial : :class:`pauxy.trial_wavefunction.X' object
        Trial wavefunction class.
    nstblz : int
        Number of steps between GS orthogonalisation.
    BT2 : :class:`numpy.ndarray`
        One body propagator.
    dt : float
        Timestep.

    Returns
    -------
    psi_bp : list of :class:`pauxy.walker.Walker` objects
        Back propagated list of walkers.
    """
    nup = system.nup
    psi_store = []
    for (i, c) in enumerate(stack.get_block()[0][::-1]):
        B = construct_propagator_matrix_planewave(system, BT2, c, dt)
        phi[:, :nup] = numpy.dot(B[0].conj().T, phi[:, :nup])
        phi[:, nup:] = numpy.dot(B[1].conj().T, phi[:, nup:])
        if i != 0 and i % nstblz == 0:
            (phi[:, :nup], R) = reortho(phi[:, :nup])
            (phi[:, nup:], R) = reortho(phi[:, nup:])
        if store:
            psi_store.append(phi.copy())

    return psi_store
Esempio n. 4
0
def unit_test():
    from pauxy.systems.ueg import UEG
    import numpy as np
    inputs = {'nup': 7, 'ndown': 7, 'rs': 1.0, 'ecut': 2.0}
    system = UEG(inputs, True)
    nbsf = system.nbasis
    Pa = np.zeros([nbsf, nbsf], dtype=np.complex128)
    Pb = np.zeros([nbsf, nbsf], dtype=np.complex128)
    na = system.nup
    nb = system.ndown
    for i in range(na):
        Pa[i, i] = 1.0
    for i in range(nb):
        Pb[i, i] = 1.0
    P = np.array([Pa, Pb])
    etot, ekin, epot = local_energy_ueg(system, G=P)
    print("ERHF = {}, {}, {}".format(etot, ekin, epot))

    from pauxy.utils.linalg import exponentiate_matrix, reortho
    from pauxy.estimators.greens_function import gab
    # numpy.random.seed()
    rCa = numpy.random.randn(nbsf, na)
    zCa = numpy.random.randn(nbsf, na)
    rCb = numpy.random.randn(nbsf, nb)
    zCb = numpy.random.randn(nbsf, nb)

    Ca = rCa + 1j * zCa
    Cb = rCb + 1j * zCb

    Ca, detR = reortho(Ca)
    Cb, detR = reortho(Cb)
    # S = print(Ca.dot(Cb.T))
    # print(S)
    # exit()
    Ca = numpy.array(Ca, dtype=numpy.complex128)
    Cb = numpy.array(Cb, dtype=numpy.complex128)
    P = [gab(Ca, Ca), gab(Cb, Cb)]
Esempio n. 5
0
def back_propagate_single_ghf(phi,
                              configs,
                              weights,
                              system,
                              nstblz,
                              BT2,
                              store=False):
    r"""Perform back propagation for single walker.

    Parameters
    ---------
    phi : :class:`pauxy.walkers.MultiGHFWalker` object
        Walker.
    configs : :class:`numpy.ndarray`
        Auxilliary field configurations.
    weights : :class:`numpy.ndarray`
        Not used. For interface consistency.
    system : system object in general.
        Container for model input options.
    nstblz : int
        Number of steps between GS orthogonalisation.
    BT2 : :class:`numpy.ndarray`
        One body propagator.
    store : bool
        If true the the back propagated wavefunctions are stored along the back
        propagation path.

    Returns
    -------
    psi_store : list of :class:`pauxy.walker.Walker` objects
        Back propagated list of walkers.
    """
    nup = system.nup
    psi_store = []
    for (i, c) in enumerate(configs[::-1]):
        B = construct_propagator_matrix_ghf(system, BT2, c, conjt=True)
        for (idet, psi_i) in enumerate(phi):
            # propagate each component of multi-determinant expansion
            phi[idet] = B.dot(phi[idet])
            if i != 0 and i % nstblz == 0:
                # implicitly propagating the full GHF wavefunction
                (phi[idet], detR) = reortho(psi_i)
                weights[idet] *= detR.conjugate()
        if store:
            psi_store.append(copy.deepcopy(phi))

    return psi_store
Esempio n. 6
0
def back_propagate_ghf(system, psi, trial, nstblz, BT2, dt):
    r"""Perform back propagation for GHF style wavefunction.

    Parameters
    ---------
    system : system object in general.
        Container for model input options.
    psi : :class:`pauxy.walkers.Walkers` object
        CPMC wavefunction.
    trial : :class:`pauxy.trial_wavefunction.X' object
        Trial wavefunction class.
    nstblz : int
        Number of steps between GS orthogonalisation.
    BT2 : :class:`numpy.ndarray`
        One body propagator.
    dt : float
        Timestep.

    Returns
    -------
    psi_bp : list of :class:`pauxy.walker.Walker` objects
        Back propagated list of walkers.
    """
    psi_bp = [
        MultiGHFWalker(1, system, trial, w, weights='ones', wfn0='GHF')
        for w in range(len(psi))
    ]
    for (iw, w) in enumerate(psi):
        # propagators should be applied in reverse order
        for (i, c) in enumerate(w.field_configs.get_block()[0][::-1]):
            B = construct_propagator_matrix_ghf(system, BT2, c, conjt=True)
            for (idet, psi_i) in enumerate(psi_bp[iw].phi):
                # propagate each component of multi-determinant expansion
                psi_bp[iw].phi[idet] = B.dot(psi_bp[iw].phi[idet])
                if i != 0 and i % nstblz == 0:
                    # implicitly propagating the full GHF wavefunction
                    (psi_bp[iw].phi[idet], detR) = reortho(psi_i)
                    psi_bp[iw].weights[idet] *= detR.conjugate()
    return psi_bp
Esempio n. 7
0
    def calculate_spgf_stable(self, system, psi, trial):
        """Calculate imaginary time single-particle green's function.

        This uses the stable algorithm as outlined in:
        Feldbacher and Assad, Phys. Rev. B 63, 073105.

        On return the spgf estimator array will have been updated.

        Parameters
        ----------
        system : system object in general.
            Container for model input options.
        psi : :class:`pauxy.walkers.Walkers` object
            CPMC wavefunction.
        trial : :class:`pauxy.trial_wavefunction.X' object
            Trial wavefunction class.
        """

        nup = system.nup
        M = system.nbasis
        if self.restore_weights:
            self.denom = sum(w.weight * w.stack.wfac[0] / w.stack.wfac[1]
                             for w in psi.walkers)
        else:
            self.denom = sum(w.weight for w in psi.walkers)
        for ix, w in enumerate(psi.walkers):
            Ggr = numpy.array([self.I.copy(), self.I.copy()])
            Gls = numpy.array([self.I.copy(), self.I.copy()])
            # 1. Construct psi_L for first step in algorithm by back
            # propagating the input back propagated left hand wfn.
            # Note we use the first itcf_nmax fields for estimating the ITCF.
            # We store for intermediate back propagated left-hand wavefunctions.
            # This leads to more stable equal time green's functions compared to
            # that found by multiplying psi_L^n by B^{-1}(x^(n)) factors.
            phi_left = trial.psi.copy()
            psi_Ls = self.back_propagate_single(phi_left,
                                                w.stack,
                                                system,
                                                self.nstblz,
                                                self.BT2,
                                                self.dt,
                                                store=True)
            # 2. Calculate G(n,n). This is the equal time Green's function at
            # the step where we began saving auxilary fields (constructed with
            # psi_L back propagated along this path.)
            (Ggr_nn,
             Gls_nn) = self.initial_greens_function(phi_left, w.phi_right,
                                                    trial, nup, w.weights)
            # 3. Construct ITCF by moving forwards in imaginary time from time
            # slice n along our auxiliary field path.
            if self.restore_weights:
                wfac = w.weight * w.stack.wfac[0] / w.stack.wfac[1]
            else:
                wfac = w.weight
            self.accumulate(0, wfac, Ggr_nn, Gls_nn, M)
            for ic in range(self.nmax // w.stack.stack_size):
                # B takes the state from time n to time n+1.
                B = w.stack.get(ic)
                # G is the cumulative product of stabilised short-time ITCFs.
                # The first term in brackets is the G(n+1,n) which should be
                # well conditioned.
                (Ggr, Gls) = self.increment_tau(Ggr, Gls, B, Ggr_nn, Gls_nn)
                self.accumulate(ic + 1, wfac, Ggr, Gls, M)
                # Construct equal-time green's function shifted forwards along
                # the imaginary time interval. We need to update |psi_L> =
                # (B(c)^{dagger})^{-1}|psi_L> and |psi_R> = B(c)|psi_R>, where c
                # is the current configution in this loop. Note that we store
                # |psi_L> along the path, so we don't need to remove the
                # propagator matrices.
                L = psi_Ls[len(psi_Ls) - ic - 1]
                propagate_single(w.phi_right, system, B)
                if ic != 0 and ic % self.nstblz == 0:
                    (w.phi_right[:, :nup], R) = reortho(w.phi_right[:, :nup])
                    (w.phi_right[:, nup:], R) = reortho(w.phi_right[:, nup:])
                (Ggr_nn, Gls_nn) = self.initial_greens_function(
                    L, w.phi_right, trial, nup, w.weights)
            w.stack.reset()
        # copy current walker distribution to initial (right hand) wavefunction
        # for next estimate of ITCF
        psi.copy_init_wfn()