def fock_loop(agf2, eri, gf, se): ''' Self-consistent loop for the density matrix via the HF self- consistent field. Args: eri : _ChemistERIs Electronic repulsion integrals gf : GreensFunction Auxiliaries of the Green's function se : SelfEnergy Auxiliaries of the self-energy Returns: :class:`SelfEnergy`, :class:`GreensFunction` and a boolean indicating wheter convergence was successful. ''' assert type(gf) is aux.GreensFunction assert type(se) is aux.SelfEnergy cput0 = cput1 = (logger.process_clock(), logger.perf_counter()) log = logger.Logger(agf2.stdout, agf2.verbose) diis = lib.diis.DIIS(agf2) diis.space = agf2.fock_diis_space diis.min_space = agf2.fock_diis_min_space fock = agf2.get_fock(eri, gf) nelec = eri.nocc * 2 nmo = eri.nmo naux = se.naux nqmo = nmo + naux buf = np.zeros((nqmo, nqmo)) converged = False opts = dict(tol=agf2.conv_tol_nelec, maxiter=agf2.max_cycle_inner) rdm1_prev = 0 for niter1 in range(1, agf2.max_cycle_outer + 1): se, opt = minimize_chempot(se, fock, nelec, x0=se.chempot, **opts) for niter2 in range(1, agf2.max_cycle_inner + 1): w, v = se.eig(fock, chempot=0.0, out=buf) se.chempot, nerr = binsearch_chempot((w, v), nmo, nelec) w, v = se.eig(fock, out=buf) gf = aux.GreensFunction(w, v[:nmo], chempot=se.chempot) fock = agf2.get_fock(eri, gf) rdm1 = agf2.make_rdm1(gf) fock = diis.update(fock, xerr=None) if niter2 > 1: derr = np.max(np.absolute(rdm1 - rdm1_prev)) if derr < agf2.conv_tol_rdm1: break rdm1_prev = rdm1.copy() log.debug1('fock loop %d cycles = %d dN = %.3g |ddm| = %.3g', niter1, niter2, nerr, derr) cput1 = log.timer_debug1('fock loop %d' % niter1, *cput1) if derr < agf2.conv_tol_rdm1 and abs(nerr) < agf2.conv_tol_nelec: converged = True break log.info('fock converged = %s chempot = %.9g dN = %.3g |ddm| = %.3g', converged, se.chempot, nerr, derr) log.timer('fock loop', *cput0) return gf, se, converged
def fock_loop(agf2, eri, gf, se): ''' Self-consistent loop for the density matrix via the HF self- consistent field. Args: eri : _ChemistsERIs Electronic repulsion integrals gf : tuple of GreensFunction Auxiliaries of the Green's function for each spin se : tuple of SelfEnergy Auxiliaries of the self-energy for each spin Returns: :class:`SelfEnergy`, :class:`GreensFunction` and a boolean indicating whether convergence was successful. ''' assert type(gf[0]) is aux.GreensFunction assert type(gf[1]) is aux.GreensFunction assert type(se[0]) is aux.SelfEnergy assert type(se[1]) is aux.SelfEnergy cput0 = cput1 = (time.clock(), time.time()) log = logger.Logger(agf2.stdout, agf2.verbose) diis = lib.diis.DIIS(agf2) diis.space = agf2.fock_diis_space diis.min_space = agf2.fock_diis_min_space focka, fockb = agf2.get_fock(eri, gf) sea, seb = se gfa, gfb = gf nalph, nbeta = agf2.nocc nmoa, nmob = eri.nmo nauxa, nauxb = sea.naux, seb.naux nqmoa, nqmob = nauxa+nmoa, nauxb+nmob bufa, bufb = np.zeros((nqmoa, nqmoa)), np.zeros((nqmob, nqmob)) converged = False opts = dict(tol=agf2.conv_tol_nelec, maxiter=agf2.max_cycle_inner) for niter1 in range(1, agf2.max_cycle_outer+1): sea, opt = minimize_chempot(sea, focka, nalph, x0=sea.chempot, occupancy=1, **opts) seb, opt = minimize_chempot(seb, fockb, nbeta, x0=seb.chempot, occupancy=1, **opts) for niter2 in range(1, agf2.max_cycle_inner+1): wa, va = sea.eig(focka, chempot=0.0, out=bufa) wb, vb = seb.eig(fockb, chempot=0.0, out=bufb) sea.chempot, nerra = \ binsearch_chempot((wa, va), nmoa, nalph, occupancy=1) seb.chempot, nerrb = \ binsearch_chempot((wb, vb), nmob, nbeta, occupancy=1) nerr = max(nerra, nerrb) wa, va = sea.eig(focka, out=bufa) wb, vb = seb.eig(fockb, out=bufb) gfa = aux.GreensFunction(wa, va[:nmoa], chempot=sea.chempot) gfb = aux.GreensFunction(wb, vb[:nmob], chempot=seb.chempot) gf = (gfa, gfb) focka, fockb = agf2.get_fock(eri, gf) rdm1a, rdm1b = agf2.make_rdm1(gf) focka, fockb = diis.update(np.array((focka, fockb)), xerr=None) if niter2 > 1: derra = np.max(np.absolute(rdm1a - rdm1a_prev)) derrb = np.max(np.absolute(rdm1b - rdm1b_prev)) derr = max(derra, derrb) if derr < agf2.conv_tol_rdm1: break rdm1a_prev = rdm1a.copy() rdm1b_prev = rdm1b.copy() log.debug1('fock loop %d cycles = %d dN = %.3g |ddm| = %.3g', niter1, niter2, nerr, derr) cput1 = log.timer_debug1('fock loop %d'%niter1, *cput1) if derr < agf2.conv_tol_rdm1 and abs(nerr) < agf2.conv_tol_nelec: converged = True break se = (sea, seb) log.info('fock converged = %s' % converged) log.info(' alpha: chempot = %.9g dN = %.3g |ddm| = %.3g', sea.chempot, nerra, derra) log.info(' beta: chempot = %.9g dN = %.3g |ddm| = %.3g', seb.chempot, nerrb, derrb) log.timer('fock loop', *cput0) return gf, se, converged