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])
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
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
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)]
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
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
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()