def __init__(self, weight, system, trial, index=0): self.weight = weight self.alive = 1 if trial.initial_wavefunction == 'free_electron': self.phi = numpy.zeros(shape=(system.nbasis, system.ne), dtype=trial.psi.dtype) tmp = FreeElectron(system, system.ktwist.all() != None, {}) self.phi[:, :system.nup] = tmp.psi[:, :system.nup] self.phi[:, system.nup:] = tmp.psi[:, system.nup:] else: self.phi = copy.deepcopy(trial.psi) self.inv_ovlp = [0, 0] self.nup = system.nup self.inverse_overlap(trial.psi) self.G = numpy.zeros(shape=(2, system.nbasis, system.nbasis), dtype=trial.psi.dtype) self.Gmod = numpy.zeros(shape=(2, system.nbasis, system.nup), dtype=trial.psi.dtype) self.greens_function(trial) self.ot = 1.0 # interface consistency self.ots = numpy.zeros(1) self.E_L = local_energy(system, self.G)[0].real # walkers overlap at time tau before backpropagation occurs self.ot_bp = 1.0 # walkers weight at time tau before backpropagation occurs self.weight_bp = weight # Historic wavefunction for back propagation. self.phi_old = copy.deepcopy(self.phi) # Historic wavefunction for ITCF. self.phi_init = copy.deepcopy(self.phi) # Historic wavefunction for ITCF. self.phi_bp = copy.deepcopy(self.phi) self.weights = numpy.array([1])
def calculate_energy(self, system): if self.verbose: print("# Computing trial energy.") (self.energy, self.e1b, self.e2b) = local_energy(system, self.G) if self.verbose: print("# (E, E1B, E2B): (%13.8e, %13.8e, %13.8e)" % (self.energy.real, self.e1b.real, self.e2b.real))
def __init__(self, system, cplx, trial, parallel=False, verbose=False): if verbose: print("# Parsing Hartree--Fock trial wavefunction input options.") init_time = time.time() self.name = "hartree_fock" self.type = "hartree_fock" self.initial_wavefunction = trial.get('initial_wavefunction', 'hartree_fock') self.trial_type = complex self.psi = numpy.zeros(shape=(system.nbasis, system.nup + system.ndown), dtype=self.trial_type) occup = numpy.identity(system.nup) occdown = numpy.identity(system.ndown) self.psi[:system.nup, :system.nup] = occup self.psi[:system.ndown, system.nup:] = occdown gup = gab(self.psi[:, :system.nup], self.psi[:, :system.nup]) gdown = gab(self.psi[:, system.nup:], self.psi[:, system.nup:]) self.G = numpy.array([gup, gdown]) (self.energy, self.e1b, self.e2b) = local_energy(system, self.G) self.coeffs = 1.0 self.bp_wfn = trial.get('bp_wfn', None) self.error = False self.initialisation_time = time.time() - init_time if verbose: print("# Finished setting up trial wavefunction.")
def recompute_ci_coeffs(self, system): H = numpy.zeros((self.ndets, self.ndets), dtype=numpy.complex128) S = numpy.zeros((self.ndets, self.ndets), dtype=numpy.complex128) if self.ortho_expansion: for i in range(self.ndets): for j in range(i, self.ndets): di = self.spin_occs[i] dj = self.spin_occs[j] H[i, j] = get_hmatel(system, di, dj)[0] e, ev = scipy.linalg.eigh(H, lower=False) else: na = system.nup for i, di in enumerate(self.psi): for j, dj in enumerate(self.psi): if j >= i: ga, gha, ioa = gab_mod_ovlp(di[:, :na], dj[:, :na]) gb, ghb, iob = gab_mod_ovlp(di[:, na:], dj[:, na:]) G = numpy.array([ga, gb]) Ghalf = numpy.array([gha, ghb]) ovlp = 1.0 / (scipy.linalg.det(ioa) * scipy.linalg.det(iob)) if abs(ovlp) > 1e-12: H[i, j] = ovlp * local_energy( system, G, Ghalf=Ghalf)[0] S[i, j] = ovlp H[j, i] = numpy.conjugate(H[i, j]) S[j, i] = numpy.conjugate(S[i, j]) e, ev = scipy.linalg.eigh(H, S, lower=False) if self.verbose > 1: print("Old and New CI coefficients: ") for co, cn in zip(self.coeffs, ev[:, 0]): print("{} {}".format(co, cn)) self.coeffs = numpy.array(ev[:, 0], dtype=numpy.complex128)
def __init__(self, system, cplx, trial, parallel=False, verbose=False): if verbose: print("# Constructing UHF trial wavefunction") init_time = time.time() self.name = "UHF" self.type = "UHF" self.initial_wavefunction = trial.get('initial_wavefunction', 'trial') if cplx: self.trial_type = complex else: self.trial_type = float # Unpack input options. self.ninitial = trial.get('ninitial', 10) self.nconv = trial.get('nconv', 5000) self.ueff = trial.get('ueff', 0.4) self.deps = trial.get('deps', 1e-8) self.alpha = trial.get('alpha', 0.5) # For interface compatability self.coeffs = 1.0 self.ndets = 1 (self.psi, self.eigs, self.emin, self.error, self.nav) = (self.find_uhf_wfn(system, cplx, self.ueff, self.ninitial, self.nconv, self.alpha, self.deps, verbose)) if self.error and not parallel: warnings.warn('Error in constructing trial wavefunction. Exiting') sys.exit() Gup = gab(self.psi[:, :system.nup], self.psi[:, :system.nup]).T Gdown = gab(self.psi[:, system.nup:], self.psi[:, system.nup:]).T self.G = numpy.array([Gup, Gdown]) self.etrial = local_energy(system, self.G)[0].real self.bp_wfn = trial.get('bp_wfn', None) self.initialisation_time = time.time() - init_time
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 calculate_energy(self, system): if self.verbose: print("# Computing trial wavefunction energy.") start = time.time() (self.energy, self.e1b, self.e2b) = local_energy(system, self.G, Ghalf=[self.gup_half, self.gdown_half], opt=True) if self.verbose: print("# (E, E1B, E2B): (%13.8e, %13.8e, %13.8e)" % (self.energy.real, self.e1b.real, self.e2b.real)) print("# Time to evaluate local energy: %f s" % (time.time() - start))
def local_energy(self, system): """Compute walkers local energy Parameters ---------- system : object System object. Returns ------- (E, T, V) : tuple Mixed estimates for walker's energy components. """ return local_energy(system, self.G)
def update_uhf(self, system, qmc, trial, psi, step, free_projection=False): """Calculate back-propagated estimates for RHF/UHF walkers. Parameters ---------- system : system object in general. Container for model input options. qmc : :class:`pauxy.state.QMCOpts` object. Container for qmc input options. trial : :class:`pauxy.trial_wavefunction.X' object Trial wavefunction class. psi : :class:`pauxy.walkers.Walkers` object CPMC wavefunction. step : int Current simulation step free_projection : bool True if doing free projection. """ if step % self.nmax != 0: return psi_bp = self.back_propagate(system, psi.walkers, trial, self.nstblz, self.BT2, qmc.dt) nup = system.nup denominator = 0 for i, (wnm, wb) in enumerate(zip(psi.walkers, psi_bp)): self.G[0] = gab(wb.phi[:, :nup], wnm.phi_old[:, :nup]).T self.G[1] = gab(wb.phi[:, nup:], wnm.phi_old[:, nup:]).T energies = numpy.array(list(local_energy(system, self.G))) if self.restore_weights is not None: weight = wnm.weight * self.calculate_weight_factor(wnm) else: weight = wnm.weight denominator += weight self.estimates[1:] = ( self.estimates[1:] + weight * numpy.append(energies, self.G.flatten())) self.estimates[0] += denominator psi.copy_historic_wfn() psi.copy_bp_wfn(psi_bp)
def scf(self, system, beta, mu, P): # 1. Compute HMF HMF = fock_matrix(system, P) dt = self.dtau muN = mu * numpy.eye(system.nbasis, dtype=self.G.dtype) rho = numpy.array([ scipy.linalg.expm(-dt * (HMF[0] - muN)), scipy.linalg.expm(-dt * (HMF[1] - muN)) ]) Pold = one_rdm_stable(rho, self.num_bins) if self.verbose: print(" # Running Thermal SCF.") for it in range(self.max_scf_it): HMF = fock_matrix(system, Pold) rho = numpy.array([ scipy.linalg.expm(-dt * (HMF[0] - muN)), scipy.linalg.expm(-dt * (HMF[1] - muN)) ]) Pnew = (1 - self.alpha) * one_rdm_stable( rho, self.num_bins) + self.alpha * Pold change = numpy.linalg.norm(Pnew - Pold) if change < self.deps: break if self.verbose: N = particle_number(P).real E = local_energy(system, P, opt=False)[0].real S = entropy(beta, mu, HMF) omega = E - mu * N - 1.0 / beta * S print( " # Iteration: {:4d} dP: {:13.8e} Omega: {:13.8e}".format( it, change, omega.real)) Pold = Pnew.copy() if self.verbose: N = particle_number(P).real print(" # Average particle number: {:13.8e}".format(N)) return HMF
def find_uhf_wfn(self, system, cplx, ueff, ninit, nit_max, alpha, deps=1e-8, verbose=0): emin = 0 uold = system.U system.U = ueff minima = [] # Local minima nup = system.nup # Search over different random starting points. for attempt in range(0, ninit): # Set up initial (random) guess for the density. (self.trial, eold) = self.initialise(system.nbasis, system.nup, system.ndown, cplx) niup = self.density(self.trial[:, :nup]) nidown = self.density(self.trial[:, nup:]) niup_old = self.density(self.trial[:, :nup]) nidown_old = self.density(self.trial[:, nup:]) for it in range(0, nit_max): (niup, nidown, e_up, e_down) = (self.diagonalise_mean_field( system, ueff, niup, nidown)) # Construct Green's function to compute the energy. Gup = gab(self.trial[:, :nup], self.trial[:, :nup]).T Gdown = gab(self.trial[:, nup:], self.trial[:, nup:]).T enew = local_energy(system, numpy.array([Gup, Gdown]))[0].real if verbose > 1: print("# %d %f %f" % (it, enew, eold)) sc = self.self_consistant(enew, eold, niup, niup_old, nidown, nidown_old, it, deps, verbose) if sc: # Global minimum search. if attempt == 0: minima.append(enew) psi_accept = copy.deepcopy(self.trial) e_accept = numpy.append(e_up, e_down) elif all(numpy.array(minima) - enew > deps): minima.append(enew) psi_accept = copy.deepcopy(self.trial) e_accept = numpy.append(e_up, e_down) break else: mixup = self.mix_density(niup, niup_old, alpha) mixdown = self.mix_density(nidown, nidown_old, alpha) niup_old = niup nidown_old = nidown niup = mixup nidown = mixdown eold = enew if verbose > 1: print("# SCF cycle: {:3d}. After {:4d} steps the minimum UHF" " energy found is: {: 8f}".format(attempt, it, eold)) system.U = uold print("# Minimum energy found: {: 8f}".format(min(minima))) try: return (psi_accept, e_accept, min(minima), False, [niup, nidown]) except UnboundLocalError: warnings.warn("Warning: No UHF wavefunction found." "Delta E: %f" % (enew - emin)) return (trial, numpy.append(e_up, e_down), None, True, None)
def __init__(self, system, cplx, trial, parallel=False, verbose=False): if verbose: print ("# Parsing free electron input options.") init_time = time.time() self.name = "free_electron" self.type = "free_electron" self.initial_wavefunction = trial.get('initial_wavefunction', 'free_electron') if verbose: print ("# Diagonalising one-body Hamiltonian.") (self.eigs_up, self.eigv_up) = diagonalise_sorted(system.T[0]) (self.eigs_dn, self.eigv_dn) = diagonalise_sorted(system.T[1]) self.reference = trial.get('reference', None) if cplx: self.trial_type = complex else: self.trial_type = float self.read_in = trial.get('read_in', None) self.psi = numpy.zeros(shape=(system.nbasis, system.nup+system.ndown), dtype=self.trial_type) if self.read_in is not None: if verbose: print ("# Reading trial wavefunction from %s"%(self.read_in)) try: self.psi = numpy.load(self.read_in) self.psi = self.psi.astype(self.trial_type) except OSError: if verbose: print("# Trial wavefunction is not in native numpy form.") print("# Assuming Fortran GHF format.") orbitals = read_fortran_complex_numbers(self.read_in) tmp = orbitals.reshape((2*system.nbasis, system.ne), order='F') ups = [] downs = [] # deal with potential inconsistency in ghf format... for (i, c) in enumerate(tmp.T): if all(abs(c[:system.nbasis]) > 1e-10): ups.append(i) else: downs.append(i) self.psi[:, :system.nup] = tmp[:system.nbasis, ups] self.psi[:, system.nup:] = tmp[system.nbasis:, downs] else: # I think this is slightly cleaner than using two separate # matrices. if self.reference is not None: self.psi[:, :system.nup] = self.eigv_up[:, self.reference] self.psi[:, system.nup:] = self.eigv_dn[:, self.reference] else: self.psi[:, :system.nup] = self.eigv_up[:, :system.nup] self.psi[:, system.nup:] = self.eigv_dn[:, :system.ndown] gup = gab(self.psi[:, :system.nup], self.psi[:, :system.nup]).T gdown = gab(self.psi[:, system.nup:], self.psi[:, system.nup:]).T self.G = numpy.array([gup, gdown]) self.etrial = local_energy(system, self.G)[0].real # For interface compatability self.coeffs = 1.0 self.ndets = 1 self.bp_wfn = trial.get('bp_wfn', None) self.error = False self.eigs = numpy.append(self.eigs_up, self.eigs_dn) self.eigs.sort() self.initialisation_time = time.time() - init_time if verbose: print ("# Finished initialising free electron trial wavefunction.")
def local_energy(self, system, two_rdm=None): rdm = one_rdm_from_G(self.G) return local_energy(system, rdm, two_rdm=two_rdm, opt=False)
def __init__(self, walker_opts, system, trial, index=0, nprop_tot=None, nbp=None): self.weight = walker_opts.get('weight', 1.0) self.unscaled_weight = self.weight self.phase = 1 + 0j self.alive = 1 self.phi = trial.init.copy() # JOONHO randomizing the guess # self.phi = numpy.random.rand([system.nbasis,system.ne]) self.inv_ovlp = [0.0, 0.0] self.nup = system.nup self.ndown = system.ndown self.inverse_overlap(trial) self.G = numpy.zeros(shape=(2, system.nbasis, system.nbasis), dtype=trial.psi.dtype) self.Gmod = [ numpy.zeros(shape=(system.nup, system.nbasis), dtype=trial.psi.dtype), numpy.zeros(shape=(system.ndown, system.nbasis), dtype=trial.psi.dtype) ] self.greens_function(trial) self.total_weight = 0.0 self.ot = 1.0 # interface consistency self.ots = numpy.zeros(1, dtype=numpy.complex128) self.E_L = local_energy(system, self.G, self.Gmod)[0].real # walkers overlap at time tau before backpropagation occurs self.ot_bp = 1.0 # walkers weight at time tau before backpropagation occurs self.weight_bp = self.weight # Historic wavefunction for back propagation. self.phi_old = copy.deepcopy(self.phi) self.hybrid_energy = 0.0 # Historic wavefunction for ITCF. self.phi_right = copy.deepcopy(self.phi) self.weights = numpy.array([1.0]) # Number of propagators to store for back propagation / ITCF. num_propg = walker_opts.get('num_propg', 1) # if system.name == "Generic": # self.stack = PropagatorStack(self.stack_size, num_propg, # system.nbasis, trial.psi.dtype, # BT=None, BTinv=None, # diagonal=False) try: excite = trial.excite_ia except AttributeError: excite = None if excite is not None: self.ia = trial.excite_ia self.reortho = self.reortho_excite self.trial_buff = numpy.copy(trial.full_orbs[:, :self.ia[1] + 1]) if nbp is not None: self.field_configs = FieldConfig(system.nfields, nprop_tot, nbp, numpy.complex128) else: self.field_configs = None self.buff_names, self.buff_size = get_numeric_names(self.__dict__)
"mu": 0.2, "sparse": False, "integrals": "hamil.h5" } system = Generic(inputs=sys_opts) # trial = OneBody(comm, system, 1.0, 0.05, verbose=True) mus = numpy.arange(-1, 1) data = [] dt = 0.05 fci = pd.read_csv('be_fixed_n.out', sep=r'\s+') for b, n in zip(fci.beta, fci.N): trial = OneBody(comm, system, b, dt, options={"nav": n}, verbose=True) data.append([ local_energy(system, trial.P, opt=False)[0].real, particle_number(trial.P).real ]) pl.plot(fci.beta, zip(*data)[0], label='Match N') match = zip(*data)[0] data = [] for b, n in zip(fci.beta, fci.N): trial = MeanField(comm, system, b, dt, options={"nav": n}, verbose=True) data.append([ local_energy(system, trial.P, opt=False)[0].real, particle_number(trial.P).real ]) pl.plot(fci.beta, fci.E, label='FCI') pl.plot(fci.beta, zip(*data)[0], label='THF', linestyle=':') data = pd.DataFrame({ 'beta': fci.beta,
def update_uhf(self, system, qmc, trial, psi, step, free_projection=False): """Calculate back-propagated estimates for RHF/UHF walkers. Parameters ---------- system : system object in general. Container for model input options. qmc : :class:`pauxy.state.QMCOpts` object. Container for qmc input options. trial : :class:`pauxy.trial_wavefunction.X' object Trial wavefunction class. psi : :class:`pauxy.walkers.Walkers` object CPMC wavefunction. step : int Current simulation step free_projection : bool True if doing free projection. """ buff_ix = psi.walkers[0].field_configs.step if buff_ix not in self.splits: return nup = system.nup for i, wnm in enumerate(psi.walkers): if self.init_walker: phi_bp = trial.init.copy() else: phi_bp = trial.psi.copy() # TODO: Fix for ITCF. self.back_propagate(phi_bp, wnm.field_configs, system, self.nstblz, self.BT2, self.dt) self.G[0] = gab(phi_bp[:, :nup], wnm.phi_old[:, :nup]).T self.G[1] = gab(phi_bp[:, nup:], wnm.phi_old[:, nup:]).T if self.eval_energy: eloc = local_energy(system, self.G, opt=False, two_rdm=self.two_rdm) energies = numpy.array(list(eloc)) else: energies = numpy.zeros(3) if self.calc_two_rdm is not None and self.calc_two_rdm is not "structure_factor": # <p^+ q^+ s r> = G(p, r, q, s) also spin-summed self.two_rdm = numpy.einsum("pr,qs->prqs",self.G[0], self.G[0], optimize=True)\ - numpy.einsum("ps,qr->prqs",self.G[0], self.G[0], optimize=True) self.two_rdm += numpy.einsum("pr,qs->prqs",self.G[1], self.G[1], optimize=True)\ - numpy.einsum("ps,qr->prqs",self.G[1], self.G[1], optimize=True) self.two_rdm += numpy.einsum("pr,qs->prqs",self.G[0], self.G[1], optimize=True)\ + numpy.einsum("pr,qs->prqs",self.G[1], self.G[0], optimize=True) if self.eval_ekt: if (system.name == 'UEG'): # there needs to be a factor of 2.0 here to account for the convention of cholesky vectors in the system class chol_vecs = 2.0 * system.chol_vecs.toarray().T.reshape( (system.nchol, system.nbasis, system.nbasis)) self.ekt_fock_1p = ekt_1p_fock_opt(system.H1[0], chol_vecs, self.G[0], self.G[1]) self.ekt_fock_1h = ekt_1h_fock_opt(system.H1[0], chol_vecs, self.G[0], self.G[1]) else: self.ekt_fock_1p = ekt_1p_fock_opt(system.H1[0], system.chol_vecs, self.G[0], self.G[1]) self.ekt_fock_1h = ekt_1h_fock_opt(system.H1[0], system.chol_vecs, self.G[0], self.G[1]) if self.restore_weights is not None: cosine_fac, ph_fac = wnm.field_configs.get_wfac() if self.restore_weights == "full": # BP-Pres wfac = ph_fac / cosine_fac else: # BP-PRes (partial) wfac = ph_fac weight = wnm.weight * wfac else: # BP-PhL weight = wnm.weight self.estimates[:self.nreg] += weight * energies self.estimates[self.nreg] += weight start = self.nreg + 1 end = start + self.G.size self.estimates[start:end] += weight * self.G.flatten() if self.calc_two_rdm is not None: start = end end = end + self.two_rdm.size self.estimates[start:end] += weight * self.two_rdm.flatten() if self.eval_ekt: start = end end = end + self.ekt_fock_1p.size self.estimates[start:end] += weight * self.ekt_fock_1p.flatten( ) start = end end = end + self.ekt_fock_1h.size self.estimates[start:end] += weight * self.ekt_fock_1h.flatten( ) if buff_ix == self.splits[-1]: wnm.field_configs.reset() if buff_ix == self.splits[-1]: psi.copy_historic_wfn() self.accumulated = True self.buff_ix = buff_ix