def kernel(self, x0=None): '''TDA diagonalization solver ''' self.check_sanity() self.dump_flags() vind, hdiag = self.get_vind(self._scf) precond = self.get_precond(hdiag) if x0 is None: x0 = self.init_guess(self._scf, self.nstates) self.converged, self.e, x1 = \ lib.davidson1(vind, x0, precond, tol=self.conv_tol, nroots=self.nstates, lindep=self.lindep, max_space=self.max_space, verbose=self.verbose) mo_occ = self._scf.mo_occ tot_x_a = sum((occ>0).sum()*(occ==0).sum() for occ in mo_occ[0]) self.xy = [(_unpack(xi, mo_occ), # (X_alpha, X_beta) (0, 0)) # (Y_alpha, Y_beta) for xi in x1] #TODO: analyze CIS wfn point group symmetry return self.e, self.xy
def kernel(self, x0=None, nstates=None): '''TDDFT diagonalization solver ''' mf = self._scf if mf._numint.libxc.is_hybrid_xc(mf.xc): raise RuntimeError('%s cannot be used with hybrid functional' % self.__class__) self.check_sanity() self.dump_flags() if nstates is None: nstates = self.nstates else: self.nstates = nstates log = lib.logger.Logger(self.stdout, self.verbose) vind, hdiag = self.gen_vind(self._scf) precond = self.get_precond(hdiag) if x0 is None: x0 = self.init_guess(self._scf, self.nstates) def pickeig(w, v, nroots, envs): idx = numpy.where(w > POSTIVE_EIG_THRESHOLD**2)[0] return w[idx], v[:,idx], idx self.converged, w2, x1 = \ lib.davidson1(vind, x0, precond, tol=self.conv_tol, nroots=nstates, lindep=self.lindep, max_space=self.max_space, pick=pickeig, verbose=log) mo_energy = self._scf.mo_energy mo_occ = self._scf.mo_occ occidx = numpy.where(mo_occ==2)[0] viridx = numpy.where(mo_occ==0)[0] e_ia = (mo_energy[viridx,None] - mo_energy[occidx]).T e_ia = numpy.sqrt(e_ia) def norm_xy(w, z): zp = e_ia * z.reshape(e_ia.shape) zm = w/e_ia * z.reshape(e_ia.shape) x = (zp + zm) * .5 y = (zp - zm) * .5 norm = lib.norm(x)**2 - lib.norm(y)**2 norm = numpy.sqrt(.5/norm) # normalize to 0.5 for alpha spin return (x*norm, y*norm) idx = numpy.where(w2 > POSTIVE_EIG_THRESHOLD**2)[0] self.e = numpy.sqrt(w2[idx]) self.xy = [norm_xy(self.e[i], x1[i]) for i in idx] if self.chkfile: lib.chkfile.save(self.chkfile, 'tddft/e', self.e) lib.chkfile.save(self.chkfile, 'tddft/xy', self.xy) log.note('Excited State energies (eV)\n%s', self.e * nist.HARTREE2EV) return self.e, self.xy
def eig(self, op, x0=None, precond=None, **kwargs): if isinstance(op, numpy.ndarray): self.converged = True return scipy.linalg.eigh(op) self.converged, e, ci = \ lib.davidson1(lambda xs: [op(x) for x in xs], x0, precond, lessio=self.lessio, **kwargs) if kwargs['nroots'] == 1: self.converged = self.converged[0] e = e[0] ci = ci[0] return e, ci
def eig(self, op, x0=None, precond=None, **kwargs): if isinstance(op, numpy.ndarray): self.converged = True return scipy.linalg.eigh(op) # TODO: check the hermitian of Hamiltonian then determine whether to # call the non-hermitian diagonlization solver davidson_nosym1 self.converged, e, ci = \ lib.davidson1(lambda xs: [op(x) for x in xs], x0, precond, lessio=self.lessio, **kwargs) if kwargs.get('nroots', 1) == 1: self.converged = self.converged[0] e = e[0] ci = ci[0] return e, ci
def kernel(myci, eris, ci0=None, max_cycle=50, tol=1e-8, verbose=logger.INFO): if isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(myci.stdout, verbose) mol = myci.mol nmo = myci.nmo nocc = myci.nocc nvir = nmo - 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 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(xs): return [myci.contract(x, eris) for x in xs] def precond(x, e, *args): diagd = diag - (e-myci.level_shift) diagd[abs(diagd)<1e-8] = 1e-8 return x / diagd def cisd_dot(x1, x2): return dot(x1, x2, nocc, nvir) conv, ecisd, ci = lib.davidson1(op, ci0, precond, tol=tol, max_cycle=max_cycle, max_space=myci.max_space, lindep=myci.lindep, dot=cisd_dot, nroots=myci.nroots, verbose=log) if myci.nroots == 1: ecisd = ecisd[0] ci = ci[0] return conv, ecisd, ci
def kernel(self, x0=None, nstates=None): '''TDA diagonalization solver ''' self.check_sanity() self.dump_flags() if nstates is None: nstates = self.nstates else: self.nstates = nstates log = logger.Logger(self.stdout, self.verbose) vind, hdiag = self.gen_vind(self._scf) precond = self.get_precond(hdiag) if x0 is None: x0 = self.init_guess(self._scf, self.nstates) def pickeig(w, v, nroots, envs): idx = numpy.where(w > POSTIVE_EIG_THRESHOLD**2)[0] return w[idx], v[:,idx], idx self.converged, self.e, x1 = \ lib.davidson1(vind, x0, precond, tol=self.conv_tol, nroots=nstates, lindep=self.lindep, max_space=self.max_space, pick=pickeig, verbose=log) nocc = (self._scf.mo_occ>0).sum() nmo = self._scf.mo_occ.size nvir = nmo - nocc # 1/sqrt(2) because self.x is for alpha excitation amplitude and 2(X^+*X) = 1 self.xy = [(xi.reshape(nocc,nvir)*numpy.sqrt(.5),0) for xi in x1] if self.chkfile: lib.chkfile.save(self.chkfile, 'tddft/e', self.e) lib.chkfile.save(self.chkfile, 'tddft/xy', self.xy) log.note('Excited State energies (eV)\n%s', self.e * nist.HARTREE2EV) return self.e, self.xy
def kernel(self, x0=None): '''TDA diagonalization solver ''' self.check_sanity() mo_energy = self._scf.mo_energy nocc = (self._scf.mo_occ>0).sum() eai = lib.direct_sum('a-i->ai', mo_energy[nocc:], mo_energy[:nocc]) if x0 is None: x0 = self.init_guess(eai, self.nstates) precond = self.get_precond(eai.ravel()) self.e, x1 = lib.davidson1(self.get_vind, x0, precond, tol=self.conv_tol, nroots=self.nstates, lindep=self.lindep, max_space=self.max_space, verbose=self.verbose)[1:] # 1/sqrt(2) because self.x is for alpha excitation amplitude and 2(X^+*X) = 1 self.xy = [(xi.reshape(eai.shape)*numpy.sqrt(.5),0) for xi in x1] return self.e, self.xy
def kernel(self, x0=None): '''TDDFT diagonalization solver ''' mf = self._scf if mf._numint.libxc.is_hybrid_xc(mf.xc): raise RuntimeError('%s cannot be applied with hybrid functional' % self.__class__) self.check_sanity() self.dump_flags() vind, hdiag = self.gen_vind(self._scf) precond = self.get_precond(hdiag) if x0 is None: x0 = self.init_guess(self._scf, self.nstates) w2, x1 = lib.davidson1(vind, x0, precond, tol=self.conv_tol, nroots=self.nstates, lindep=self.lindep, max_space=self.max_space, verbose=self.verbose)[1:] mo_energy = self._scf.mo_energy mo_occ = self._scf.mo_occ occidx = numpy.where(mo_occ==2)[0] viridx = numpy.where(mo_occ==0)[0] eai = lib.direct_sum('a-i->ai', mo_energy[viridx], mo_energy[occidx]) eai = numpy.sqrt(eai) def norm_xy(w, z): zp = eai * z.reshape(eai.shape) zm = w/eai * z.reshape(eai.shape) x = (zp + zm) * .5 y = (zp - zm) * .5 norm = 2*(lib.norm(x)**2 - lib.norm(y)**2) norm = 1/numpy.sqrt(norm) return (x*norm, y*norm) self.e = numpy.sqrt(w2) self.xy = [norm_xy(self.e[i], z) for i, z in enumerate(x1)] return self.e, self.xy
def kernel(myci, eris, ci0=None, max_cycle=50, tol=1e-8, verbose=logger.INFO): if isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(myci.stdout, verbose) mol = myci.mol nmo = myci.nmo nocc = myci.nocc nvir = nmo - nocc diag = myci.make_diagonal(eris) ehf = diag[0] diag -= ehf if ci0 is None: ci0 = myci.get_init_guess(eris)[1] def op(xs): return [myci.contract(x, eris) for x in xs] def precond(x, e, *args): diagd = diag - (e-myci.level_shift) diagd[abs(diagd)<1e-8] = 1e-8 return x / diagd def cisd_dot(x1, x2): return dot(x1, x2, nocc, nvir) conv, ecisd, ci = lib.davidson1(op, ci0, precond, tol=tol, max_cycle=max_cycle, max_space=myci.max_space, lindep=myci.lindep, dot=cisd_dot, nroots=myci.nroots, verbose=log) if myci.nroots == 1: conv = conv[0] ecisd = ecisd[0] ci = ci[0] return conv, ecisd, ci
def kernel(self, x0=None): '''TDDFT diagonalization solver ''' if self._scf._numint.libxc.is_hybrid_xc(self._scf.xc): raise RuntimeError('%s cannot be applied with hybrid functional' % self.__class__) self.check_sanity() mo_energy = self._scf.mo_energy nocc = (self._scf.mo_occ>0).sum() eai = lib.direct_sum('a-i->ai', mo_energy[nocc:], mo_energy[:nocc]) if x0 is None: x0 = self.init_guess(eai, self.nstates) precond = self.get_precond(eai.ravel()**2) w2, x1 = lib.davidson1(self.get_vind, x0, precond, tol=self.conv_tol, nroots=self.nstates, lindep=self.lindep, max_space=self.max_space, verbose=self.verbose)[1:] self.e = numpy.sqrt(w2) eai = numpy.sqrt(eai) def norm_xy(w, z): zp = eai * z.reshape(eai.shape) zm = w/eai * z.reshape(eai.shape) x = (zp + zm) * .5 y = (zp - zm) * .5 norm = 2*(lib.norm(x)**2 - lib.norm(y)**2) norm = 1/numpy.sqrt(norm) return x*norm,y*norm self.xy = [norm_xy(self.e[i], z) for i, z in enumerate(x1)] return self.e, self.xy
def kernel(self, x0=None): '''TDA diagonalization solver ''' self.check_sanity() self.dump_flags() vind, hdiag = self.get_vind(self._scf) precond = self.get_precond(hdiag) if x0 is None: x0 = self.init_guess(self._scf, self.nstates) self.e, x1 = lib.davidson1(vind, x0, precond, tol=self.conv_tol, nroots=self.nstates, lindep=self.lindep, max_space=self.max_space, verbose=self.verbose)[1:] mo_occ = self._scf.mo_occ # 1/sqrt(2) because self.x is for alpha excitation amplitude and 2(X^+*X) = 1 self.xy = [(_unpack(xi * numpy.sqrt(.5), mo_occ), 0) for xi in x1] return self.e, self.xy
def kernel(self, x0=None): '''TDA diagonalization solver ''' self.check_sanity() self.dump_flags() vind, hdiag = self.gen_vind(self._scf) precond = self.get_precond(hdiag) if x0 is None: x0 = self.init_guess(self._scf, self.nstates) def pickeig(w, v, nroots, envs): idx = numpy.where(w > POSTIVE_EIG_THRESHOLD)[0] return w[idx], v[:, idx], idx log = logger.Logger(self.stdout, self.verbose) precision = self.cell.precision * 1e-2 hermi = 1 self.converged, self.e, x1 = \ lib.davidson1(vind, x0, precond, tol=self.conv_tol, nroots=self.nstates, lindep=self.lindep, max_space=self.max_space, pick=pickeig, fill_heff=purify_krlyov_heff(precision, hermi, log), verbose=self.verbose) mo_occ = self._scf.mo_occ self.xy = [ ( _unpack(xi, mo_occ), # (X_alpha, X_beta) (0, 0)) # (Y_alpha, Y_beta) for xi in x1 ] #TODO: analyze CIS wfn point group symmetry return self.e, self.xy
def kernel(self, x0=None): '''TDA diagonalization solver ''' self.check_sanity() self.dump_flags() vind, hdiag = self.get_vind(self._scf) precond = self.get_precond(hdiag) if x0 is None: x0 = self.init_guess(self._scf, self.nstates) self.e, x1 = lib.davidson1(vind, x0, precond, tol=self.conv_tol, nroots=self.nstates, lindep=self.lindep, max_space=self.max_space, verbose=self.verbose)[1:] mo_occ = self._scf.mo_occ tot_x_a = sum((occ>0).sum()*(occ==0).sum() for occ in mo_occ[0]) self.xy = [(_unpack(xi, mo_occ), # (X_alpha, X_beta) (0, 0)) # (Y_alpha, Y_beta) for xi in x1] #TODO: analyze CIS wfn point group symmetry return self.e, self.xy
def kernel(myci, eris, ci0=None, max_cycle=50, tol=1e-8, verbose=logger.INFO): ''' Run CISD calculation. Args: myci : CISD (inheriting) object eris : ccsd._ChemistsERIs (inheriting) object (poss diff for df) Contains the various (pq|rs) integrals needed. Kwargs: ci0 : (List of) numpy array(s) (if None it will set) Initial guess for CISD coeffs. max_cycle : integer Maximum number of iterations to converge to CISD solution. If not converged before, calculation stops without having converged. tol : float Convergence tolerance. verbose : integer Level of output (roughly: the higher, the more output). Returns: conv : bool Is it converged? ecisd : List of floats or float The lowest :attr:`myci.nroots` eigenvalues. ci : List of 1D arrays or 1D array The lowest :attr:`myci.nroots` eigenvectors. ''' log = logger.new_logger(myci, verbose) diag = myci.make_diagonal(eris) # Note that ehf is not the HF energy (see `make_diagonal`). ehf = diag[0] diag -= ehf if ci0 is None: ci0 = myci.get_init_guess(eris=eris, nroots=myci.nroots, diag=diag)[1] def op(xs): return [myci.contract(x, eris) for x in xs] def precond(x, e, *args): diagd = diag - (e - myci.level_shift) diagd[abs(diagd) < 1e-8] = 1e-8 return x / diagd if myci._dot is not None: nmo = myci.nmo nocc = myci.nocc def cisd_dot(x1, x2): return myci._dot(x1, x2, nmo, nocc) else: cisd_dot = numpy.dot conv, ecisd, ci = lib.davidson1(op, ci0, precond, tol=tol, max_cycle=max_cycle, max_space=myci.max_space, lindep=myci.lindep, dot=cisd_dot, nroots=myci.nroots, verbose=log) if myci.nroots == 1: conv = conv[0] ecisd = ecisd[0] ci = ci[0] return conv, ecisd, ci
def kernel(self, x0=None, nstates=None): '''TDDFT diagonalization solver ''' cpu0 = (time.clock(), time.time()) mf = self._scf if mf._numint.libxc.is_hybrid_xc(mf.xc): raise RuntimeError('%s cannot be used with hybrid functional' % self.__class__) self.check_sanity() self.dump_flags() if nstates is None: nstates = self.nstates else: self.nstates = nstates log = lib.logger.Logger(self.stdout, self.verbose) vind, hdiag = self.get_vind(self._scf) precond = self.get_precond(hdiag) if x0 is None: x0 = self.init_guess(self._scf, self.nstates) def pickeig(w, v, nroots, envs): idx = numpy.where(w > POSTIVE_EIG_THRESHOLD**2)[0] return w[idx], v[:, idx], idx self.converged, w2, x1 = \ lib.davidson1(vind, x0, precond, tol=self.conv_tol, nroots=nstates, lindep=self.lindep, max_space=self.max_space, pick=pickeig, verbose=log) mo_energy = self._scf.mo_energy mo_occ = self._scf.mo_occ occidxa = numpy.where(mo_occ[0] > 0)[0] occidxb = numpy.where(mo_occ[1] > 0)[0] viridxa = numpy.where(mo_occ[0] == 0)[0] viridxb = numpy.where(mo_occ[1] == 0)[0] nocca = len(occidxa) noccb = len(occidxb) nvira = len(viridxa) nvirb = len(viridxb) e_ia_a = (mo_energy[0][viridxa, None] - mo_energy[0][occidxa]).T e_ia_b = (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]).T e_ia = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1))) e_ia = numpy.sqrt(e_ia) e = [] xy = [] for i, z in enumerate(x1): if w2[i] < POSTIVE_EIG_THRESHOLD**2: continue w = numpy.sqrt(w2[i]) zp = e_ia * z zm = w / e_ia * z x = (zp + zm) * .5 y = (zp - zm) * .5 norm = lib.norm(x)**2 - lib.norm(y)**2 if norm > 0: norm = 1 / numpy.sqrt(norm) e.append(w) xy.append(( ( x[:nocca * nvira].reshape(nocca, nvira) * norm, # X_alpha x[nocca * nvira:].reshape(noccb, nvirb) * norm), # X_beta ( y[:nocca * nvira].reshape(nocca, nvira) * norm, # Y_alpha y[nocca * nvira:].reshape(noccb, nvirb) * norm))) # Y_beta self.e = numpy.array(e) self.xy = xy if self.chkfile: lib.chkfile.save(self.chkfile, 'tddft/e', self.e) lib.chkfile.save(self.chkfile, 'tddft/xy', self.xy) log.timer('TDDFT', *cpu0) log.note('Excited State energies (eV)\n%s', self.e * nist.HARTREE2EV) return self.e, self.xy
def kernel(self, x0=None, nstates=None): '''TDDFT diagonalization solver ''' mf = self._scf if mf._numint.libxc.is_hybrid_xc(mf.xc): raise RuntimeError('%s cannot be used with hybrid functional' % self.__class__) self.check_sanity() self.dump_flags() if nstates is None: nstates = self.nstates else: self.nstates = nstates log = lib.logger.Logger(self.stdout, self.verbose) vind, hdiag = self.get_vind(self._scf) precond = self.get_precond(hdiag) if x0 is None: x0 = self.init_guess(self._scf, self.nstates) def pickeig(w, v, nroots, envs): idx = numpy.where(w > POSTIVE_EIG_THRESHOLD**2)[0] return w[idx], v[:,idx], idx self.converged, w2, x1 = \ lib.davidson1(vind, x0, precond, tol=self.conv_tol, nroots=nstates, lindep=self.lindep, max_space=self.max_space, pick=pickeig, verbose=log) mo_energy = self._scf.mo_energy mo_occ = self._scf.mo_occ occidxa = numpy.where(mo_occ[0]>0)[0] occidxb = numpy.where(mo_occ[1]>0)[0] viridxa = numpy.where(mo_occ[0]==0)[0] viridxb = numpy.where(mo_occ[1]==0)[0] nocca = len(occidxa) noccb = len(occidxb) nvira = len(viridxa) nvirb = len(viridxb) e_ia_a = (mo_energy[0][viridxa,None] - mo_energy[0][occidxa]).T e_ia_b = (mo_energy[1][viridxb,None] - mo_energy[1][occidxb]).T e_ia = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1))) e_ia = numpy.sqrt(e_ia) e = [] xy = [] for i, z in enumerate(x1): if w2[i] < POSTIVE_EIG_THRESHOLD**2: continue w = numpy.sqrt(w2[i]) zp = e_ia * z zm = w/e_ia * z x = (zp + zm) * .5 y = (zp - zm) * .5 norm = lib.norm(x)**2 - lib.norm(y)**2 if norm > 0: norm = 1/numpy.sqrt(norm) e.append(w) xy.append(((x[:nocca*nvira].reshape(nocca,nvira) * norm, # X_alpha x[nocca*nvira:].reshape(noccb,nvirb) * norm), # X_beta (y[:nocca*nvira].reshape(nocca,nvira) * norm, # Y_alpha y[nocca*nvira:].reshape(noccb,nvirb) * norm)))# Y_beta self.e = numpy.array(e) self.xy = xy if self.chkfile: lib.chkfile.save(self.chkfile, 'tddft/e', self.e) lib.chkfile.save(self.chkfile, 'tddft/xy', self.xy) log.note('Excited State energies (eV)\n%s', self.e * nist.HARTREE2EV) return self.e, self.xy
def kernel(self, x0=None, nstates=None): '''TDDFT diagonalization solver ''' cpu0 = (lib.logger.process_clock(), lib.logger.perf_counter()) mf = self._scf if mf._numint.libxc.is_hybrid_xc(mf.xc): raise RuntimeError('%s cannot be used with hybrid functional' % self.__class__) self.check_sanity() self.dump_flags() if nstates is None: nstates = self.nstates else: self.nstates = nstates log = lib.logger.Logger(self.stdout, self.verbose) vind, hdiag = self.gen_vind(self._scf) precond = self.get_precond(hdiag) if x0 is None: x0 = self.init_guess(self._scf, self.nstates) def pickeig(w, v, nroots, envs): idx = numpy.where(w > self.positive_eig_threshold)[0] return w[idx], v[:, idx], idx self.converged, w2, x1 = \ lib.davidson1(vind, x0, precond, tol=self.conv_tol, nroots=nstates, lindep=self.lindep, max_cycle=self.max_cycle, max_space=self.max_space, pick=pickeig, verbose=log) mo_energy = self._scf.mo_energy mo_occ = self._scf.mo_occ occidx = numpy.where(mo_occ == 1)[0] viridx = numpy.where(mo_occ == 0)[0] e_ia = (mo_energy[viridx, None] - mo_energy[occidx]).T e_ia = numpy.sqrt(e_ia) def norm_xy(w, z): zp = e_ia * z.reshape(e_ia.shape) zm = w / e_ia * z.reshape(e_ia.shape) x = (zp + zm) * .5 y = (zp - zm) * .5 norm = lib.norm(x)**2 - lib.norm(y)**2 norm = numpy.sqrt(1. / norm) return (x * norm, y * norm) idx = numpy.where(w2 > self.positive_eig_threshold)[0] self.e = numpy.sqrt(w2[idx]) self.xy = [norm_xy(self.e[i], x1[i]) for i in idx] if self.chkfile: lib.chkfile.save(self.chkfile, 'tddft/e', self.e) lib.chkfile.save(self.chkfile, 'tddft/xy', self.xy) log.timer('TDDFT', *cpu0) self._finalize() return self.e, self.xy
def davidson(self, *args, **kwargs): return lib.davidson1(*args, **kwargs)
def davidson(auxspc, phys, chempot=None, nroots=1, which='SM', tol=1e-14, maxiter=None, ntrial=None): ''' Diagonalise the result of :func:`AuxiliarySpace.get_array` using the sparse :func:`AuxiliarySpace.dot` method, with the Davidson algorithm. This algorithm may perform poorly for IPs or EAs if they are not extremal eigenvalues, which they are not in standard AGF2. Args: auxspc : AuxiliarySpace or subclass Auxiliary space object to solve for phys : 2D array Physical space (1p + 1h), typically the Fock matrix Kwargs: chempot : float If provided, use instead of :attr:`self.chempot` nroots : int Number of roots to solve for. Default 1. which : str Which eigenvalues to solve for. Options are: `LM` : Largest (in magnitude) eigenvalues. `SM` : Smallest (in magnitude) eigenvalues. `LA` : Largest (algebraic) eigenvalues. `SA` : Smallest (algebraic) eigenvalues. Default 'SM'. tol : float Convergence threshold maxiter : int Maximum number of iterations. Default 10*dim ntrial : int Maximum number of trial vectors. Default min(dim, max(2*nroots+1, 20)) Returns: tuple of ndarrays (eigenvalues, eigenvectors) ''' _check_phys_shape(auxspc, phys) dim = auxspc.nphys + auxspc.naux if maxiter is None: maxiter = 10 * dim if ntrial is None: ntrial = min(dim, max(2*nroots+1, 20)) if which not in ['SM', 'LM', 'SA', 'LA']: raise ValueError(which) if which in ['SM', 'LM']: abs_op = np.absolute else: abs_op = lambda x: x if which in ['SM', 'SA']: order = 1 else: order = -1 matvec = lambda x: auxspc.dot(phys, np.asarray(x)) diag = np.concatenate([np.diag(phys), auxspc.energy]) guess = [np.zeros((dim)) for n in range(nroots)] mask = np.argsort(abs_op(diag))[::order] for i in range(nroots): guess[i][mask[i]] = 1 def pick(w, v, nroots, callback): mask = np.argsort(abs_op(w)) mask = mask[::order] w = w[mask] v = v[:,mask] return w, v, 0 conv, w, v = lib.davidson1(matvec, guess, diag, tol=tol, nroots=nroots, max_space=ntrial, max_cycle=maxiter, pick=pick) return conv, w, v
def kernel(self, x0=None): '''TDDFT diagonalization solver ''' mf = self._scf if mf._numint.libxc.is_hybrid_xc(mf.xc): raise RuntimeError('%s cannot be applied with hybrid functional' % self.__class__) self.check_sanity() self.dump_flags() vind, hdiag = self.get_vind(self._scf) precond = self.get_precond(hdiag) if x0 is None: x0 = self.init_guess(self._scf, self.nstates) w2, x1 = lib.davidson1(vind, x0, precond, tol=self.conv_tol, nroots=self.nstates, lindep=self.lindep, max_space=self.max_space, verbose=self.verbose)[1:] mo_energy = self._scf.mo_energy mo_occ = self._scf.mo_occ occidxa = numpy.where(mo_occ[0] > 0)[0] occidxb = numpy.where(mo_occ[1] > 0)[0] viridxa = numpy.where(mo_occ[0] == 0)[0] viridxb = numpy.where(mo_occ[1] == 0)[0] nocca = len(occidxa) noccb = len(occidxb) nvira = len(viridxa) nvirb = len(viridxb) e_ai_a = mo_energy[0][viridxa].reshape(-1, 1) - mo_energy[0][occidxa] e_ai_b = mo_energy[1][viridxb].reshape(-1, 1) - mo_energy[1][occidxb] eai = numpy.hstack((e_ai_a.reshape(-1), e_ai_b.reshape(-1))) eai = numpy.sqrt(eai) e = [] xy = [] for i, z in enumerate(x1): if w2[i] < 0: continue w = numpy.sqrt(w2[i]) zp = eai * z zm = w / eai * z x = (zp + zm) * .5 y = (zp - zm) * .5 norm = lib.norm(x)**2 - lib.norm(y)**2 if norm > 0: norm = 1 / numpy.sqrt(norm) e.append(w) xy.append(( ( x[:nocca * nvira].reshape(nvira, nocca) * norm, # X_alpha x[nocca * nvira:].reshape(nvirb, noccb) * norm), # X_beta ( y[:nocca * nvira].reshape(nvira, nocca) * norm, # Y_alpha y[nocca * nvira:].reshape(nvirb, noccb) * norm))) # Y_beta self.e = numpy.array(e) self.xy = xy return self.e, self.xy