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 __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 initial_greens_function_uhf(self, A, B, trial, nup, weights): r"""Compute initial green's function at timestep n for UHF wavefunction. Here we actually compute the equal-time green's function: .. math:: G_{ij} = \langle c_i c_j^{\dagger} \rangle Parameters ---------- A : :class:`numpy.ndarray` Left hand wavefunction for green's function. B : :class:`numpy.ndarray` Left hand wavefunction for green's function. trial : :class:`pauxy.trial_wavefunction.X' object Trial wavefunction class. nup : int Number of up electrons. weight : :class:`numpy.ndarray` Any GS orthogonalisation factors which need to be included. Returns ------- G_nn : :class:`numpy.ndarray` Green's function. """ Ggr_up = self.I - gab(A[:, :nup], B[:, :nup]) Ggr_down = self.I - gab(A[:, nup:], B[:, nup:]) Gls_up = self.I - Ggr_up Gls_down = self.I - Ggr_down return (numpy.array([Ggr_up, Ggr_down]), numpy.array([Gls_up, Gls_down]))
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 __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 find_uhf_wfn(self, system, cplx, ueff, ninit, nit_max, alpha, deps=1e-8, verbose=False): 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: 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 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)