def uhf_external(mf, with_symmetry=True, verbose=None): log = logger.new_logger(mf, verbose) hop1, hdiag1, hop2, hdiag2 = _gen_hop_uhf_external(mf, with_symmetry) def precond(dx, e, x0): hdiagd = hdiag1 - e hdiagd[abs(hdiagd) < 1e-8] = 1e-8 return dx / hdiagd x0 = numpy.zeros_like(hdiag1) x0[hdiag1 > 1e-5] = 1. / hdiag1[hdiag1 > 1e-5] if not with_symmetry: # allow to break point group symmetry x0[numpy.argmin(hdiag1)] = 1 e1, v = lib.davidson(hop1, x0, precond, tol=1e-4, verbose=log) if e1 < -1e-5: log.note('UHF/UKS wavefunction has a real -> complex instablity') else: log.note( 'UHF/UKS wavefunction is stable in the real -> complex stability analysis' ) def precond(dx, e, x0): hdiagd = hdiag2 - e hdiagd[abs(hdiagd) < 1e-8] = 1e-8 return dx / hdiagd x0 = numpy.zeros_like(hdiag2) x0[hdiag2 > 1e-5] = 1. / hdiag2[hdiag2 > 1e-5] if not with_symmetry: # allow to break point group symmetry x0[numpy.argmin(hdiag2)] = 1 e3, v = lib.davidson(hop2, x0, precond, tol=1e-4, verbose=log) log.debug('uhf_external: lowest eigs of H = %s', e3) mo = scipy.linalg.block_diag(*mf.mo_coeff) if e3 < -1e-5: log.note('UHF/UKS wavefunction has an UHF/UKS -> GHF/GKS instablity.') occidxa = numpy.where(mf.mo_occ[0] > 0)[0] viridxa = numpy.where(mf.mo_occ[0] == 0)[0] occidxb = numpy.where(mf.mo_occ[1] > 0)[0] viridxb = numpy.where(mf.mo_occ[1] == 0)[0] nocca = len(occidxa) nvira = len(viridxa) noccb = len(occidxb) nvirb = len(viridxb) nmo = nocca + nvira dx = numpy.zeros((nmo * 2, nmo * 2)) dx[viridxa[:, None], nmo + occidxb] = v[:nvira * noccb].reshape(nvira, noccb) dx[nmo + viridxb[:, None], occidxa] = v[nvira * noccb:].reshape(nvirb, nocca) u = newton_ah.expmat(dx - dx.conj().T) mo = numpy.dot(mo, u) mo = numpy.hstack([ mo[:, :nocca], mo[:, nmo:nmo + noccb], mo[:, nocca:nmo], mo[:, nmo + noccb:] ]) else: log.note( 'UHF/UKS wavefunction is stable in the UHF/UKS -> GHF/GKS stability analysis' ) return mo
def rhf_external(mf, with_symmetry=True, verbose=None): log = logger.new_logger(mf, verbose) hop1, hdiag1, hop2, hdiag2 = _gen_hop_rhf_external(mf, with_symmetry) def precond(dx, e, x0): hdiagd = hdiag1 - e hdiagd[abs(hdiagd)<1e-8] = 1e-8 return dx/hdiagd x0 = numpy.zeros_like(hdiag1) x0[hdiag1>1e-5] = 1. / hdiag1[hdiag1>1e-5] if not with_symmetry: # allow to break point group symmetry x0[numpy.argmin(hdiag1)] = 1 e1, v1 = lib.davidson(hop1, x0, precond, tol=1e-4, verbose=log) if e1 < -1e-5: log.note('RHF/RKS wavefunction has a real -> complex instablity') else: log.note('RHF/RKS wavefunction is stable in the real -> complex stability analysis') def precond(dx, e, x0): hdiagd = hdiag2 - e hdiagd[abs(hdiagd)<1e-8] = 1e-8 return dx/hdiagd x0 = v1 e3, v3 = lib.davidson(hop2, x0, precond, tol=1e-4, verbose=log) if e3 < -1e-5: log.note('RHF/RKS wavefunction has a RHF/RKS -> UHF/UKS instablity.') mo = (_rotate_mo(mf.mo_coeff, mf.mo_occ, v3), mf.mo_coeff) else: log.note('RHF/RKS wavefunction is stable in the RHF/RKS -> UHF/UKS stability analysis') mo = (mf.mo_coeff, mf.mo_coeff) return mo
def rhf_external(mf, with_symmetry=True, verbose=None): log = logger.new_logger(mf, verbose) hop1, hdiag1, hop2, hdiag2 = _gen_hop_rhf_external(mf, with_symmetry) def precond(dx, e, x0): hdiagd = hdiag1 - e hdiagd[abs(hdiagd)<1e-8] = 1e-8 return dx/hdiagd x0 = numpy.zeros_like(hdiag1) x0[hdiag1>1e-5] = 1. / hdiag1[hdiag1>1e-5] if not with_symmetry: # allow to break point group symmetry x0[numpy.argmin(hdiag1)] = 1 e1, v1 = lib.davidson(hop1, x0, precond, tol=1e-4, verbose=log) if e1 < -1e-5: log.note('RHF/RKS wavefunction has a real -> complex instablity') else: log.note('RHF/RKS wavefunction is stable in the real -> complex stablity analysis') def precond(dx, e, x0): hdiagd = hdiag2 - e hdiagd[abs(hdiagd)<1e-8] = 1e-8 return dx/hdiagd x0 = v1 e3, v3 = lib.davidson(hop2, x0, precond, tol=1e-4, verbose=log) if e3 < -1e-5: log.note('RHF/RKS wavefunction has a RHF/RKS -> UHF/UKS instablity.') mo = (_rotate_mo(mf.mo_coeff, mf.mo_occ, v3), mf.mo_coeff) else: log.note('RHF/RKS wavefunction is stable in the RHF/RKS -> UHF/UKS stablity analysis') mo = (mf.mo_coeff, mf.mo_coeff) return mo
def kernel(h1e, eri, norb, nelec, ecore=0, verbose=logger.NOTE): if isinstance(nelec, (int, numpy.integer)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec h2e = direct_spin1.absorb_h1e(h1e, eri, norb, nelec, .5) namax = cistring.num_strings(norb, neleca) nbmax = cistring.num_strings(norb, nelecb) myci = SelectedCI() strsa = [int('1'*neleca, 2)] strsb = [int('1'*nelecb, 2)] ci_strs = (strsa, strsb) ci0 = numpy.ones((1,1)) ci0, ci_strs = enlarge_space(myci, (ci0, ci_strs), h2e, norb, nelec) def all_linkstr_index(ci_strs): cd_indexa = cre_des_linkstr(ci_strs[0], norb, neleca) dd_indexa = des_des_linkstr(ci_strs[0], norb, neleca) cd_indexb = cre_des_linkstr(ci_strs[1], norb, nelecb) dd_indexb = des_des_linkstr(ci_strs[1], norb, nelecb) return cd_indexa, dd_indexa, cd_indexb, dd_indexb def hop(c): hc = contract_2e(h2e, (c, ci_strs), norb, nelec, link_index) return hc.reshape(-1) precond = lambda x, e, *args: x/(hdiag-e+1e-4) e_last = 0 tol = 1e-2 conv = False for icycle in range(norb): tol = max(tol*1e-2, myci.float_tol) link_index = all_linkstr_index(ci_strs) hdiag = make_hdiag(h1e, eri, ci_strs, norb, nelec) e, ci0 = lib.davidson(hop, ci0.reshape(-1), precond, tol=tol, verbose=verbose) print('icycle %d ci.shape %s E = %.15g' % (icycle, (len(ci_strs[0]), len(ci_strs[1])), e)) if ci0.shape == (namax,nbmax) or abs(e-e_last) < myci.float_tol*10: conv = True break ci1, ci_strs = enlarge_space(myci, (ci0, ci_strs), h2e, norb, nelec) if ci1.size < ci0.size*1.02: conv = True break e_last = e ci0 = ci1 link_index = all_linkstr_index(ci_strs) hdiag = make_hdiag(h1e, eri, ci_strs, norb, nelec) e, ci0 = lib.davidson(hop, ci0.reshape(-1), precond, tol=myci.conv_tol, verbose=verbose) na = len(ci_strs[0]) nb = len(ci_strs[1]) return e+ecore, (ci0.reshape(na,nb), ci_strs)
def uhf_external(mf, with_symmetry=True, verbose=None): log = logger.new_logger(mf, verbose) hop1, hdiag1, hop2, hdiag2 = _gen_hop_uhf_external(mf, with_symmetry) def precond(dx, e, x0): hdiagd = hdiag1 - e hdiagd[abs(hdiagd)<1e-8] = 1e-8 return dx/hdiagd x0 = numpy.zeros_like(hdiag1) x0[hdiag1>1e-5] = 1. / hdiag1[hdiag1>1e-5] if not with_symmetry: # allow to break point group symmetry x0[numpy.argmin(hdiag1)] = 1 e1, v = lib.davidson(hop1, x0, precond, tol=1e-4, verbose=log) if e1 < -1e-5: log.note('UHF/UKS wavefunction has a real -> complex instablity') else: log.note('UHF/UKS wavefunction is stable in the real -> complex stability analysis') def precond(dx, e, x0): hdiagd = hdiag2 - e hdiagd[abs(hdiagd)<1e-8] = 1e-8 return dx/hdiagd x0 = numpy.zeros_like(hdiag2) x0[hdiag2>1e-5] = 1. / hdiag2[hdiag2>1e-5] if not with_symmetry: # allow to break point group symmetry x0[numpy.argmin(hdiag2)] = 1 e3, v = lib.davidson(hop2, x0, precond, tol=1e-4, verbose=log) log.debug('uhf_external: lowest eigs of H = %s', e3) mo = scipy.linalg.block_diag(*mf.mo_coeff) if e3 < -1e-5: log.note('UHF/UKS wavefunction has an UHF/UKS -> GHF/GKS instablity.') occidxa = numpy.where(mf.mo_occ[0]> 0)[0] viridxa = numpy.where(mf.mo_occ[0]==0)[0] occidxb = numpy.where(mf.mo_occ[1]> 0)[0] viridxb = numpy.where(mf.mo_occ[1]==0)[0] nocca = len(occidxa) nvira = len(viridxa) noccb = len(occidxb) nvirb = len(viridxb) nmo = nocca + nvira dx = numpy.zeros((nmo*2,nmo*2)) dx[viridxa[:,None],nmo+occidxb] = v[:nvira*noccb].reshape(nvira,noccb) dx[nmo+viridxb[:,None],occidxa] = v[nvira*noccb:].reshape(nvirb,nocca) u = newton_ah.expmat(dx - dx.conj().T) mo = numpy.dot(mo, u) mo = numpy.hstack([mo[:,:nocca], mo[:,nmo:nmo+noccb], mo[:,nocca:nmo], mo[:,nmo+noccb:]]) else: log.note('UHF/UKS wavefunction is stable in the UHF/UKS -> GHF/GKS stability analysis') return mo
def uhf_internal(mf, with_symmetry=True, verbose=None): log = logger.new_logger(mf, verbose) g, hop, hdiag = newton_ah.gen_g_hop_uhf(mf, mf.mo_coeff, mf.mo_occ, with_symmetry=with_symmetry) hdiag *= 2 def precond(dx, e, x0): hdiagd = hdiag - e hdiagd[abs(hdiagd)<1e-8] = 1e-8 return dx/hdiagd def hessian_x(x): # See comments in function rhf_internal return hop(x).real * 2 x0 = numpy.zeros_like(g) x0[g!=0] = 1. / hdiag[g!=0] if not with_symmetry: # allow to break point group symmetry x0[numpy.argmin(hdiag)] = 1 e, v = lib.davidson(hessian_x, x0, precond, tol=1e-4, verbose=log) if e < -1e-5: log.note('UHF/UKS wavefunction has an internal instablity.') nocca = numpy.count_nonzero(mf.mo_occ[0]> 0) nvira = numpy.count_nonzero(mf.mo_occ[0]==0) mo = (_rotate_mo(mf.mo_coeff[0], mf.mo_occ[0], v[:nocca*nvira]), _rotate_mo(mf.mo_coeff[1], mf.mo_occ[1], v[nocca*nvira:])) else: log.note('UHF/UKS wavefunction is stable in the intenral stability analysis') mo = mf.mo_coeff return mo
def rhf_internal(mf, with_symmetry=True, verbose=None): log = logger.new_logger(mf, verbose) g, hop, hdiag = newton_ah.gen_g_hop_rhf(mf, mf.mo_coeff, mf.mo_occ, with_symmetry=with_symmetry) hdiag *= 2 def precond(dx, e, x0): hdiagd = hdiag - e hdiagd[abs(hdiagd) < 1e-8] = 1e-8 return dx / hdiagd # The results of hop(x) corresponds to a displacement that reduces # gradients g. It is the vir-occ block of the matrix vector product # (Hessian*x). The occ-vir block equals to x2.T.conj(). The overall # Hessian for internal reotation is x2 + x2.T.conj(). This is # the reason we apply (.real * 2) below def hessian_x(x): return hop(x).real * 2 x0 = numpy.zeros_like(g) x0[g != 0] = 1. / hdiag[g != 0] if not with_symmetry: # allow to break point group symmetry x0[numpy.argmin(hdiag)] = 1 e, v = lib.davidson(hessian_x, x0, precond, tol=1e-4, verbose=log) if e < -1e-5: log.note('RHF/RKS wavefunction has an internal instablity') mo = _rotate_mo(mf.mo_coeff, mf.mo_occ, v) else: log.note( 'RHF/RKS wavefunction is stable in the internal stability analysis' ) mo = mf.mo_coeff return mo
def ghf_stability(mf, verbose=None): log = logger.new_logger(mf, verbose) with_symmetry = True g, hop, hdiag = newton_ah.gen_g_hop_ghf(mf, mf.mo_coeff, mf.mo_occ, with_symmetry=with_symmetry) hdiag *= 2 def precond(dx, e, x0): hdiagd = hdiag - e hdiagd[abs(hdiagd)<1e-8] = 1e-8 return dx/hdiagd def hessian_x(x): # See comments in function rhf_internal return hop(x).real * 2 x0 = numpy.zeros_like(g) x0[g!=0] = 1. / hdiag[g!=0] if not with_symmetry: # allow to break point group symmetry x0[numpy.argmin(hdiag)] = 1 e, v = lib.davidson(hessian_x, x0, precond, tol=1e-4, verbose=log) if e < -1e-5: log.note('GHF wavefunction has an internal instablity') mo = _rotate_mo(mf.mo_coeff, mf.mo_occ, v) else: log.note('GHF wavefunction is stable in the intenral stability analysis') mo = mf.mo_coeff return mo
def uhf_internal(mf, with_symmetry=True, verbose=None): log = logger.new_logger(mf, verbose) g, hop, hdiag = newton_ah.gen_g_hop_uhf(mf, mf.mo_coeff, mf.mo_occ, with_symmetry=with_symmetry) hdiag *= 2 def precond(dx, e, x0): hdiagd = hdiag - e hdiagd[abs(hdiagd) < 1e-8] = 1e-8 return dx / hdiagd def hessian_x(x): # See comments in function rhf_internal return hop(x).real * 2 x0 = numpy.zeros_like(g) x0[g != 0] = 1. / hdiag[g != 0] if not with_symmetry: # allow to break point group symmetry x0[numpy.argmin(hdiag)] = 1 e, v = lib.davidson(hessian_x, x0, precond, tol=1e-4, verbose=log) if e < -1e-5: log.note('UHF/UKS wavefunction has an internal instablity.') nocca = numpy.count_nonzero(mf.mo_occ[0] > 0) nvira = numpy.count_nonzero(mf.mo_occ[0] == 0) mo = (_rotate_mo(mf.mo_coeff[0], mf.mo_occ[0], v[:nocca * nvira]), _rotate_mo(mf.mo_coeff[1], mf.mo_occ[1], v[nocca * nvira:])) else: log.note( 'UHF/UKS wavefunction is stable in the internal stability analysis' ) mo = mf.mo_coeff return mo
def kernel(t, u, g, hpp, nsite, nelec, nphonon, tol=1e-9, max_cycle=100, verbose=0, ecore=0, **kwargs): cishape = make_shape(nsite, nelec, nphonon) ci0 = numpy.zeros(cishape) ci0.__setitem__((0, 0) + (0, ) * nsite, 1) # Add noise for initial guess, remove it if problematic ci0[0, :] += numpy.random.random(ci0[0, :].shape) * 1e-6 ci0[:, 0] += numpy.random.random(ci0[:, 0].shape) * 1e-6 def hop(c): hc = contract_all(t, u, g, hpp, c, nsite, nelec, nphonon) return hc.reshape(-1) hdiag = make_hdiag(t, u, g, hpp, nsite, nelec, nphonon) precond = lambda x, e, *args: x / (hdiag - e + 1e-4) e, c = lib.davidson(hop, ci0.reshape(-1), precond, tol=tol, max_cycle=max_cycle, verbose=verbose, **kwargs) return e + ecore, c
def rohf_internal(mf, with_symmetry=True, verbose=None, return_status=False): log = logger.new_logger(mf, verbose) g, hop, hdiag = newton_ah.gen_g_hop_rohf(mf, mf.mo_coeff, mf.mo_occ, with_symmetry=with_symmetry) hdiag *= 2 stable = True def precond(dx, e, x0): hdiagd = hdiag - e hdiagd[abs(hdiagd) < 1e-8] = 1e-8 return dx / hdiagd def hessian_x(x): # See comments in function rhf_internal return hop(x).real * 2 x0 = numpy.zeros_like(g) x0[g != 0] = 1. / hdiag[g != 0] if not with_symmetry: # allow to break point group symmetry x0[numpy.argmin(hdiag)] = 1 e, v = lib.davidson(hessian_x, x0, precond, tol=1e-4, verbose=log) if e < -1e-5: log.note(f'{mf.__class__} wavefunction has an internal instability.') mo = _rotate_mo(mf.mo_coeff, mf.mo_occ, v) stable = False else: log.note(f'{mf.__class__} wavefunction is stable in the internal ' 'stability analysis') mo = mf.mo_coeff if return_status: return mo, stable else: return mo
def uhf_internal(mf, verbose=None): log = logger.new_logger(mf, verbose) g, hop, hdiag = newton_ah.gen_g_hop_uhf(mf, mf.mo_coeff, mf.mo_occ) def precond(dx, e, x0): hdiagd = hdiag * 2 - e hdiagd[abs(hdiagd) < 1e-8] = 1e-8 return dx / hdiagd def hessian_x(x): # See comments in function rhf_internal return hop(x).real * 2 x0 = numpy.zeros_like(g) x0[g != 0] = 1. / hdiag[g != 0] e, v = lib.davidson(hessian_x, x0, precond, tol=1e-4, verbose=log) if e < -1e-5: log.log('KUHF/KUKS wavefunction has an internal instability.') tot_x_a = sum( (occ > 0).sum() * (occ == 0).sum() for occ in mf.mo_occ[0]) mo = (_rotate_mo(mf.mo_coeff[0], mf.mo_occ[0], v[:tot_x_a]), _rotate_mo(mf.mo_coeff[1], mf.mo_occ[1], v[tot_x_a:])) else: log.log( 'KUHF/KUKS wavefunction is stable in the internal stability analysis' ) mo = mf.mo_coeff return mo
def optimizeUnitCells(self, D, two_site, verbosity, rotate): """Optimizes the two unit cells. """ for info in self._sweep(two_site): # Create the big site AA = self.make_center_site(two_site, info) diagonal = self.heff_diagonal(two_site, info) w, v = davidson(lambda x: self.Heff(x, two_site, info), x0=AA.ravel(), precond=diagonal) self.eigenval = w * self.sign print_info = { 'sites': info['sites'], 'fidelity': 1 - abs(np.dot(AA.ravel().conj(), v)), 'energy': self.energy, } print_info = { **print_info, **self.update_sites(v, two_site, info, D, rotate) } if verbosity >= 2: print(print_info) if verbosity >= 2: print()
def rhf_internal(mf, with_symmetry=True, verbose=None): log = logger.new_logger(mf, verbose) g, hop, hdiag = newton_ah.gen_g_hop_rhf(mf, mf.mo_coeff, mf.mo_occ, with_symmetry=with_symmetry) def precond(dx, e, x0): hdiagd = hdiag - e hdiagd[abs(hdiagd) < 1e-8] = 1e-8 return dx / hdiagd x0 = numpy.zeros_like(g) x0[g != 0] = 1. / hdiag[g != 0] if not with_symmetry: # allow to break point group symmetry x0[numpy.argmin(hdiag)] = 1 e, v = lib.davidson(hop, x0, precond, tol=1e-4, verbose=log) if e < -1e-5: log.note('RHF/RKS wavefunction has an internal instablity') mo = _rotate_mo(mf.mo_coeff, mf.mo_occ, v) else: log.note( 'RHF/RKS wavefunction is stable in the intenral stablity analysis') mo = mf.mo_coeff return mo
def rhf_internal(mf, verbose=None): log = logger.new_logger(mf, verbose) g, hop, hdiag = newton_ah.gen_g_hop_rhf(mf, mf.mo_coeff, mf.mo_occ) def precond(dx, e, x0): hdiagd = hdiag*2 - e hdiagd[abs(hdiagd)<1e-8] = 1e-8 return dx/hdiagd # The results of hop(x) corresponds to a displacement that reduces # gradients g. It is the vir-occ block of the matrix vector product # (Hessian*x). The occ-vir block equals to x2.T.conj(). The overall # Hessian for internal reotation is x2 + x2.T.conj(). This is # the reason we apply (.real * 2) below def hessian_x(x): return hop(x).real * 2 x0 = numpy.zeros_like(g) x0[g!=0] = 1. / hdiag[g!=0] e, v = lib.davidson(hessian_x, x0, precond, tol=1e-4, verbose=log) if e < -1e-5: log.log('KRHF/KRKS wavefunction has an internal instablity') mo = _rotate_mo(mf.mo_coeff, mf.mo_occ, v) else: log.log('KRHF/KRKS wavefunction is stable in the intenral stability analysis') mo = mf.mo_coeff return mo
def Hmat_diagonalization(Hmat, method="full", nroots=1, diags=None): ''' exact diagonalization ''' if method == "Arnoldi": print "arpack Arnoldi method" e, c = scipy.sparse.linalg.eigsh(Hmat, k=nroots, which="SA") print "e=",e elif method == "Davidson": print "pyscf davidson method" precond = lambda x, e, *args: x/(diags-e+1e-4) nconfigs = Hmat.shape[0] def hop(c): return Hmat.dot(c) initial = np.random.rand(nconfigs)-0.5 e, c = lib.davidson(hop, initial, precond, nroots=nroots,max_cycle=100) elif method == "full": print "full diagonalization" e, c = scipy.linalg.eigh(a=Hmat.todense()) return e, c
def kernel(myci, eris, ci0=None, max_cycle=50, tol=1e-8, verbose=logger.INFO): mol = myci.mol nmo = myci.nmo nocc = myci.nocc mo_energy = eris.fock.diagonal() diag = make_diagonal(mol, mo_energy, eris, nocc) ehf = diag[0] diag -= ehf if ci0 is None: # MP2 initial guess nvir = nmo - nocc e_i = mo_energy[:nocc] e_a = mo_energy[nocc:] ci0 = numpy.zeros(1+nocc*nvir+(nocc*nvir)**2) ci0[0] = 1 t2 = 2*eris.voov.transpose(1,2,0,3) - eris.voov.transpose(1,2,3,0) t2 /= lib.direct_sum('i+j-a-b', e_i, e_i, e_a, e_a) ci0[1+nocc*nvir:] = t2.ravel() def op(x): return contract(myci, x, eris) def precond(x, e, *args): return x / (diag - e) def cisd_dot(x1, x2): return dot(x1, x2, nocc, nvir) ecisd, ci = lib.davidson(op, ci0, precond, max_cycle=max_cycle, tol=tol, dot=cisd_dot, verbose=verbose) conv = True # It should be checked in lib.davidson function return conv, ecisd, ci
def RTE(H_, dT, Tmax, lanczos=False, psi0=None): # --- diagonalization --- N = H_[0][2].shape[1] nbit = int(np.log2(N)) hdiag = np.zeros(N, dtype=complex) ei = np.zeros(N, dtype=complex) for i in range(N): xi = Int2Bas(i, 2, nbit) for (A, h, imp, gmp) in H_: nact = len(A) for m in np.where(np.abs(h) > 1e-8)[0]: sm = Int2Bas(m, 4, nact) #print A,sm,[xi[A[i]] for i in range(nact)] smx = [ sigma_matrices[xi[A[w]], xi[A[w]], sm[w]] for w in range(nact) ] hdiag[i] += h[m] * np.prod(smx) if (i % 1000 == 0): print i, N, hdiag[i] precond = lambda x, e, *args: x / (hdiag - e + 1e-4) def hop(c_): return Hpsi(H_, c_) epsm0, Um0 = davidson(hop, psi0, precond) fout = open('RTE_davidson.out', 'w') fout.write("gs energy %.6f \n" % epsm0) # --- initial state --- if (psi0 is None): i0 = np.argmin(hdiag) psi0 = np.zeros(N, dtype=complex) psi0[i0] = 1.0 # --- real-time evolution --- bra_RTE = psi0[:] braH_RTE = Hpsi(H_, psi0[:])[:] ket_RTE = psi0[:] nbeta = int(Tmax / dT) + 1 hvect_LANZ = np.zeros(nbeta + 1, dtype=complex) svect_LANZ = np.zeros(nbeta + 1, dtype=complex) fout.write("ITE\n") for ib in range(nbeta): hvect_LANZ[ib] = np.einsum('a,a', np.conj(braH_RTE), ket_RTE) svect_LANZ[ib] = np.einsum('a,a', np.conj(bra_RTE), ket_RTE) ket_RTE = ExpitH(H_, ket_RTE, dT)[0] print ib, hvect_LANZ[ib] dump_lanz_rte(hvect_LANZ[:nbeta], svect_LANZ[:nbeta], 'qlanz.vecs') fout.close()
def ghf_stability(mf, verbose=None, return_status=False): ''' Stability analysis for GHF/GKS method. Args: mf : GHF or GKS object Kwargs: return_status: bool Whether to return `stable_i` and `stable_e` Returns: If return_status is False (default), the return value includes a new set of orbitals, which are more close to the stable condition. Else, another one boolean variable (indicating current status: stable or unstable) is returned. ''' log = logger.new_logger(mf, verbose) with_symmetry = True g, hop, hdiag = newton_ah.gen_g_hop_ghf(mf, mf.mo_coeff, mf.mo_occ, with_symmetry=with_symmetry) hdiag *= 2 stable = True def precond(dx, e, x0): hdiagd = hdiag - e hdiagd[abs(hdiagd) < 1e-8] = 1e-8 return dx / hdiagd def hessian_x(x): # See comments in function rhf_internal return hop(x).real * 2 x0 = numpy.zeros_like(g) x0[g != 0] = 1. / hdiag[g != 0] if not with_symmetry: # allow to break point group symmetry x0[numpy.argmin(hdiag)] = 1 e, v = lib.davidson(hessian_x, x0, precond, tol=1e-4, verbose=log) if e < -1e-5: log.note('GHF wavefunction has an internal instability') mo = _rotate_mo(mf.mo_coeff, mf.mo_occ, v) stable = False else: log.note( 'GHF wavefunction is stable in the internal stability analysis') mo = mf.mo_coeff if return_status: return mo, stable else: return mo
def kernel(h1e, g2e, norb, nelec, ecore=0): h2e = absorb_h1e(h1e, g2e, norb, nelec, .5) na = cistring.num_strings(norb, nelec//2) ci0 = numpy.zeros((na,na)) ci0[0,0] = 1 def hop(c): hc = contract_2e(h2e, c, norb, nelec) return hc.reshape(-1) hdiag = make_hdiag(h1e, g2e, norb, nelec) precond = lambda x, e, *args: x/(hdiag-e+1e-4) e, c = lib.davidson(hop, ci0.reshape(-1), precond) return e+ecore
def kernel(hobj): mol = hobj.mol atom_charges = mol.atom_charges() atmlst = numpy.where(atom_charges != 0)[0] # Exclude ghost atoms natm = len(atmlst) mass = numpy.array([elements.MASSES[atom_charges[i]] for i in atmlst]) reduced_mass = 1. / (1. / mass).sum() if hobj.nroots is None: h = hobj.hess(atmlst=atmlst) h = numpy.einsum('ijxy,i,j->ijxy', h, mass**-.5, mass**-.5) h = h.transpose(0, 2, 1, 3).reshape(natm * 3, natm * 3) e, c = numpy.linalg.eigh(h) c = c.T else: # Solve some roots h_op, hdiag = hobj.gen_hop() hdiag = hdiag.reshape(-1, 3)[atmlst].ravel() def vib_mode_h_op(x): x1 = numpy.zeros((mol.natm, 3)) x1[atmlst] = numpy.einsum('i,ix->ix', mass**-.5, x.reshape(natm, 3)) hx = h_op(x1).reshape(-1, 3)[atmlst] hx = numpy.einsum('i,ix->ix', mass**-.5, hx) return hx.ravel() def precond(x, e, *args): hdiagd = hdiag - e hdiagd[abs(hdiagd) < 1e-8] = 1e-8 return x / hdiagd e, c = lib.davidson(vib_mode_h_op, hdiag, precond, tol=hobj.conv_tol, nroots=hobj.nroots, verbose=5) c = numpy.asarray(c) hartree_kj = nist.HARTREE2J * 1e3 unit2cm = ((hartree_kj * nist.AVOGADRO)**.5 / (nist.BOHR * 1e-10) / (2 * numpy.pi * nist.LIGHT_SPEED_SI) * 1e-2) hobj.freq = numpy.sign(e) * abs(e)**.5 * unit2cm lib.logger.note(hobj, 'Freq %s', hobj.freq) # TODO: Remove translation and rotation modes hobj.mode = c.reshape(-1, natm, 3) # Transform back to cartesian coordinates #hobj.mode = numpy.einsum('i,kix->kix', mass**-.5, c.reshape(-1,natm,3)) return hobj.freq, hobj.mode
def kernel(h1e, eri, norb, nelec, ecore=0): h2e = absorb_h1e(h1e, eri, norb, nelec, .5) na = cistring.num_strings(norb, nelec // 2) ci0 = numpy.zeros((na, na)) ci0[0, 0] = 1 def hop(c): hc = contract_2e(h2e, c, norb, nelec) return hc.reshape(-1) hdiag = make_hdiag(h1e, eri, norb, nelec) precond = lambda x, e, *args: x / (hdiag - e + 1e-4) e, c = lib.davidson(hop, ci0.reshape(-1), precond) return e + ecore
def kernel(t, u, g, hpp, nsite, nelec, nphonon, tol=1e-9, max_cycle=100, verbose=0, **kwargs): cishape = make_shape(nsite, nelec, nphonon) ci0 = numpy.zeros(cishape) ci0.__setitem__((0,0) + (0,)*nsite, 1) # Add noise for initial guess, remove it if problematic ci0[0,:] += numpy.random.random(ci0[0,:].shape) * 1e-6 ci0[:,0] += numpy.random.random(ci0[:,0].shape) * 1e-6 def hop(c): hc = contract_all(t, u, g, hpp, c, nsite, nelec, nphonon) return hc.reshape(-1) hdiag = make_hdiag(t, u, g, hpp, nsite, nelec, nphonon) precond = lambda x, e, *args: x/(hdiag-e+1e-4) return lib.davidson(hop, ci0.reshape(-1), precond, tol=tol, max_cycle=max_cycle, verbose=verbose, **kwargs)
def rhf_external(mf, verbose=None): log = logger.new_logger(mf, verbose) hop2, hdiag2 = _gen_hop_rhf_external(mf) def precond(dx, e, x0): hdiagd = hdiag2 - e hdiagd[abs(hdiagd)<1e-8] = 1e-8 return dx/hdiagd x0 = numpy.zeros_like(hdiag2) x0[hdiag2>1e-5] = 1. / hdiag2[hdiag2>1e-5] e3, v3 = lib.davidson(hop2, x0, precond, tol=1e-4, verbose=log) if e3 < -1e-5: log.log('KRHF/KRKS wavefunction has an KRHF/KRKS -> KUHF/KUKS instablity.') mo = (_rotate_mo(mf.mo_coeff, mf.mo_occ, v3), mf.mo_coeff) else: log.log('KRHF/KRKS wavefunction is stable in the KRHF/KRKS -> KUHF/KUKS stability analysis') mo = (mf.mo_coeff, mf.mo_coeff) return mo
def uhf_external(mf, verbose=None): log = logger.new_logger(mf, verbose) hop2, hdiag2 = _gen_hop_uhf_external(mf) def precond(dx, e, x0): hdiagd = hdiag2 - e hdiagd[abs(hdiagd)<1e-8] = 1e-8 return dx/hdiagd x0 = numpy.zeros_like(hdiag2) x0[hdiag2>1e-5] = 1. / hdiag2[hdiag2>1e-5] e3, v = lib.davidson(hop2, x0, precond, tol=1e-4, verbose=log) log.debug('uhf_external: lowest eigs of H = %s', e3) mo = None if e3 < -1e-5: log.log('KUHF/KUKS wavefunction has an KUHF/KUKS -> KGHF/KGKS instablity.') else: log.log('KUHF/KUKS wavefunction is stable in the KUHF/KUKS -> KGHF/KGKS stability analysis') return mo
def kernel(hobj): mol = hobj.mol atom_charges = mol.atom_charges() atmlst = numpy.where(atom_charges != 0)[0] # Exclude ghost atoms natm = len(atmlst) mass = numpy.array([elements.MASSES[atom_charges[i]] for i in atmlst]) reduced_mass = 1./(1./mass).sum() if hobj.nroots is None: h = hobj.hess(atmlst=atmlst) h = numpy.einsum('ijxy,i,j->ijxy', h, mass**-.5, mass**-.5) h = h.transpose(0,2,1,3).reshape(natm*3,natm*3) e, c = numpy.linalg.eigh(h) c = c.T else: # Solve some roots h_op, hdiag = hobj.gen_hop() hdiag = hdiag.reshape(-1,3)[atmlst].ravel() def vib_mode_h_op(x): x1 = numpy.zeros((mol.natm,3)) x1[atmlst] = numpy.einsum('i,ix->ix', mass**-.5, x.reshape(natm,3)) hx = h_op(x1).reshape(-1,3)[atmlst] hx = numpy.einsum('i,ix->ix', mass**-.5, hx) return hx.ravel() def precond(x, e, *args): hdiagd = hdiag-e hdiagd[abs(hdiagd)<1e-8] = 1e-8 return x/hdiagd e, c = lib.davidson(vib_mode_h_op, hdiag, precond, tol=hobj.conv_tol, nroots=hobj.nroots, verbose=5) c = numpy.asarray(c) hartree_kj = nist.HARTREE2J*1e3 unit2cm = ((hartree_kj * nist.AVOGADRO)**.5 / (nist.BOHR*1e-10) / (2*numpy.pi*nist.LIGHT_SPEED_SI) * 1e-2) hobj.freq = numpy.sign(e) * abs(e)**.5 * unit2cm lib.logger.note(hobj, 'Freq %s', hobj.freq) # TODO: Remove translation and rotation modes hobj.mode = c.reshape(-1,natm,3) # Transform back to cartesian coordinates #hobj.mode = numpy.einsum('i,kix->kix', mass**-.5, c.reshape(-1,natm,3)) return hobj.freq, hobj.mode
def kernel(self, h1e, eri, norb, nelec, ci0=None, ecore=0, **kwargs): if isinstance(nelec, (int, numpy.integer)): nelecb = nelec // 2 neleca = nelec - nelecb else: neleca, nelecb = nelec h2e = self.absorb_h1e(h1e, eri, norb, nelec, .5) h2e = ao2mo.restore(1, h2e, norb) hdiag = self.make_hdiag(h1e, eri, norb, nelec) nroots = 1 if ci0 is None: ci0 = self.get_init_guess(norb, nelec, nroots, hdiag) def hop(c): return self.contract_2e(h2e, c, norb, nelec) precond = lambda x, e, *args: x / (hdiag - e + 1e-4) e, c = lib.davidson(hop, ci0, precond, **kwargs) return e + ecore, c
def kernel_ref(h1e, eri, norb, nelec, ecore=0, **kwargs): if isinstance(nelec, (int, numpy.integer)): nelecb = nelec // 2 neleca = nelec - nelecb else: neleca, nelecb = nelec h2e = direct_spin1.absorb_h1e(h1e, eri, norb, nelec, .5) h2e = ao2mo.restore(1, h2e, norb) na = cistring.num_strings(norb, neleca) ci0 = numpy.zeros(na) ci0[0] = 1 link_index = cistring.gen_linkstr_index(range(norb), neleca) def hop(c): return contract_2e_ref(h2e, c, norb, nelec, link_index) hdiag = make_hdiag(h1e, eri, norb, nelec) precond = lambda x, e, *args: x / (hdiag - e + 1e-4) e, c = lib.davidson(hop, ci0.reshape(-1), precond, **kwargs) return e + ecore
def rhf_internal(mf, verbose=None): log = logger.new_logger(mf, verbose) g, hop, hdiag = newton_ah.gen_g_hop_rhf(mf, mf.mo_coeff, mf.mo_occ) def precond(dx, e, x0): hdiagd = hdiag - e hdiagd[abs(hdiagd) < 1e-8] = 1e-8 return dx / hdiagd x0 = numpy.zeros_like(g) x0[g != 0] = 1. / hdiag[g != 0] e, v = lib.davidson(hop, x0, precond, tol=1e-4, verbose=log) if e < -1e-5: log.log('KRHF/KRKS wavefunction has an internal instablity') mo = _rotate_mo(mf.mo_coeff, mf.mo_occ, v) else: log.log( 'KRHF/KRKS wavefunction is stable in the intenral stablity analysis' ) mo = mf.mo_coeff return mo
def uhf_internal(mf, verbose=None): log = logger.new_logger(mf, verbose) g, hop, hdiag = newton_ah.gen_g_hop_uhf(mf, mf.mo_coeff, mf.mo_occ) def precond(dx, e, x0): hdiagd = hdiag*2 - e hdiagd[abs(hdiagd)<1e-8] = 1e-8 return dx/hdiagd def hessian_x(x): # See comments in function rhf_internal return hop(x).real * 2 x0 = numpy.zeros_like(g) x0[g!=0] = 1. / hdiag[g!=0] e, v = lib.davidson(hessian_x, x0, precond, tol=1e-4, verbose=log) if e < -1e-5: log.log('KUHF/KUKS wavefunction has an internal instablity.') tot_x_a = sum((occ>0).sum()*(occ==0).sum() for occ in mf.mo_occ[0]) mo = (_rotate_mo(mf.mo_coeff[0], mf.mo_occ[0], v[:tot_x_a]), _rotate_mo(mf.mo_coeff[1], mf.mo_occ[1], v[tot_x_a:])) else: log.log('KUHF/KUKS wavefunction is stable in the intenral stability analysis') mo = mf.mo_coeff return mo
def uhf_external(mf, verbose=None): log = logger.new_logger(mf, verbose) hop2, hdiag2 = _gen_hop_uhf_external(mf) def precond(dx, e, x0): hdiagd = hdiag2 - e hdiagd[abs(hdiagd) < 1e-8] = 1e-8 return dx / hdiagd x0 = numpy.zeros_like(hdiag2) x0[hdiag2 > 1e-5] = 1. / hdiag2[hdiag2 > 1e-5] e3, v = lib.davidson(hop2, x0, precond, tol=1e-4, verbose=log) log.debug('uhf_external: lowest eigs of H = %s', e3) mo = None if e3 < -1e-5: log.log( 'KUHF/KUKS wavefunction has an KUHF/KUKS -> KGHF/KGKS instablity.') else: log.log( 'KUHF/KUKS wavefunction is stable in the KUHF/KUKS -> KGHF/KGKS stablity analysis' ) return mo
def rhf_external(mf, verbose=None): log = logger.new_logger(mf, verbose) hop2, hdiag2 = _gen_hop_rhf_external(mf) def precond(dx, e, x0): hdiagd = hdiag2 - e hdiagd[abs(hdiagd) < 1e-8] = 1e-8 return dx / hdiagd x0 = numpy.zeros_like(hdiag2) x0[hdiag2 > 1e-5] = 1. / hdiag2[hdiag2 > 1e-5] e3, v3 = lib.davidson(hop2, x0, precond, tol=1e-4, verbose=log) if e3 < -1e-5: log.log( 'KRHF/KRKS wavefunction has an KRHF/KRKS -> KUHF/KUKS instablity.') mo = (_rotate_mo(mf.mo_coeff, mf.mo_occ, v3), mf.mo_coeff) else: log.log( 'KRHF/KRKS wavefunction is stable in the KRHF/KRKS -> KUHF/KUKS stability analysis' ) mo = (mf.mo_coeff, mf.mo_coeff) return mo
def rhf_external(mf, with_symmetry=True, show_hessian=True, verbose=None): #log = logger.new_logger(mf, verbose) hop1, hdiag1, hop2, hdiag2 = _gen_hop_rhf_external(mf, with_symmetry) def precond(dx, e, x0): hdiagd = hdiag1 - e hdiagd[abs(hdiagd)<1e-8] = 1e-8 return dx/hdiagd x0 = np.zeros_like(hdiag1) x0[hdiag1>1e-5] = 1. / hdiag1[hdiag1>1e-5] if not with_symmetry: # allow to break point group symmetry x0[np.argmin(hdiag1)] = 1 e1, v1 = lib.davidson(hop1, x0, precond, tol=1e-4) if e1 < -1e-5: print('RHF/RKS wavefunction has a real -> complex instablity at ',x) #else: #print('RHF/RKS wavefunction is stable in the real -> complex stability analysis') def precond(dx, e, x0): hdiagd = hdiag2 - e hdiagd[abs(hdiagd)<1e-8] = 1e-8 return dx/hdiagd x0 = v1 #hop2 is a function (so as to work with the davidson algorithm) #we get the matrix by applying to each basis vector. if show_hessian==True: #capital Hop2 is the matrix hop2_matrix=np.zeros((len(x0),len(x0))) for k in range(len(x0)): xk=np.zeros_like(x0) xk[k]=1 yk=hop2(xk) hop2_matrix[:,k]=yk #better printing to read the hessian np.set_printoptions(linewidth=300,suppress=True,precision=3) print("Printing Hessian:") print(hop2_matrix) print("Done") #reset parameters np.set_printoptions(linewidth=80, suppress=False,precision=5) e3, v3 = lib.davidson(hop2, x0, precond, tol=1e-10) if e3 < -1e-5: if verbose: print('RHF/RKS wavefunction has a RHF/RKS -> UHF/UKS instablity at ',x) print(e3) print(v3) Ca,Cb = (_rotate_mo(mf.mo_coeff, mf.mo_occ, v3), mf.mo_coeff) mo_occ = mf.get_occ(mo_energy=mf.mo_energy, mo_coeff=mf.mo_coeff) dm_broken=pyscf.scf.UHF(diatomic).make_rdm1((Ca, Cb), (mo_occ, mo_occ)) return dm_broken else: return False;
def QITE(H_, db, bmax, lanczos=False, psi0=None, omega=None, ncheck=1, davidson=True): if (davidson): N = H_[0][2].shape[1] nbit = int(np.log2(N)) hdiag = np.zeros(N, dtype=complex) for i in range(N): hdiag[i] = Hii(H_, i) print i, hdiag[i] precond = lambda x, e, *args: x / (hdiag - e + 1e-4) def hop(c_): return Hpsi(H_, c_) if (psi0 is None): i0 = np.argmin(hdiag) psi0 = np.zeros(N, dtype=complex) psi0[i0] = 1.0 from pyscf.lib import davidson epsm0, Um0 = davidson(hop, psi0, precond) else: Hm = Hmat(H_) N = Hm.shape[0] nbit = int(np.log2(N)) eps, U = SciLA.eigh(Hm) m0 = np.argmin(eps) epsm0 = eps[m0] Um0 = U[:, m0] zeta = np.exp(-db * (eps - eps[m0])) fide = 1.0 fout = open('QITE.out', 'w') fout.write("FCI gs energy %.6f \n" % epsm0) fout.write("FCI gs wfn \n") print_state(Um0, nbit, fout) psi_QITE = psi0[:] nbeta = int(bmax / db) + 1 hvect_LANZ = np.zeros(nbeta + 1) svect_LANZ = np.zeros(nbeta + 1) xv = None fout.write("QITE\n") for ib in range(nbeta): ea, ev = Hmoms(H_, psi_QITE) hvect_LANZ[ib] = ea if (omega is None): fide = fidelity(psi_QITE, Um0) else: fide = LA.norm(psi_QITE[omega])**2 if (lanczos): ea_ = Lanczos_QITE(hvect_LANZ[:ib + 1], svect_LANZ[:ib + 1], db) fout.write("%.6f %.6f %.6f %.6f %.6f \n" % (ib * db, ea, ev, fide, ea_)) else: fout.write("%.6f %.6f %.6f %.6f \n" % (ib * db, ea, ev, fide)) fout.flush() if (ncheck > 0): check = (ib % ncheck == 0) else: check = False psi_QITE, dnorm, xv = QITE_step(H_, psi_QITE, db, xv, check) svect_LANZ[ib + 1] = svect_LANZ[ib] + np.log(dnorm) fout.write("QITE gs wfn \n") print_state(psi_QITE, nbit, fout) dump_state(psi_QITE, nbit, 'qite.psi') dump_lanz_vecs(hvect_LANZ[:nbeta], svect_LANZ[:nbeta], 'qlanz.vecs') fout.close()
def eig(self, op, x0, precond, **kwargs): if kwargs['nroots'] == 1 and x0[0].size > 6.5e7: # 500MB lessio = True else: lessio = False return lib.davidson(op, x0, precond, lessio=lessio, **kwargs)
def optimization(MPS, MPSdim, MPSQN, MPO, MPOdim, ephtable, pbond, nexciton,\ procedure, method="2site", nroots=1, inverse=1.0): ''' 1 or 2 site optimization procedure inverse = 1.0 / -1.0 -1.0 to get the largest eigenvalue ''' assert method in ["2site", "1site"] print "optimization method", method # construct the environment matrix construct_enviro(MPS, MPS, MPO, "L") nMPS = len(MPS) # construct each sweep cycle scheme if method == "1site": loop = [['R', i] for i in xrange(nMPS - 1, -1, -1)] + [['L', i] for i in xrange(0, nMPS)] else: loop = [['R', i] for i in xrange(nMPS - 1, 0, -1)] + [['L', i] for i in xrange(1, nMPS)] # initial matrix ltensor = np.ones((1, 1, 1)) rtensor = np.ones((1, 1, 1)) energy = [] for isweep in xrange(len(procedure)): print "Procedure", procedure[isweep] for system, imps in loop: if system == "R": lmethod, rmethod = "Enviro", "System" else: lmethod, rmethod = "System", "Enviro" if method == "1site": lsite = imps - 1 addlist = [imps] else: lsite = imps - 2 addlist = [imps - 1, imps] ltensor = GetLR('L', lsite, MPS, MPS, MPO, itensor=ltensor, method=lmethod) rtensor = GetLR('R', imps + 1, MPS, MPS, MPO, itensor=rtensor, method=rmethod) # get the quantum number pattern qnmat, qnbigl, qnbigr = construct_qnmat(MPSQN, ephtable, pbond, addlist, method, system) cshape = qnmat.shape # hdiag tmp_ltensor = np.einsum("aba -> ba", ltensor) tmp_MPOimps = np.einsum("abbc -> abc", MPO[imps]) tmp_rtensor = np.einsum("aba -> ba", rtensor) if method == "1site": # S-a c f-S # O-b-O-g-O # S-a c f-S path = [([0, 1],"ba, bcg -> acg"),\ ([1, 0],"acg, gf -> acf")] hdiag = tensorlib.multi_tensor_contract( path, tmp_ltensor, tmp_MPOimps, tmp_rtensor)[(qnmat == nexciton)] # initial guess b-S-c # a cguess = MPS[imps][qnmat == nexciton] else: # S-a c d f-S # O-b-O-e-O-g-O # S-a c d f-S tmp_MPOimpsm1 = np.einsum("abbc -> abc", MPO[imps - 1]) path = [([0, 1],"ba, bce -> ace"),\ ([0, 1],"edg, gf -> edf"),\ ([0, 1],"ace, edf -> acdf")] hdiag = tensorlib.multi_tensor_contract( path, tmp_ltensor, tmp_MPOimpsm1, tmp_MPOimps, tmp_rtensor)[(qnmat == nexciton)] # initial guess b-S-c-S-e # a d cguess = np.tensordot(MPS[imps - 1], MPS[imps], axes=1)[qnmat == nexciton] hdiag *= inverse nonzeros = np.sum(qnmat == nexciton) print "Hmat dim", nonzeros count = [0] def hop(c): # convert c to initial structure according to qn pattern cstruct = c1d2cmat(cshape, c, qnmat, nexciton) count[0] += 1 if method == "1site": #S-a l-S # d #O-b-O-f-O # e #S-c k-S path = [([0, 1],"abc, adl -> bcdl"),\ ([2, 0],"bcdl, bdef -> clef"),\ ([1, 0],"clef, lfk -> cek")] cout = tensorlib.multi_tensor_contract( path, ltensor, cstruct, MPO[imps], rtensor) else: #S-a l-S # d g #O-b-O-f-O-j-O # e h #S-c k-S path = [([0, 1],"abc, adgl -> bcdgl"),\ ([3, 0],"bcdgl, bdef -> cglef"),\ ([2, 0],"cglef, fghj -> clehj"),\ ([1, 0],"clehj, ljk -> cehk")] cout = tensorlib.multi_tensor_contract( path, ltensor, cstruct, MPO[imps - 1], MPO[imps], rtensor) # convert structure c to 1d according to qn return inverse * cout[qnmat == nexciton] if nroots != 1: cguess = [cguess] for iroot in xrange(nroots - 1): cguess += [np.random.random([nonzeros]) - 0.5] precond = lambda x, e, *args: x / (hdiag - e + 1e-4) e, c = lib.davidson(hop, cguess, precond, max_cycle=100,\ nroots=nroots) # scipy arpack solver : much slower than davidson #A = scipy.sparse.linalg.LinearOperator((nonzeros,nonzeros), matvec=hop) #e, c = scipy.sparse.linalg.eigsh(A,k=1, which="SA",v0=cguess) print "HC loops:", count[0] print "isweep, imps, e=", isweep, imps, e energy.append(e) cstruct = c1d2cmat(cshape, c, qnmat, nexciton, nroots=nroots) if nroots == 1: # direct svd the coefficient matrix mps, mpsdim, mpsqn, compmps = Renormalization_svd(cstruct, qnbigl, qnbigr,\ system, nexciton, procedure[isweep][0], percent=procedure[isweep][1]) else: # diagonalize the reduced density matrix mps, mpsdim, mpsqn, compmps = Renormalization_ddm(cstruct, qnbigl, qnbigr,\ system, nexciton, procedure[isweep][0], percent=procedure[isweep][1]) if method == "1site": MPS[imps] = mps if system == "L": if imps != len(MPS) - 1: MPS[imps + 1] = np.tensordot(compmps, MPS[imps + 1], axes=1) MPSdim[imps + 1] = mpsdim MPSQN[imps + 1] = mpsqn else: MPS[imps] = np.tensordot(MPS[imps], compmps, axes=1) MPSdim[imps + 1] = 1 MPSQN[imps + 1] = [0] else: if imps != 0: MPS[imps - 1] = np.tensordot(MPS[imps - 1], compmps, axes=1) MPSdim[imps] = mpsdim MPSQN[imps] = mpsqn else: MPS[imps] = np.tensordot(compmps, MPS[imps], axes=1) MPSdim[imps] = 1 MPSQN[imps] = [0] else: if system == "L": MPS[imps - 1] = mps MPS[imps] = compmps else: MPS[imps] = mps MPS[imps - 1] = compmps MPSdim[imps] = mpsdim MPSQN[imps] = mpsqn if nroots == 1: lowestenergy = np.min(energy) print "lowest energy = ", lowestenergy return energy
def kernel(self, D=16, sites=2, max_iter=100, tol=1e-15, verbosity=2): """Executing of the DMRG algorithm. Args: D: The bond dimension to use for DMRG. The algorithm can choose a bond dimension larger than the one specified to avoid truncating between renormalized states degenerate in their singular values. sites: The number of sites to add each step max_iter: The maximal iterations to use in the DMRG algorithm. tol: The tolerance on which to abort the calculation verbosity: 0: Don't print anything. 1: Print results for the optimization. 2: Print intermediate result at every even chain length. """ if sites % 2 != 0: raise ValueError('Number of sites needs to be even') self.nrsites = sites AA = None for i in range(max_iter): # Diagonalize size = self.M * self.M * (self.p**self.nrsites) if AA is None or AA.size != size: AA = rand(size) AA /= norm(AA) w, v = davidson(self.Heff, x0=AA, precond=self.Heffdiagonal()) AA = v # Renormalize the basis E = (w - self.Etot) / self.nrsites ΔE, self.E, self.Etot = self.E - E, E, w trunc, info = self.renormalize_basis(AA, D) if info is not None and verbosity >= 3: print(info) error = info['ArAl TF'] if info is not None else None # Update the effective Hamiltonian self.update_Heff() # Energy difference between this and the previous even-length chain if verbosity >= 2: print( f"it {i}:\tM: {self.M},\tE: {self.E:.12f},\t" f"ΔE: {ΔE:.3g},\ttrunc: {trunc:.3g}", end='') if error is None: print() else: print(f',\tError: {error}') try: if i > 10 and error < tol: break except TypeError: # error or tol is None pass if verbosity >= 1: print(f"its: {i},\tM: {self.M},\tE: {self.E:.12f},\t" f"ΔE: {ΔE:.3g},\ttrunc: {trunc:.3g}") if i == max_iter: print("Convergence not reached.") return self.E
def kernel(h1e, eri, norb, nelec, ecore=0, verbose=logger.NOTE): if isinstance(nelec, (int, numpy.integer)): nelecb = nelec // 2 neleca = nelec - nelecb else: neleca, nelecb = nelec h2e = direct_spin1.absorb_h1e(h1e, eri, norb, nelec, .5) namax = cistring.num_strings(norb, neleca) nbmax = cistring.num_strings(norb, nelecb) myci = SelectedCI() strsa = [int('1' * neleca, 2)] strsb = [int('1' * nelecb, 2)] ci_strs = (strsa, strsb) ci0 = numpy.ones((1, 1)) ci0, ci_strs = enlarge_space(myci, (ci0, ci_strs), h2e, norb, nelec) def all_linkstr_index(ci_strs): cd_indexa = cre_des_linkstr(ci_strs[0], norb, neleca) dd_indexa = des_des_linkstr(ci_strs[0], norb, neleca) cd_indexb = cre_des_linkstr(ci_strs[1], norb, nelecb) dd_indexb = des_des_linkstr(ci_strs[1], norb, nelecb) return cd_indexa, dd_indexa, cd_indexb, dd_indexb def hop(c): hc = contract_2e(h2e, (c, ci_strs), norb, nelec, link_index) return hc.reshape(-1) precond = lambda x, e, *args: x / (hdiag - e + 1e-4) e_last = 0 tol = 1e-2 conv = False for icycle in range(norb): tol = max(tol * 1e-2, myci.float_tol) link_index = all_linkstr_index(ci_strs) hdiag = make_hdiag(h1e, eri, ci_strs, norb, nelec) e, ci0 = lib.davidson(hop, ci0.reshape(-1), precond, tol=tol, verbose=verbose) print('icycle %d ci.shape %s E = %.15g' % (icycle, (len(ci_strs[0]), len(ci_strs[1])), e)) if ci0.shape == (namax, nbmax) or abs(e - e_last) < myci.float_tol * 10: conv = True break ci1, ci_strs = enlarge_space(myci, (ci0, ci_strs), h2e, norb, nelec) if ci1.size < ci0.size * 1.02: conv = True break e_last = e ci0 = ci1 link_index = all_linkstr_index(ci_strs) hdiag = make_hdiag(h1e, eri, ci_strs, norb, nelec) e, ci0 = lib.davidson(hop, ci0.reshape(-1), precond, tol=myci.conv_tol, verbose=verbose) na = len(ci_strs[0]) nb = len(ci_strs[1]) return e + ecore, (ci0.reshape(na, nb), ci_strs)
def calc_eigs_davidson(mpsL, W, F, site, nStates, nStatesCalc=None, preserveState=False, orthonormalize=False, oneSite=True, edgePreserveState=True): Hfun, precond = make_ham_func(mpsL[0], W, F, site, oneSite=oneSite) (n1, n2, n3) = mpsL[0][site].shape if nStatesCalc is None: nStatesCalc = nStates nStates, nStatesCalc = min(nStates, n1 * n2 * n3 - 1), min(nStatesCalc, n1 * n2 * n3 - 1) guess = [] # PH - Figure out new initial guess here !!! for state in range(nStates): if oneSite: guess.append(np.reshape(mpsL[state][site], -1)) else: guess.append( np.reshape( einsum('ijk,lkm->iljm', mpsL[state][site], mpsL[state][site + 1]), -1)) # PH - Could add some convergence check #print(len(guess)) vals, vecso = davidson(Hfun, guess, precond, nroots=nStatesCalc, pick=pick_eigs, follow_state=False, tol=1e-16, max_cycle=1000) #print(len(vecso)) sort_inds = np.argsort(np.real(vals)) try: vecs = np.zeros((len(vecso[0]), nStates), dtype=np.complex_) E = -vals[sort_inds[:nStates]] for i in range(min(nStates, len(sort_inds))): try: vecs[:, i] = vecso[sort_inds[i]] except: vecs[:, i] = guess[i] except: vecs = vecso E = -vals pass # Allow orthonormalize to a float indicating a gap size where it should be turned on if not isinstance(orthonormalize, bool): if nStates == 1: orthonormalize = False else: gap = np.abs(E[0] - E[1]) if gap < orthonormalize: orthonormalize = True else: orthonormalize = False # Orthonormalize (when gap is too small?) - PH, Why? if (nStates > 1) and orthonormalize: vecs = sla.orth(vecs) # At the ends, we do not want to switch states when preserving state is off if ((site == 0) or (site == len(mpsL[0]) - 1)) and edgePreserveState: preserveState = True E, vecs, ovlp = check_overlap(guess[0], vecs, E, preserveState=preserveState) return E, vecs, ovlp
def ITE(H_,db,bmax,lanczos=False,psi0=None): N = H_[0][2].shape[1] nbit = int(np.log2(N)) hdiag = np.zeros(N,dtype=complex) for i in range(N): hdiag[i] = Hii(H_,i) precond = lambda x,e, *args: x/(hdiag-e+1e-4) def hop(c_): return Hpsi(H_,c_) if(psi0 is None): i0 = np.argmin(hdiag) psi0 = np.zeros(N,dtype=complex) psi0[i0] = 1.0 from pyscf.lib import davidson epsm0,Um0 = davidson(hop,psi0,precond) fout = open('ITE.out','w') fout.write("FCI gs energy %.6f \n" % epsm0) fout.write("FCI gs wfn \n") print_state(Um0,nbit,fout) if(psi0 is None): i0 = np.argmin(hdiag) psi_ITE = np.zeros(N,dtype=complex) psi_ITE[i0] = 1.0 else: psi_ITE = psi0.copy() nbeta = int(bmax/db)+1 hvect_LANZ = np.zeros(nbeta+1) svect_LANZ = np.zeros(nbeta+1) if(lanczos): space_LANZ = np.zeros((N,nbeta),dtype=complex) fout.write("ITE\n") for ib in range(nbeta): ea,ev = Hmoms(H_,psi_ITE) hvect_LANZ[ib] = ea fide = fidelity(psi_ITE,Um0) if(lanczos): space_LANZ[:,ib] = psi_ITE.copy() psi_LANZ = Lanczos_kernel(UH,space_LANZ[:,:ib+1]) ea_,ev_ = Hmoms(H_,psi_LANZ) fide_ = fidelity(psi_LANZ,Um0) fout.write("%.6f %.6f %.6f %.6f %.6f %.6f %.6f \n" % (ib*db,ea,ev,fide,ea_,ev_,fide_)) else: fout.write("%.6f %.6f %.6f %.6f \n" % (ib*db,ea,ev,fide)) psi_ITE,dn = ExpmbH(H_,psi_ITE,db) svect_LANZ[ib+1] = svect_LANZ[ib]+np.log(dn) fout.write("ITE gs wfn \n") print_state(psi_ITE,nbit,fout) dump_state(psi_ITE,nbit,'ite.psi') dump_lanz_vecs(hvect_LANZ[:nbeta],svect_LANZ[:nbeta],'qlanz.vecs') fout.close()