def solve_mo1_fc(sscobj, h1): cput1 = (time.clock(), time.time()) log = logger.Logger(sscobj.stdout, sscobj.verbose) mol = sscobj.mol mo_energy = sscobj._scf.mo_energy mo_coeff = sscobj._scf.mo_coeff mo_occ = sscobj._scf.mo_occ nset = len(h1) eai = 1. / lib.direct_sum('a-i->ai', mo_energy[mo_occ==0], mo_energy[mo_occ>0]) mo1 = numpy.asarray(h1) * -eai if not sscobj.cphf: return mo1 orbo = mo_coeff[:,mo_occ> 0] orbv = mo_coeff[:,mo_occ==0] nocc = orbo.shape[1] nvir = orbv.shape[1] nmo = nocc + nvir vresp = _gen_rhf_response(sscobj._scf, singlet=False, hermi=1) mo_v_o = numpy.asarray(numpy.hstack((orbv,orbo)), order='F') def vind(mo1): dm1 = _dm1_mo2ao(mo1.reshape(nset,nvir,nocc), orbv, orbo*2) # *2 for double occupancy dm1 = dm1 + dm1.transpose(0,2,1) v1 = vresp(dm1) v1 = _ao2mo.nr_e2(v1, mo_v_o, (0,nvir,nvir,nmo)).reshape(nset,nvir,nocc) v1 *= eai return v1.ravel() mo1 = lib.krylov(vind, mo1.ravel(), tol=sscobj.conv_tol, max_cycle=sscobj.max_cycle_cphf, verbose=log) log.timer('solving FC CPHF eqn', *cput1) return mo1.reshape(nset,nvir,nocc)
def solve_withs1(fvind, mo_energy, mo_occ, h1, s1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): ''' C^1_{ij} = -1/2 S1 e1 = h1 - s1*e0 + (e0_j-e0_i)*c1 + vhf[c1] ''' if isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(sys.stdout, verbose) t0 = (time.clock(), time.time()) occidx = mo_occ > 0 viridx = mo_occ == 0 e_a = mo_energy[viridx] e_i = mo_energy[occidx] e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i) nvir, nocc = e_ai.shape nmo = nocc + nvir # Do not reshape h1 because h1 may be a 2D array (nvir,nocc) s1 = s1.reshape(-1, nmo, nocc) hs = mo1base = h1.reshape(-1, nmo, nocc) - s1 * e_i mo_e1 = hs[:, occidx, :].copy() mo1base[:, viridx] *= -e_ai mo1base[:, occidx] = -s1[:, occidx] * .5 def vind_vo(mo1): v = fvind(mo1.reshape(h1.shape)).reshape(-1, nmo, nocc) v[:, viridx, :] *= e_ai v[:, occidx, :] = 0 return v.ravel() mo1 = lib.krylov(vind_vo, mo1base.ravel(), tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) mo1 = mo1.reshape(mo1base.shape) log.timer('krylov solver in CPHF', *t0) v_mo = fvind(mo1.reshape(h1.shape)).reshape(-1, nmo, nocc) mo1[:, viridx] = mo1base[:, viridx] - v_mo[:, viridx] * e_ai mo_e1 += mo1[:, occidx] * lib.direct_sum('i-j->ij', e_i, e_i) mo_e1 += v_mo[:, occidx, :] if h1.ndim == 3: return mo1, mo_e1 else: return mo1.reshape(h1.shape), mo_e1.reshape(nocc, nocc)
def solve_nos1(fvind, mo_energy, mo_occ, h1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): if isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(sys.stdout, verbose) t0 = (time.clock(), time.time()) e_a = mo_energy[mo_occ==0] e_i = mo_energy[mo_occ>0] e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i) nocc = e_i.size nvir = e_a.size nmo = nocc + nvir mo1base = h1 * -e_ai def vind_vo(mo1): v = fvind(mo1.reshape(h1.shape)).reshape(h1.shape) v *= e_ai return v.ravel() mo1 = lib.krylov(vind_vo, mo1base.ravel(), tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) log.timer('krylov solver in CPHF', *t0) return mo1.reshape(h1.shape), None
def solve_nos1(fvind, mo_energy, mo_occ, h1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): '''For field independent basis. First order overlap matrix is zero''' log = logger.new_logger(verbose=verbose) t0 = (time.clock(), time.time()) e_a = mo_energy[mo_occ == 0] e_i = mo_energy[mo_occ > 0] e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i) mo1base = h1 * -e_ai def vind_vo(mo1): v = fvind(mo1.reshape(h1.shape)).reshape(h1.shape) v *= e_ai return v.ravel() mo1 = lib.krylov(vind_vo, mo1base.ravel(), tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) log.timer('krylov solver in CPHF', *t0) return mo1.reshape(h1.shape), None
def solve_withs1(fvind, mo_energy, mo_occ, h1, s1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): '''For field dependent basis. First order overlap matrix is non-zero. The first order orbitals are set to C^1_{ij} = -1/2 S1 e1 = h1 - s1*e0 + (e0_j-e0_i)*c1 + vhf[c1] ''' log = logger.new_logger(verbose=verbose) t0 = (time.clock(), time.time()) occidx = mo_occ > 0 viridx = mo_occ == 0 e_a = mo_energy[viridx] e_i = mo_energy[occidx] e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i) nvir, nocc = e_ai.shape nmo = nocc + nvir s1 = s1.reshape(-1, nmo, nocc) hs = mo1base = h1.reshape(-1, nmo, nocc) - s1 * e_i mo_e1 = hs[:, occidx, :].copy() mo1base[:, viridx] *= -e_ai mo1base[:, occidx] = -s1[:, occidx] * .5 def vind_vo(mo1): v = fvind(mo1.reshape(h1.shape)).reshape(-1, nmo, nocc) v[:, viridx, :] *= e_ai v[:, occidx, :] = 0 return v.ravel() mo1 = lib.krylov(vind_vo, mo1base.ravel(), tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) mo1 = mo1.reshape(mo1base.shape) log.timer('krylov solver in CPHF', *t0) v1mo = fvind(mo1.reshape(h1.shape)).reshape(-1, nmo, nocc) mo1[:, viridx] = mo1base[:, viridx] - v1mo[:, viridx] * e_ai mo_e1 += mo1[:, occidx] * lib.direct_sum('i-j->ij', e_i, e_i) mo_e1 += v1mo[:, occidx, :] if h1.ndim == 3: return mo1, mo_e1 else: return mo1.reshape(h1.shape), mo_e1.reshape(nocc, nocc)
def solve_withs1(fvind, mo_energy, mo_occ, h1, s1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): '''For field dependent basis. First order overlap matrix is non-zero. The first order orbitals are set to C^1_{ij} = -1/2 S1 e1 = h1 - s1*e0 + (e0_j-e0_i)*c1 + vhf[c1] Kwargs: hermi : boolean Whether the matrix defined by fvind is Hermitian or not. Returns: First order orbital coefficients (in MO basis) and first order orbital energy matrix ''' log = logger.new_logger(verbose=verbose) t0 = (time.clock(), time.time()) occidx = mo_occ > 0 viridx = mo_occ == 0 e_a = mo_energy[viridx] e_i = mo_energy[occidx] e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i) nvir, nocc = e_ai.shape nmo = nocc + nvir s1 = s1.reshape(-1,nmo,nocc) hs = mo1base = h1.reshape(-1,nmo,nocc) - s1*e_i mo_e1 = hs[:,occidx,:].copy() mo1base[:,viridx] *= -e_ai mo1base[:,occidx] = -s1[:,occidx] * .5 def vind_vo(mo1): v = fvind(mo1.reshape(h1.shape)).reshape(-1,nmo,nocc) v[:,viridx,:] *= e_ai v[:,occidx,:] = 0 return v.ravel() mo1 = lib.krylov(vind_vo, mo1base.ravel(), tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) mo1 = mo1.reshape(mo1base.shape) log.timer('krylov solver in CPHF', *t0) v1mo = fvind(mo1.reshape(h1.shape)).reshape(-1,nmo,nocc) mo1[:,viridx] = mo1base[:,viridx] - v1mo[:,viridx]*e_ai # mo_e1 has the same symmetry as the first order Fock matrix (hermitian or # anti-hermitian). mo_e1 = v1mo - s1*lib.direct_sum('i+j->ij',e_i,e_i) mo_e1 += mo1[:,occidx] * lib.direct_sum('i-j->ij', e_i, e_i) mo_e1 += v1mo[:,occidx,:] if h1.ndim == 3: return mo1, mo_e1 else: return mo1.reshape(h1.shape), mo_e1.reshape(nocc,nocc)
def solve_nos1(fvind, mo_energy, mo_occ, h1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): '''For field independent basis. First order overlap matrix is zero''' log = logger.new_logger(verbose=verbose) t0 = (time.clock(), time.time()) nkpt = len(h1) moloc = np.zeros([nkpt + 1], dtype=int) for k in range(nkpt): moloc[k + 1] = moloc[k] + h1[k].size occidx = [] viridx = [] for k in range(nkpt): occidx.append(mo_occ[k] > 0) viridx.append(mo_occ[k] == 0) e_a = [mo_energy[k][viridx[k]] for k in range(nkpt)] e_i = [mo_energy[k][occidx[k]] for k in range(nkpt)] e_ai = [1 / lib.direct_sum('a-i->ai', e_a[k], e_i[k]) for k in range(nkpt)] mo1base = [] for k in range(nkpt): mo1base.append((h1[k] * -e_ai[k]).ravel()) mo1base = np.hstack(mo1base) def vind_vo(mo1): mo1 = mo1.flatten() tmp = [] for k in range(nkpt): tmp.append(mo1[moloc[k]:moloc[k + 1]].reshape(h1[k].shape)) v = fvind(tmp) for k in range(nkpt): v[k] *= e_ai[k] v[k] = v[k].ravel() return np.hstack(v) _mo1 = lib.krylov(vind_vo, mo1base, tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log).flatten() log.timer('krylov solver in CPHF', *t0) mo1 = [] for k in range(nkpt): mo1.append(_mo1[moloc[k]:moloc[k + 1]].reshape(h1[k].shape)) return mo1, None
def solve_nos1(fvind, mo_energy, mo_occ, h1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): '''For field independent basis. First order overlap matrix is zero''' log = logger.new_logger(verbose=verbose) t0 = (time.clock(), time.time()) occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 viridxa = ~occidxa viridxb = ~occidxb nocca = numpy.count_nonzero(occidxa) noccb = numpy.count_nonzero(occidxb) nvira = mo_occ[0].size - nocca nvirb = mo_occ[1].size - noccb e_ai = numpy.hstack( ((mo_energy[0][viridxa, None] - mo_energy[0][occidxa]).ravel(), (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]).ravel())) e_ai = 1 / e_ai mo1base = numpy.hstack( (h1[0].reshape(-1, nvira * nocca), h1[1].reshape(-1, nvirb * noccb))) mo1base *= -e_ai def vind_vo(mo1): v = fvind(mo1.reshape(mo1base.shape)).reshape(mo1base.shape) v *= e_ai return v.ravel() mo1 = lib.krylov(vind_vo, mo1base.ravel(), tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) log.timer('krylov solver in CPHF', *t0) if isinstance(h1[0], numpy.ndarray) and h1[0].ndim == 2: mo1 = (mo1[:nocca * nvira].reshape(nvira, nocca), mo1[nocca * nvira:].reshape(nvirb, noccb)) else: mo1 = mo1.reshape(mo1base.shape) mo1_a = mo1[:, :nvira * nocca].reshape(-1, nvira, nocca) mo1_b = mo1[:, nvira * nocca:].reshape(-1, nvirb, noccb) mo1 = (mo1_a, mo1_b) return mo1, None
def solve_withs1(fvind, mo_energy, mo_occ, h1, s1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): ''' C^1_{ij} = -1/2 S1 e1 = h1 - s1*e0 + (e0_j-e0_i)*c1 + vhf[c1] ''' if isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(sys.stdout, verbose) t0 = (time.clock(), time.time()) occidx = mo_occ > 0 viridx = mo_occ == 0 e_a = mo_energy[viridx] e_i = mo_energy[occidx] e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i) nvir, nocc = e_ai.shape nmo = nocc + nvir # Do not reshape h1 because h1 may be a 2D array (nvir,nocc) s1 = s1.reshape(-1,nmo,nocc) hs = mo1base = h1.reshape(-1,nmo,nocc) - s1*e_i mo_e1 = hs[:,occidx,:].copy() mo1base[:,viridx] *= -e_ai mo1base[:,occidx] = -s1[:,occidx] * .5 def vind_vo(mo1): v = fvind(mo1.reshape(h1.shape)).reshape(-1,nmo,nocc) v[:,viridx,:] *= e_ai v[:,occidx,:] = 0 return v.ravel() mo1 = lib.krylov(vind_vo, mo1base.ravel(), tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) mo1 = mo1.reshape(mo1base.shape) log.timer('krylov solver in CPHF', *t0) v_mo = fvind(mo1.reshape(h1.shape)).reshape(-1,nmo,nocc) mo1[:,viridx] = mo1base[:,viridx] - v_mo[:,viridx]*e_ai mo_e1 += mo1[:,occidx] * lib.direct_sum('i-j->ij', e_i, e_i) mo_e1 += v_mo[:,occidx,:] if h1.ndim == 3: return mo1, mo_e1 else: return mo1.reshape(h1.shape), mo_e1.reshape(nocc,nocc)
def solve_nos1(fvind, mo_energy, mo_occ, h1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): '''For field independent basis. First order overlap matrix is zero''' log = logger.new_logger(verbose=verbose) t0 = (time.clock(), time.time()) e_a = mo_energy[mo_occ==0] e_i = mo_energy[mo_occ>0] e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i) mo1base = h1 * -e_ai def vind_vo(mo1): v = fvind(mo1.reshape(h1.shape)).reshape(h1.shape) v *= e_ai return v.ravel() mo1 = lib.krylov(vind_vo, mo1base.ravel(), tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) log.timer('krylov solver in CPHF', *t0) return mo1.reshape(h1.shape), None
def solve_withs1(fvind, mo_energy, mo_occ, h1, s1=None, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): if isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(sys.stdout, verbose) t0 = (time.clock(), time.time()) e_a = mo_energy[mo_occ==0] e_i = mo_energy[mo_occ>0] e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i) nocc = e_i.size nvir = e_a.size nmo = nocc + nvir hs = mo1base = h1.reshape(-1,nmo,nocc) - s1.reshape(-1,nmo,nocc)*e_i mo_e1 = hs[:,mo_occ>0,:].copy() mo1base[:,mo_occ==0] *= -e_ai mo1base[:,mo_occ>0] = -s1.reshape(-1,nmo,nocc)[:,mo_occ>0] * .5 e_ij = lib.direct_sum('i-j->ij', e_i, e_i) mo_e1 += mo1base[:,mo_occ>0,:] * e_ij def vind_vo(mo1): v = fvind(mo1.reshape(h1.shape)).reshape(mo1base.shape) v[:,mo_occ==0,:] *= e_ai v[:,mo_occ>0,:] = 0 return v.ravel() mo1 = lib.krylov(vind_vo, mo1base.ravel(), tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) mo1 = mo1.reshape(mo1base.shape) log.timer('krylov solver in CPHF', *t0) v_mo = fvind(mo1.reshape(h1.shape)).reshape(mo1base.shape) mo_e1 -= v_mo[:,mo_occ>0,:] mo1[:,mo_occ==0] = mo1base[:,mo_occ==0] - v_mo[:,mo_occ==0]*e_ai if h1.ndim == 3: return mo1, mo_e1 else: return mo1.reshape(h1.shape), mo_e1.reshape(nocc,nocc)
def solve_nos1(fvind, mo_energy, mo_occ, h1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): '''For field independent basis. First order overlap matrix is zero''' log = logger.new_logger(verbose=verbose) t0 = (time.clock(), time.time()) occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 viridxa = ~occidxa viridxb = ~occidxb nocca = numpy.count_nonzero(occidxa) noccb = numpy.count_nonzero(occidxb) nvira = mo_occ[0].size - nocca nvirb = mo_occ[1].size - noccb e_ai = numpy.hstack(((mo_energy[0][viridxa,None]-mo_energy[0][occidxa]).ravel(), (mo_energy[1][viridxb,None]-mo_energy[1][occidxb]).ravel())) e_ai = 1 / e_ai mo1base = numpy.hstack((h1[0].reshape(-1,nvira*nocca), h1[1].reshape(-1,nvirb*noccb))) mo1base *= -e_ai def vind_vo(mo1): v = fvind(mo1.reshape(mo1base.shape)).reshape(mo1base.shape) v *= e_ai return v.ravel() mo1 = lib.krylov(vind_vo, mo1base.ravel(), tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) log.timer('krylov solver in CPHF', *t0) if isinstance(h1[0], numpy.ndarray) and h1[0].ndim == 2: mo1 = (mo1[:nocca*nvira].reshape(nvira,nocca), mo1[nocca*nvira:].reshape(nvirb,noccb)) else: mo1 = mo1.reshape(mo1base.shape) mo1_a = mo1[:,:nvira*nocca].reshape(-1,nvira,nocca) mo1_b = mo1[:,nvira*nocca:].reshape(-1,nvirb,noccb) mo1 = (mo1_a, mo1_b) return mo1, None
def solve_nos1(fvind, mo_energy, mo_occ, h1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): if isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(sys.stdout, verbose) t0 = (time.clock(), time.time()) e_a = mo_energy[mo_occ == 0] e_i = mo_energy[mo_occ > 0] e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i) nocc = e_i.size nvir = e_a.size nmo = nocc + nvir mo1base = h1 * -e_ai def vind_vo(mo1): v = fvind(mo1.reshape(h1.shape)).reshape(h1.shape) v *= e_ai return v.ravel() mo1 = lib.krylov(vind_vo, mo1base.ravel(), tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) log.timer('krylov solver in CPHF', *t0) return mo1.reshape(h1.shape), None
def solve_mo1_fc(sscobj, h1): cput1 = (time.clock(), time.time()) log = logger.Logger(sscobj.stdout, sscobj.verbose) mol = sscobj.mol mf = sscobj._scf mo_energy = mf.mo_energy mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ h1aa, h1ab, h1ba, h1bb = h1 eai_aa = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0]==0], mo_energy[0][mo_occ[0]>0]) eai_ab = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0]==0], mo_energy[1][mo_occ[1]>0]) eai_ba = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1]==0], mo_energy[0][mo_occ[0]>0]) eai_bb = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1]==0], mo_energy[1][mo_occ[1]>0]) mo1aa = numpy.asarray(h1aa) * -eai_aa mo1ab = numpy.asarray(h1ab) * -eai_ab mo1ba = numpy.asarray(h1ba) * -eai_ba mo1bb = numpy.asarray(h1bb) * -eai_bb mo1_fc = (mo1aa, mo1ab, mo1ba, mo1bb) if not sscobj.cphf: return mo1_fc orboa = mo_coeff[0][:,mo_occ[0]> 0] orbva = mo_coeff[0][:,mo_occ[0]==0] orbob = mo_coeff[1][:,mo_occ[1]> 0] orbvb = mo_coeff[1][:,mo_occ[1]==0] nocca = orboa.shape[1] nvira = orbva.shape[1] noccb = orbob.shape[1] nvirb = orbvb.shape[1] nao = mol.nao vresp = _gen_uhf_response(mf, with_j=False, hermi=1) if ZZ_ONLY: # To make UHF/UKS and RHF/RKS code consistent, only z-component is # considered. nvars = nvira*nocca + nvirb*noccb nset = h1aa.size // eai_aa.size def _split_mo1(mo1): mo1 = mo1.reshape(nset,nvars) mo1aa = mo1[:,:nvira*nocca].reshape(nset,nvira,nocca) mo1bb = mo1[:,nvira*nocca:].reshape(nset,nvirb,noccb) return mo1aa, mo1ab, mo1ba, mo1bb mo1_fc = numpy.hstack((mo1_fc[0].reshape(nset,-1), mo1_fc[3].reshape(nset,-1))) mo_va_oa = numpy.asarray(numpy.hstack((orbva,orboa)), order='F') mo_vb_ob = numpy.asarray(numpy.hstack((orbvb,orbob)), order='F') def vind(mo1): mo1aa, mo1ab, mo1ba, mo1bb = _split_mo1(mo1) dm1aa = _dm1_mo2ao(mo1aa, orbva, orboa) dm1bb = _dm1_mo2ao(mo1bb, orbvb, orbob) dm1 = lib.asarray([dm1aa+dm1aa.transpose(0,2,1), dm1bb+dm1bb.transpose(0,2,1)]) v1 = vresp(dm1) v1aa = _ao2mo.nr_e2(v1[0], mo_va_oa, (0,nvira,nvira,nvira+nocca)) v1bb = _ao2mo.nr_e2(v1[1], mo_vb_ob, (0,nvirb,nvirb,nvirb+noccb)) v1aa = v1aa.reshape(nset,nvira,nocca) v1bb = v1bb.reshape(nset,nvirb,noccb) v1aa *= eai_aa v1bb *= eai_bb v1mo = numpy.hstack((v1aa.reshape(nset,-1), v1bb.reshape(nset,-1))) return v1mo.ravel() else: segs = (nvira*nocca, nvira*noccb, nvirb*nocca, nvirb*noccb) sections = numpy.cumsum(segs[:3]) nvars = numpy.sum(segs) nset = h1aa.size // eai_aa.size def _split_mo1(mo1): mo1 = numpy.split(mo1.reshape(nset,nvars), sections, axis=1) mo1aa = mo1[0].reshape(nset,nvira,nocca) mo1ab = mo1[1].reshape(nset,nvira,noccb) mo1ba = mo1[2].reshape(nset,nvirb,nocca) mo1bb = mo1[3].reshape(nset,nvirb,noccb) return mo1aa, mo1ab, mo1ba, mo1bb mo1_fc = numpy.hstack((mo1_fc[0].reshape(nset,-1), mo1_fc[1].reshape(nset,-1), mo1_fc[2].reshape(nset,-1), mo1_fc[3].reshape(nset,-1))) mo_va_oa = numpy.asarray(numpy.hstack((orbva,orboa)), order='F') mo_va_ob = numpy.asarray(numpy.hstack((orbva,orbob)), order='F') mo_vb_oa = numpy.asarray(numpy.hstack((orbvb,orboa)), order='F') mo_vb_ob = numpy.asarray(numpy.hstack((orbvb,orbob)), order='F') def vind(mo1): mo1aa, mo1ab, mo1ba, mo1bb = _split_mo1(mo1) dm1aa = _dm1_mo2ao(mo1aa, orbva, orboa) dm1ab = _dm1_mo2ao(mo1ab, orbva, orbob) dm1ba = _dm1_mo2ao(mo1ba, orbvb, orboa) dm1bb = _dm1_mo2ao(mo1bb, orbvb, orbob) dm1 = lib.asarray([dm1aa+dm1aa.transpose(0,2,1), dm1ab+dm1ba.transpose(0,2,1), dm1ba+dm1ab.transpose(0,2,1), dm1bb+dm1bb.transpose(0,2,1)]) v1 = vresp(dm1) v1aa = _ao2mo.nr_e2(v1[0], mo_va_oa, (0,nvira,nvira,nvira+nocca)) v1ab = _ao2mo.nr_e2(v1[1], mo_va_ob, (0,nvira,nvira,nvira+noccb)) v1ba = _ao2mo.nr_e2(v1[2], mo_vb_oa, (0,nvirb,nvirb,nvirb+nocca)) v1bb = _ao2mo.nr_e2(v1[3], mo_vb_ob, (0,nvirb,nvirb,nvirb+noccb)) v1aa = v1aa.reshape(nset,nvira,nocca) v1ab = v1ab.reshape(nset,nvira,noccb) v1ba = v1ba.reshape(nset,nvirb,nocca) v1bb = v1bb.reshape(nset,nvirb,noccb) v1aa *= eai_aa v1ab *= eai_ab v1ba *= eai_ba v1bb *= eai_bb v1mo = numpy.hstack((v1aa.reshape(nset,-1), v1ab.reshape(nset,-1), v1ba.reshape(nset,-1), v1bb.reshape(nset,-1))) return v1mo.ravel() mo1 = lib.krylov(vind, mo1_fc.ravel(), tol=sscobj.conv_tol, max_cycle=sscobj.max_cycle_cphf, verbose=log) log.timer('solving FC CPHF eqn', *cput1) mo1_fc = _split_mo1(mo1) return mo1_fc
def solve_mo1_fc(sscobj, h1): cput1 = (time.clock(), time.time()) log = logger.Logger(sscobj.stdout, sscobj.verbose) mol = sscobj.mol mf = sscobj._scf mo_energy = mf.mo_energy mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ h1aa, h1ab, h1ba, h1bb = h1 eai_aa = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0] == 0], mo_energy[0][mo_occ[0] > 0]) eai_ab = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0] == 0], mo_energy[1][mo_occ[1] > 0]) eai_ba = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1] == 0], mo_energy[0][mo_occ[0] > 0]) eai_bb = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1] == 0], mo_energy[1][mo_occ[1] > 0]) mo1aa = numpy.asarray(h1aa) * -eai_aa mo1ab = numpy.asarray(h1ab) * -eai_ab mo1ba = numpy.asarray(h1ba) * -eai_ba mo1bb = numpy.asarray(h1bb) * -eai_bb mo1_fc = (mo1aa, mo1ab, mo1ba, mo1bb) if not sscobj.cphf: return mo1_fc orboa = mo_coeff[0][:, mo_occ[0] > 0] orbva = mo_coeff[0][:, mo_occ[0] == 0] orbob = mo_coeff[1][:, mo_occ[1] > 0] orbvb = mo_coeff[1][:, mo_occ[1] == 0] nocca = orboa.shape[1] nvira = orbva.shape[1] noccb = orbob.shape[1] nvirb = orbvb.shape[1] nao = mol.nao vresp = _gen_uhf_response(mf, with_j=False, hermi=1) if ZZ_ONLY: # To make UHF/UKS and RHF/RKS code consistent, only z-component is # considered. nvars = nvira * nocca + nvirb * noccb nset = h1aa.size // eai_aa.size def _split_mo1(mo1): mo1 = mo1.reshape(nset, nvars) mo1aa = mo1[:, :nvira * nocca].reshape(nset, nvira, nocca) mo1bb = mo1[:, nvira * nocca:].reshape(nset, nvirb, noccb) return mo1aa, mo1ab, mo1ba, mo1bb mo1_fc = numpy.hstack( (mo1_fc[0].reshape(nset, -1), mo1_fc[3].reshape(nset, -1))) mo_va_oa = numpy.asarray(numpy.hstack((orbva, orboa)), order='F') mo_vb_ob = numpy.asarray(numpy.hstack((orbvb, orbob)), order='F') def vind(mo1): mo1aa, mo1ab, mo1ba, mo1bb = _split_mo1(mo1) dm1aa = _dm1_mo2ao(mo1aa, orbva, orboa) dm1bb = _dm1_mo2ao(mo1bb, orbvb, orbob) dm1 = lib.asarray([ dm1aa + dm1aa.transpose(0, 2, 1), dm1bb + dm1bb.transpose(0, 2, 1) ]) v1 = vresp(dm1) v1aa = _ao2mo.nr_e2(v1[0], mo_va_oa, (0, nvira, nvira, nvira + nocca)) v1bb = _ao2mo.nr_e2(v1[1], mo_vb_ob, (0, nvirb, nvirb, nvirb + noccb)) v1aa = v1aa.reshape(nset, nvira, nocca) v1bb = v1bb.reshape(nset, nvirb, noccb) v1aa *= eai_aa v1bb *= eai_bb v1mo = numpy.hstack((v1aa.reshape(nset, -1), v1bb.reshape(nset, -1))) return v1mo.ravel() else: segs = (nvira * nocca, nvira * noccb, nvirb * nocca, nvirb * noccb) sections = numpy.cumsum(segs[:3]) nvars = numpy.sum(segs) nset = h1aa.size // eai_aa.size def _split_mo1(mo1): mo1 = numpy.split(mo1.reshape(nset, nvars), sections, axis=1) mo1aa = mo1[0].reshape(nset, nvira, nocca) mo1ab = mo1[1].reshape(nset, nvira, noccb) mo1ba = mo1[2].reshape(nset, nvirb, nocca) mo1bb = mo1[3].reshape(nset, nvirb, noccb) return mo1aa, mo1ab, mo1ba, mo1bb mo1_fc = numpy.hstack( (mo1_fc[0].reshape(nset, -1), mo1_fc[1].reshape(nset, -1), mo1_fc[2].reshape(nset, -1), mo1_fc[3].reshape(nset, -1))) mo_va_oa = numpy.asarray(numpy.hstack((orbva, orboa)), order='F') mo_va_ob = numpy.asarray(numpy.hstack((orbva, orbob)), order='F') mo_vb_oa = numpy.asarray(numpy.hstack((orbvb, orboa)), order='F') mo_vb_ob = numpy.asarray(numpy.hstack((orbvb, orbob)), order='F') def vind(mo1): mo1aa, mo1ab, mo1ba, mo1bb = _split_mo1(mo1) dm1aa = _dm1_mo2ao(mo1aa, orbva, orboa) dm1ab = _dm1_mo2ao(mo1ab, orbva, orbob) dm1ba = _dm1_mo2ao(mo1ba, orbvb, orboa) dm1bb = _dm1_mo2ao(mo1bb, orbvb, orbob) dm1 = lib.asarray([ dm1aa + dm1aa.transpose(0, 2, 1), dm1ab + dm1ba.transpose(0, 2, 1), dm1ba + dm1ab.transpose(0, 2, 1), dm1bb + dm1bb.transpose(0, 2, 1) ]) v1 = vresp(dm1) v1aa = _ao2mo.nr_e2(v1[0], mo_va_oa, (0, nvira, nvira, nvira + nocca)) v1ab = _ao2mo.nr_e2(v1[1], mo_va_ob, (0, nvira, nvira, nvira + noccb)) v1ba = _ao2mo.nr_e2(v1[2], mo_vb_oa, (0, nvirb, nvirb, nvirb + nocca)) v1bb = _ao2mo.nr_e2(v1[3], mo_vb_ob, (0, nvirb, nvirb, nvirb + noccb)) v1aa = v1aa.reshape(nset, nvira, nocca) v1ab = v1ab.reshape(nset, nvira, noccb) v1ba = v1ba.reshape(nset, nvirb, nocca) v1bb = v1bb.reshape(nset, nvirb, noccb) v1aa *= eai_aa v1ab *= eai_ab v1ba *= eai_ba v1bb *= eai_bb v1mo = numpy.hstack( (v1aa.reshape(nset, -1), v1ab.reshape(nset, -1), v1ba.reshape(nset, -1), v1bb.reshape(nset, -1))) return v1mo.ravel() mo1 = lib.krylov(vind, mo1_fc.ravel(), tol=sscobj.conv_tol, max_cycle=sscobj.max_cycle_cphf, verbose=log) log.timer('solving FC CPHF eqn', *cput1) mo1_fc = _split_mo1(mo1) return mo1_fc
def solve_withs1(fvind, mo_energy, mo_occ, h1, s1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): '''For field dependent basis. First order overlap matrix is non-zero. The first order orbitals are set to C^1_{ij} = -1/2 S1 e1 = h1 - s1*e0 + (e0_j-e0_i)*c1 + vhf[c1] Kwargs: hermi : boolean Whether the matrix defined by fvind is Hermitian or not. Returns: First order orbital coefficients (in MO basis) and first order orbital energy matrix ''' log = logger.new_logger(verbose=verbose) t0 = (logger.process_clock(), logger.perf_counter()) nkpt = len(h1) ncomp = h1[0].shape[0] occidx = [] viridx = [] for k in range(nkpt): occidx.append(mo_occ[k] > 0) viridx.append(mo_occ[k] == 0) e_a = [mo_energy[k][viridx[k]] for k in range(nkpt)] e_i = [mo_energy[k][occidx[k]] for k in range(nkpt)] e_ai = [1 / lib.direct_sum('a-i->ai', e_a[k], e_i[k]) for k in range(nkpt)] nocc = np.zeros([nkpt], dtype=int) nvir = np.zeros([nkpt], dtype=int) nmo = np.zeros([nkpt], dtype=int) moloc = np.zeros([nkpt+1], dtype=int) for k in range(nkpt): nvir_k, nocc_k = e_ai[k].shape nmo_k = nvir_k + nocc_k nvir[k] = nvir_k nocc[k] = nocc_k nmo[k] = nmo_k moloc[k+1] = moloc[k] + nmo_k * nocc_k * ncomp mo1base = [] _mo1base = [] mo_e1 = [] for k in range(nkpt): mo1base.append(h1[k] - s1[k] * e_i[k]) mo_e1.append(mo1base[k][:,occidx[k],:].copy()) mo1base[k][:,viridx[k]] *= -e_ai[k] mo1base[k][:,occidx[k]] = -s1[k][:,occidx[k]] * .5 _mo1base.append(mo1base[k].ravel()) _mo1base = np.hstack(_mo1base) def vind_vo(mo1): mo1 = mo1.ravel() tmp = [] for k in range(nkpt): tmp.append(mo1[moloc[k]:moloc[k+1]].reshape(-1,nmo[k],nocc[k])) v = fvind(tmp) for k in range(nkpt): v[k][:,viridx[k],:] *= e_ai[k] v[k][:,occidx[k],:] = 0 v[k] = v[k].ravel() return np.hstack(v) _mo1 = lib.krylov(vind_vo, _mo1base, tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) mo1 = [] for k in range(nkpt): mo1.append(_mo1[moloc[k]:moloc[k+1]].reshape(-1,nmo[k],nocc[k])) log.timer('krylov solver in CPHF', *t0) v1mo = fvind(mo1) for k in range(nkpt): mo1[k][:,viridx[k]] = mo1base[k][:,viridx[k]] - \ v1mo[k][:,viridx[k]]*e_ai[k] # mo_e1 has the same symmetry as the first order Fock matrix (hermitian or # anti-hermitian). mo_e1 = v1mo + u1*lib.direct_sum('i-j->ij',e_i,e_i) for k in range(nkpt): mo_e1[k] += mo1[k][:,occidx[k]] * lib.direct_sum('i-j->ij', e_i[k], e_i[k]) mo_e1[k] += v1mo[k][:,occidx[k]] return mo1, mo_e1
def solve_withs1(fvind, mo_energy, mo_occ, h1, s1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): '''For field dependent basis. First order overlap matrix is non-zero. The first order orbitals are set to C^1_{ij} = -1/2 S1 e1 = h1 - s1*e0 + (e0_j-e0_i)*c1 + vhf[c1] Kwargs: hermi : boolean Whether the matrix defined by fvind is Hermitian or not. Returns: First order orbital coefficients (in MO basis) and first order orbital energy matrix ''' log = logger.new_logger(verbose=verbose) t0 = (logger.process_clock(), logger.perf_counter()) occidx = mo_occ > 0 viridx = mo_occ == 0 e_a = mo_energy[viridx] e_i = mo_energy[occidx] e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i) nvir, nocc = e_ai.shape nmo = nocc + nvir s1 = s1.reshape(-1, nmo, nocc) hs = mo1base = h1.reshape(-1, nmo, nocc) - s1 * e_i mo_e1 = hs[:, occidx, :].copy() mo1base[:, viridx] *= -e_ai mo1base[:, occidx] = -s1[:, occidx] * .5 def vind_vo(mo1): v = fvind(mo1.reshape(h1.shape)).reshape(-1, nmo, nocc) v[:, viridx, :] *= e_ai v[:, occidx, :] = 0 return v.ravel() mo1 = lib.krylov(vind_vo, mo1base.ravel(), tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) mo1 = mo1.reshape(mo1base.shape) log.timer('krylov solver in CPHF', *t0) v1mo = fvind(mo1.reshape(h1.shape)).reshape(-1, nmo, nocc) mo1[:, viridx] = mo1base[:, viridx] - v1mo[:, viridx] * e_ai # mo_e1 has the same symmetry as the first order Fock matrix (hermitian or # anti-hermitian). mo_e1 = v1mo - s1*lib.direct_sum('i+j->ij',e_i,e_i) mo_e1 += mo1[:, occidx] * lib.direct_sum('i-j->ij', e_i, e_i) mo_e1 += v1mo[:, occidx, :] if h1.ndim == 3: return mo1, mo_e1 else: return mo1.reshape(h1.shape), mo_e1.reshape(nocc, nocc)
def solve_withs1(fvind, mo_energy, mo_occ, h1, s1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): '''For field dependent basis. First order overlap matrix is non-zero. The first order orbitals are set to C^1_{ij} = -1/2 S1 e1 = h1 - s1*e0 + (e0_j-e0_i)*c1 + vhf[c1] ''' log = logger.new_logger(verbose=verbose) t0 = (time.clock(), time.time()) occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 viridxa = ~occidxa viridxb = ~occidxb nocca = numpy.count_nonzero(occidxa) noccb = numpy.count_nonzero(occidxb) nmoa, nmob = mo_occ[0].size, mo_occ[1].size eai_a = mo_energy[0][viridxa, None] - mo_energy[0][occidxa] eai_b = mo_energy[1][viridxb, None] - mo_energy[1][occidxb] s1_a = s1[0].reshape(-1, nmoa, nocca) nset = s1_a.shape[0] s1_b = s1[1].reshape(nset, nmob, noccb) hs_a = mo1base_a = h1[0].reshape(nset, nmoa, nocca) - s1_a * mo_energy[0][occidxa] hs_b = mo1base_b = h1[1].reshape(nset, nmob, noccb) - s1_b * mo_energy[1][occidxb] mo_e1_a = hs_a[:, occidxa].copy() mo_e1_b = hs_b[:, occidxb].copy() mo1base_a[:, viridxa] /= -eai_a mo1base_b[:, viridxb] /= -eai_b mo1base_a[:, occidxa] = -s1_a[:, occidxa] * .5 mo1base_b[:, occidxb] = -s1_b[:, occidxb] * .5 eai_a = 1. / eai_a eai_b = 1. / eai_b mo1base = numpy.hstack( (mo1base_a.reshape(nset, -1), mo1base_b.reshape(nset, -1))) def vind_vo(mo1): v = fvind(mo1).reshape(mo1base.shape) v1a = v[:, :nmoa * nocca].reshape(nset, nmoa, nocca) v1b = v[:, nmoa * nocca:].reshape(nset, nmob, noccb) v1a[:, viridxa] *= eai_a v1b[:, viridxb] *= eai_b v1a[:, occidxa] = 0 v1b[:, occidxb] = 0 return v.ravel() mo1 = lib.krylov(vind_vo, mo1base.ravel(), tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) log.timer('krylov solver in CPHF', *t0) v1mo = fvind(mo1).reshape(mo1base.shape) v1a = v1mo[:, :nmoa * nocca].reshape(nset, nmoa, nocca) v1b = v1mo[:, nmoa * nocca:].reshape(nset, nmob, noccb) mo1 = mo1.reshape(mo1base.shape) mo1_a = mo1[:, :nmoa * nocca].reshape(nset, nmoa, nocca) mo1_b = mo1[:, nmoa * nocca:].reshape(nset, nmob, noccb) mo1_a[:, viridxa] = mo1base_a[:, viridxa] - v1a[:, viridxa] * eai_a mo1_b[:, viridxb] = mo1base_b[:, viridxb] - v1b[:, viridxb] * eai_b mo_e1_a += mo1_a[:, occidxa] * (mo_energy[0][occidxa, None] - mo_energy[0][occidxa]) mo_e1_b += mo1_b[:, occidxb] * (mo_energy[1][occidxb, None] - mo_energy[1][occidxb]) mo_e1_a += v1mo[:, :nmoa * nocca].reshape(nset, nmoa, nocca)[:, occidxa] mo_e1_b += v1mo[:, nmoa * nocca:].reshape(nset, nmob, noccb)[:, occidxb] if isinstance(h1[0], numpy.ndarray) and h1[0].ndim == 2: mo1_a, mo1_b = mo1_a[0], mo1_b[0] mo_e1_a, mo_e1_b = mo_e1_a[0], mo_e1_b[0] return (mo1_a, mo1_b), (mo_e1_a, mo_e1_b)
def solve_mo1(sscobj, h1): cput1 = (time.clock(), time.time()) log = logger.Logger(sscobj.stdout, sscobj.verbose) mol = sscobj.mol mo_energy = sscobj._scf.mo_energy mo_coeff = sscobj._scf.mo_coeff mo_occ = sscobj._scf.mo_occ h1aa, h1ab, h1ba, h1bb = h1 nset = len(h1aa) eai_aa = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0] == 0], mo_energy[0][mo_occ[0] > 0]) eai_ab = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0] == 0], mo_energy[1][mo_occ[1] > 0]) eai_ba = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1] == 0], mo_energy[0][mo_occ[0] > 0]) eai_bb = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1] == 0], mo_energy[1][mo_occ[1] > 0]) mo1 = (numpy.asarray(h1aa) * -eai_aa, numpy.asarray(h1ab) * -eai_ab, numpy.asarray(h1ba) * -eai_ba, numpy.asarray(h1bb) * -eai_bb) h1aa = h1ab = h1ba = h1bb = None if not sscobj.cphf: return mo1 orboa = mo_coeff[0][:, mo_occ[0] > 0] orbva = mo_coeff[0][:, mo_occ[0] == 0] orbob = mo_coeff[1][:, mo_occ[1] > 0] orbvb = mo_coeff[1][:, mo_occ[1] == 0] nocca = orboa.shape[1] nvira = orbva.shape[1] noccb = orbob.shape[1] nvirb = orbvb.shape[1] p1 = nvira * nocca p2 = p1 + nvira * noccb p3 = p2 + nvirb * nocca def _split_mo1(mo1): mo1 = mo1.reshape(nset, -1) mo1aa = mo1[:, :p1].reshape(nset, nvira, nocca) mo1ab = mo1[:, p1:p2].reshape(nset, nvira, noccb) mo1ba = mo1[:, p2:p3].reshape(nset, nvirb, nocca) mo1bb = mo1[:, p3:].reshape(nset, nvirb, noccb) return mo1aa, mo1ab, mo1ba, mo1bb mo1 = numpy.hstack((mo1[0].reshape(nset, -1), mo1[1].reshape(nset, -1), mo1[2].reshape(nset, -1), mo1[3].reshape(nset, -1))) vresp = _gen_uhf_response(mf, with_j=False, hermi=0) mo_va_oa = numpy.asarray(numpy.hstack((orbva, orboa)), order='F') mo_va_ob = numpy.asarray(numpy.hstack((orbva, orbob)), order='F') mo_vb_oa = numpy.asarray(numpy.hstack((orbvb, orboa)), order='F') mo_vb_ob = numpy.asarray(numpy.hstack((orbvb, orbob)), order='F') def vind(mo1): mo1aa, mo1ab, mo1ba, mo1bb = _split_mo1(mo1) dm1aa = _dm1_mo2ao(mo1aa, orbva, orboa) dm1ab = _dm1_mo2ao(mo1ab, orbva, orbob) dm1ba = _dm1_mo2ao(mo1ba, orbvb, orboa) dm1bb = _dm1_mo2ao(mo1bb, orbvb, orbob) # imaginary Hermitian dm1 = numpy.vstack([ dm1aa - dm1aa.transpose(0, 2, 1), dm1ab - dm1ba.transpose(0, 2, 1), dm1ba - dm1ab.transpose(0, 2, 1), dm1bb - dm1bb.transpose(0, 2, 1) ]) v1 = vresp(dm1) v1aa = _ao2mo.nr_e2(v1[:nset], mo_va_oa, (0, nvira, nvira, nvira + nocca)) v1ab = _ao2mo.nr_e2(v1[nset * 1:nset * 2], mo_va_ob, (0, nvira, nvira, nvira + noccb)) v1ba = _ao2mo.nr_e2(v1[nset * 2:nset * 3], mo_vb_oa, (0, nvirb, nvirb, nvirb + nocca)) v1bb = _ao2mo.nr_e2(v1[nset * 3:], mo_vb_ob, (0, nvirb, nvirb, nvirb + noccb)) v1aa = v1aa.reshape(nset, nvira, nocca) v1ab = v1ab.reshape(nset, nvira, noccb) v1ba = v1ba.reshape(nset, nvirb, nocca) v1bb = v1bb.reshape(nset, nvirb, noccb) v1aa *= eai_aa v1ab *= eai_ab v1ba *= eai_ba v1bb *= eai_bb v1mo = numpy.hstack((v1aa.reshape(nset, -1), v1ab.reshape(nset, -1), v1ba.reshape(nset, -1), v1bb.reshape(nset, -1))) return v1mo.ravel() mo1 = lib.krylov(vind, mo1.ravel(), tol=1e-9, max_cycle=20, verbose=log) log.timer('solving FC CPHF eqn', *cput1) mo1 = _split_mo1(mo1) return mo1
def solve_mo1(zfsobj): log = logger.new_logger(zfsobj, zfsobj.verbose) mol = zfsobj.mol mf = zfsobj._scf mo_energy = mf.mo_energy mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ h1 = make_h1_mo(mol, mo_coeff, mo_occ) h1aa, h1bb, h1ab, h1ba = h1 occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 viridxa = ~occidxa viridxb = ~occidxb orboa = mo_coeff[0][:, occidxa] orbob = mo_coeff[1][:, occidxb] orbva = mo_coeff[0][:, ~occidxa] orbvb = mo_coeff[1][:, ~occidxb] eai_aa = -1 / (mo_energy[0][viridxa, None] - mo_energy[0][occidxa]) eai_bb = -1 / (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]) eai_ab = -1 / (mo_energy[0][viridxa, None] - mo_energy[1][occidxb]) eai_ba = -1 / (mo_energy[1][viridxb, None] - mo_energy[0][occidxa]) mo1_aa = h1aa * eai_aa mo1_bb = h1bb * eai_bb mo1_ab = h1ab * eai_ab mo1_ba = h1ba * eai_ba if zfsobj.cphf: nvira, nocca = eai_aa.shape nvirb, noccb = eai_bb.shape p0 = nvira * nocca p1 = p0 + nvirb * noccb p2 = p1 + nvira * noccb p3 = p2 + nvirb * nocca def vind(x): x = x.reshape(3, -1) mo1_aa = x[:, :p0].reshape(3, nvira, nocca) mo1_bb = x[:, p0:p1].reshape(3, nvirb, noccb) mo1_ab = x[:, p1:p2].reshape(3, nvira, noccb) mo1_ba = x[:, p2:].reshape(3, nvirb, nocca) dm1 = numpy.asarray( [reduce(numpy.dot, (orbva, x, orboa.T)) for x in mo1_aa] + [reduce(numpy.dot, (orbvb, x, orbob.T)) for x in mo1_bb] + [reduce(numpy.dot, (orbva, x, orbob.T)) for x in mo1_ab] + [reduce(numpy.dot, (orbvb, x, orboa.T)) for x in mo1_ba]) dm1 = dm1 - dm1.transpose(0, 2, 1) vj, vk = mf.get_jk(mol, dm1, hermi=2) v1ao = -vk mo1_aa = [ reduce(numpy.dot, (orbva.T, v1ao[i], orboa)) for i in range(3) ] mo1_bb = [ reduce(numpy.dot, (orbvb.T, v1ao[i], orbob)) for i in range(3, 6) ] mo1_ab = [ reduce(numpy.dot, (orbva.T, v1ao[i], orbob)) for i in range(6, 9) ] mo1_ba = [ reduce(numpy.dot, (orbvb.T, v1ao[i], orboa)) for i in range(9, 12) ] mo1_aa = (numpy.asarray(mo1_aa) * eai_aa).reshape(3, -1) mo1_bb = (numpy.asarray(mo1_bb) * eai_bb).reshape(3, -1) mo1_ab = (numpy.asarray(mo1_ab) * eai_ab).reshape(3, -1) mo1_ba = (numpy.asarray(mo1_ba) * eai_ba).reshape(3, -1) return numpy.hstack((mo1_aa, mo1_bb, mo1_ab, mo1_ba)).ravel() mo1 = numpy.hstack((mo1_aa.reshape(3, -1), mo1_bb.reshape(3, -1), mo1_ab.reshape(3, -1), mo1_ba.reshape(3, -1))) mo1 = lib.krylov(vind, mo1.ravel(), tol=1e-9, max_cycle=20, verbose=log) mo1 = mo1.reshape(3, -1) mo1_aa = mo1[:, :p0].reshape(3, nvira, nocca) mo1_bb = mo1[:, p0:p1].reshape(3, nvirb, noccb) mo1_ab = mo1[:, p1:p2].reshape(3, nvira, noccb) mo1_ba = mo1[:, p2:].reshape(3, nvirb, nocca) return (mo1_aa, mo1_bb, mo1_ab, mo1_ba)
def kernel(self, max_cycle=30, tol=1e-9, hermi=False): 'CPHF solver for cNEO' e_a = self.base.mf_elec.mo_energy[viridx_e] e_i = self.base.mf_elec.mo_energy[occidx_e] e_ai = -1 / lib.direct_sum('a-i->ai', e_a, e_i) B_e, s1 = self.get_Bmat_elec(self.base.mf_elec) B_e[:, viridx_e] *= e_ai B_e[:, occidx_e] = -s1[:, occidx_e] * .5 mo1base = B_e.ravel() for i in range(len(self.mol.nuc)): mf_n = self.base.mf_nuc[i] occidx_n = mf_n.mo_occ > 0 viridx_n = mf_n.mo_occ == 0 e_a_n = mf_n.mo_energy[viridx_n] e_i_n = mf_n.mo_energy[occidx_n] e_ai_n = -1 / lib.direct_sum('a-i->ai', e_a_n, e_i_n) B_n, s1 = self.get_Bmat_nuc(i) B_n[:, viridx_n] *= e_ai_n B_n[:, occidx_n] = -s1[:, occidx_n] * .5 mo1base = numpy.concatenate((mo1base, B_n.ravel())) for i in range(len(self.mol.nuc)): ia = self.mol.nuc[i].atom_index for j in self.atmlst: if ia == j: irp = -self.mol.nuc[i].intor('int1e_irp', comp=9) r = numpy.identity(3) - 2 * numpy.einsum( 'xij,ji->x', irp, self.base.dm_nuc[i]).reshape(3, 3) mo1base = numpy.concatenate((mo1base, r.ravel())) else: mo1base = numpy.concatenate((mo1base, numpy.zeros(9))) logger.info(self, 'The size of CPHF equations: %s', len(mo1base)) mo1 = lib.krylov(self.full_response, mo1base, tol=tol, max_cycle=max_cycle, hermi=hermi) mo1_e, mo1_n, f1 = self.mo12ne(mo1) logger.debug(self, 'f1:\n%s', f1) v1mo_e = self.get_A_e(mo1_e, mo1_n) B_e, s1 = self.get_Bmat_elec(self.base.mf_elec) e1_e = B_e[:, occidx_e] + mo1_e[:, occidx_e] * lib.direct_sum( 'i-j->ij', e_i, e_i) - v1mo_e[:, occidx_e] logger.debug(self, 'e1e:\n%s', e1_e) e1_n = [] for i in range(len(self.mol.nuc)): mf_n = self.base.mf_nuc[i] occidx = mf_n.mo_occ > 0 viridx = mf_n.mo_occ == 0 e_i = mf_n.mo_energy[occidx] e_a = mf_n.mo_energy[viridx] e_ai = -1 / lib.direct_sum('a-i->ai', e_a, e_i) v1mo_n = self.get_A_n(i, mo1_e, mo1_n, f1) B_n, s1 = self.get_Bmat_nuc(i) e1 = B_n[:, occidx] + mo1_n[i][:, occidx] * lib.direct_sum( 'i-j->ij', e_i, e_i) - v1mo_n[:, occidx] logger.debug(self, 'e1n:\n%s', e1) e1_n.append(e1) return mo1_e, e1_e, mo1_n, e1_n, f1
def solve_withs1(fvind, mo_energy, mo_occ, h1, s1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): '''For field dependent basis. First order overlap matrix is non-zero. The first order orbitals are set to C^1_{ij} = -1/2 S1 e1 = h1 - s1*e0 + (e0_j-e0_i)*c1 + vhf[c1] ''' log = logger.new_logger(verbose=verbose) t0 = (time.clock(), time.time()) occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 viridxa = ~occidxa viridxb = ~occidxb nocca = numpy.count_nonzero(occidxa) noccb = numpy.count_nonzero(occidxb) nmoa, nmob = mo_occ[0].size, mo_occ[1].size nvira = nmoa - nocca nvirb = nmob - noccb eai_a = mo_energy[0][viridxa,None] - mo_energy[0][occidxa] eai_b = mo_energy[1][viridxb,None] - mo_energy[1][occidxb] s1_a = s1[0].reshape(-1,nmoa,nocca) nset = s1_a.shape[0] s1_b = s1[1].reshape(nset,nmob,noccb) hs_a = mo1base_a = h1[0].reshape(nset,nmoa,nocca) - s1_a * mo_energy[0][occidxa] hs_b = mo1base_b = h1[1].reshape(nset,nmob,noccb) - s1_b * mo_energy[1][occidxb] mo_e1_a = hs_a[:,occidxa].copy() mo_e1_b = hs_b[:,occidxb].copy() mo1base_a[:,viridxa]/= -eai_a mo1base_b[:,viridxb]/= -eai_b mo1base_a[:,occidxa] = -s1_a[:,occidxa] * .5 mo1base_b[:,occidxb] = -s1_b[:,occidxb] * .5 eai_a = 1. / eai_a eai_b = 1. / eai_b mo1base = numpy.hstack((mo1base_a.reshape(nset,-1), mo1base_b.reshape(nset,-1))) def vind_vo(mo1): v = fvind(mo1).reshape(mo1base.shape) v1a = v[:,:nmoa*nocca].reshape(nset,nmoa,nocca) v1b = v[:,nmoa*nocca:].reshape(nset,nmob,noccb) v1a[:,viridxa] *= eai_a v1b[:,viridxb] *= eai_b v1a[:,occidxa] = 0 v1b[:,occidxb] = 0 return v.ravel() mo1 = lib.krylov(vind_vo, mo1base.ravel(), tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) log.timer('krylov solver in CPHF', *t0) v1mo = fvind(mo1).reshape(mo1base.shape) v1a = v1mo[:,:nmoa*nocca].reshape(nset,nmoa,nocca) v1b = v1mo[:,nmoa*nocca:].reshape(nset,nmob,noccb) mo1 = mo1.reshape(mo1base.shape) mo1_a = mo1[:,:nmoa*nocca].reshape(nset,nmoa,nocca) mo1_b = mo1[:,nmoa*nocca:].reshape(nset,nmob,noccb) mo1_a[:,viridxa] = mo1base_a[:,viridxa] - v1a[:,viridxa] * eai_a mo1_b[:,viridxb] = mo1base_b[:,viridxb] - v1b[:,viridxb] * eai_b mo_e1_a += mo1_a[:,occidxa] * (mo_energy[0][occidxa,None] - mo_energy[0][occidxa]) mo_e1_b += mo1_b[:,occidxb] * (mo_energy[1][occidxb,None] - mo_energy[1][occidxb]) mo_e1_a += v1mo[:,:nmoa*nocca].reshape(nset,nmoa,nocca)[:,occidxa] mo_e1_b += v1mo[:,nmoa*nocca:].reshape(nset,nmob,noccb)[:,occidxb] if isinstance(h1[0], numpy.ndarray) and h1[0].ndim == 2: mo1_a, mo1_b = mo1_a[0], mo1_b[0] mo_e1_a, mo_e1_b = mo_e1_a[0], mo_e1_b[0] return (mo1_a, mo1_b), (mo_e1_a, mo_e1_b)
def ucphf_with_freq(mf, mo_energy, mo_occ, h1, freq=0, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): log = logger.new_logger(verbose=verbose) t0 = (time.clock(), time.time()) occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 viridxa = ~occidxa viridxb = ~occidxb mo_ea, mo_eb = mo_energy # e_ai - freq may produce very small elements which can cause numerical # issue in krylov solver LEVEL_SHIF = 0.1 e_ai_a = lib.direct_sum('a-i->ai', mo_ea[viridxa], mo_ea[occidxa]).ravel() e_ai_b = lib.direct_sum('a-i->ai', mo_eb[viridxb], mo_eb[occidxb]).ravel() diag = (e_ai_a - freq, e_ai_b - freq, e_ai_a + freq, e_ai_b + freq) diag[0][diag[0] < LEVEL_SHIF] += LEVEL_SHIF diag[1][diag[1] < LEVEL_SHIF] += LEVEL_SHIF diag[2][diag[2] < LEVEL_SHIF] += LEVEL_SHIF diag[3][diag[3] < LEVEL_SHIF] += LEVEL_SHIF mo0a, mo0b = mf.mo_coeff nao, nmoa = mo0a.shape nmob = mo0b.shape orbva = mo0a[:, viridxa] orbvb = mo0b[:, viridxb] orboa = mo0a[:, occidxa] orbob = mo0b[:, occidxb] nvira = orbva.shape[1] nvirb = orbvb.shape[1] nocca = orboa.shape[1] noccb = orbob.shape[1] h1a = h1[0].reshape(-1, nvira * nocca) h1b = h1[1].reshape(-1, nvirb * noccb) ncomp = h1a.shape[0] mo1base = numpy.hstack( (-h1a / diag[0], -h1b / diag[1], -h1a / diag[2], -h1b / diag[3])) offsets = numpy.cumsum((nocca * nvira, noccb * nvirb, nocca * nvira)) vresp = _gen_uhf_response(mf, hermi=0) def vind(xys): nz = len(xys) dm1a = numpy.empty((nz, nao, nao)) dm1b = numpy.empty((nz, nao, nao)) for i in range(nz): xa, xb, ya, yb = numpy.split(xys[i], offsets) dmx = reduce(numpy.dot, (orbva, xa.reshape(nvira, nocca), orboa.T)) dmy = reduce(numpy.dot, (orboa, ya.reshape(nvira, nocca).T, orbva.T)) dm1a[i] = dmx + dmy # AX + BY dmx = reduce(numpy.dot, (orbvb, xb.reshape(nvirb, noccb), orbob.T)) dmy = reduce(numpy.dot, (orbob, yb.reshape(nvirb, noccb).T, orbvb.T)) dm1b[i] = dmx + dmy # AX + BY v1ao = vresp(numpy.stack((dm1a, dm1b))) v1voa = lib.einsum('xpq,pi,qj->xij', v1ao[0], orbva, orboa).reshape(nz, -1) v1vob = lib.einsum('xpq,pi,qj->xij', v1ao[1], orbvb, orbob).reshape(nz, -1) v1ova = lib.einsum('xpq,pi,qj->xji', v1ao[0], orboa, orbva).reshape(nz, -1) v1ovb = lib.einsum('xpq,pi,qj->xji', v1ao[1], orbob, orbvb).reshape(nz, -1) for i in range(nz): xa, xb, ya, yb = numpy.split(xys[i], offsets) v1voa[i] += (e_ai_a - freq - diag[0]) * xa v1voa[i] /= diag[0] v1vob[i] += (e_ai_b - freq - diag[1]) * xb v1vob[i] /= diag[1] v1ova[i] += (e_ai_a + freq - diag[2]) * ya v1ova[i] /= diag[2] v1ovb[i] += (e_ai_b + freq - diag[3]) * yb v1ovb[i] /= diag[3] v = numpy.hstack((v1voa, v1vob, v1ova, v1ovb)) return v # FIXME: krylov solver is not accurate enough for many freqs. Using tight # tol and lindep could offer small help. A better linear equation solver # is needed. mo1 = lib.krylov(vind, mo1base, tol=tol, max_cycle=max_cycle, hermi=hermi, lindep=1e-18, verbose=log) log.timer('krylov solver in CPHF', *t0) dm1a = numpy.empty((ncomp, nao, nao)) dm1b = numpy.empty((ncomp, nao, nao)) for i in range(ncomp): xa, xb, ya, yb = numpy.split(mo1[i], offsets) dmx = reduce(numpy.dot, (orbva, xa.reshape(nvira, nocca) * 2, orboa.T)) dmy = reduce(numpy.dot, (orboa, ya.reshape(nvira, nocca).T * 2, orbva.T)) dm1a[i] = dmx + dmy dmx = reduce(numpy.dot, (orbvb, xb.reshape(nvirb, noccb) * 2, orbob.T)) dmy = reduce(numpy.dot, (orbob, yb.reshape(nvirb, noccb).T * 2, orbvb.T)) dm1b[i] = dmx + dmy v1ao = vresp(numpy.stack((dm1a, dm1b))) mo_e1_a = lib.einsum('xpq,pi,qj->xij', v1ao[0], orboa, orboa) mo_e1_b = lib.einsum('xpq,pi,qj->xij', v1ao[1], orbob, orbob) mo_e1 = (mo_e1_a, mo_e1_b) xa, xb, ya, yb = numpy.split(mo1, offsets, axis=1) mo1 = (xa.reshape(ncomp, nvira, nocca), xb.reshape(ncomp, nvirb, noccb), ya.reshape(ncomp, nvira, nocca), yb.reshape(ncomp, nvirb, noccb)) return mo1, mo_e1
def cphf_with_freq(mf, mo_energy, mo_occ, h1, freq=0, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): log = logger.new_logger(verbose=verbose) t0 = (time.clock(), time.time()) occidx = mo_occ > 0 viridx = mo_occ == 0 e_ai = lib.direct_sum('a-i->ai', mo_energy[viridx], mo_energy[occidx]) # e_ai - freq may produce very small elements which can cause numerical # issue in krylov solver LEVEL_SHIF = 0.1 diag = (e_ai - freq, e_ai + freq) diag[0][diag[0] < LEVEL_SHIF] += LEVEL_SHIF diag[1][diag[1] < LEVEL_SHIF] += LEVEL_SHIF nvir, nocc = e_ai.shape mo_coeff = mf.mo_coeff nao, nmo = mo_coeff.shape orbv = mo_coeff[:,viridx] orbo = mo_coeff[:,occidx] h1 = h1.reshape(-1,nvir,nocc) ncomp = h1.shape[0] mo1base = numpy.stack((-h1/diag[0], -h1/diag[1]), axis=1) mo1base = mo1base.reshape(ncomp,nocc*nvir*2) vresp = _gen_rhf_response(mf, hermi=0) def vind(xys): nz = len(xys) dms = numpy.empty((nz,nao,nao)) for i in range(nz): x, y = xys[i].reshape(2,nvir,nocc) # *2 for double occupancy dmx = reduce(numpy.dot, (orbv, x *2, orbo.T)) dmy = reduce(numpy.dot, (orbo, y.T*2, orbv.T)) dms[i] = dmx + dmy # AX + BY v1ao = vresp(dms) v1vo = lib.einsum('xpq,pi,qj->xij', v1ao, orbv, orbo) # ~c1 v1ov = lib.einsum('xpq,pi,qj->xji', v1ao, orbo, orbv) # ~c1^T for i in range(nz): x, y = xys[i].reshape(2,nvir,nocc) v1vo[i] += (e_ai - freq - diag[0]) * x v1vo[i] /= diag[0] v1ov[i] += (e_ai + freq - diag[1]) * y v1ov[i] /= diag[1] v = numpy.stack((v1vo, v1ov), axis=1) return v.reshape(nz,-1) # FIXME: krylov solver is not accurate enough for many freqs. Using tight # tol and lindep could offer small help. A better linear equation solver # is needed. mo1 = lib.krylov(vind, mo1base, tol=tol, max_cycle=max_cycle, hermi=hermi, lindep=1e-18, verbose=log) mo1 = mo1.reshape(-1,2,nvir,nocc) log.timer('krylov solver in CPHF', *t0) dms = numpy.empty((ncomp,nao,nao)) for i in range(ncomp): x, y = mo1[i] dmx = reduce(numpy.dot, (orbv, x *2, orbo.T)) dmy = reduce(numpy.dot, (orbo, y.T*2, orbv.T)) dms[i] = dmx + dmy mo_e1 = lib.einsum('xpq,pi,qj->xij', vresp(dms), orbo, orbo) mo1 = (mo1[:,0], mo1[:,1]) return mo1, mo_e1
def __FIXME_cphf_with_freq(mf, mo_energy, mo_occ, h1, freq=0, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): log = logger.new_logger(verbose=verbose) t0 = (time.clock(), time.time()) occidx = mo_occ > 0 viridx = mo_occ == 0 e_ai = lib.direct_sum('a-i->ai', mo_energy[viridx], mo_energy[occidx]) # e_ai - freq may produce very small elements which can cause numerical # issue in krylov solver LEVEL_SHIF = 0.1 diag = (e_ai - freq, e_ai + freq) diag[0][diag[0] < LEVEL_SHIF] += LEVEL_SHIF diag[1][diag[1] < LEVEL_SHIF] += LEVEL_SHIF nvir, nocc = e_ai.shape mo_coeff = mf.mo_coeff nao, nmo = mo_coeff.shape orbv = mo_coeff[:,viridx] orbo = mo_coeff[:,occidx] h1 = h1.reshape(-1,nvir,nocc) ncomp = h1.shape[0] mo1base = numpy.stack((-h1/diag[0], -h1/diag[1]), axis=1) mo1base = mo1base.reshape(ncomp,nocc*nvir*2) vresp = mf.gen_response(hermi=0) def vind(xys): nz = len(xys) dms = numpy.empty((nz,nao,nao)) for i in range(nz): x, y = xys[i].reshape(2,nvir,nocc) # *2 for double occupancy dmx = reduce(numpy.dot, (orbv, x *2, orbo.T)) dmy = reduce(numpy.dot, (orbo, y.T*2, orbv.T)) dms[i] = dmx + dmy # AX + BY v1ao = vresp(dms) v1vo = lib.einsum('xpq,pi,qj->xij', v1ao, orbv, orbo) # ~c1 v1ov = lib.einsum('xpq,pi,qj->xji', v1ao, orbo, orbv) # ~c1^T for i in range(nz): x, y = xys[i].reshape(2,nvir,nocc) v1vo[i] += (e_ai - freq - diag[0]) * x v1vo[i] /= diag[0] v1ov[i] += (e_ai + freq - diag[1]) * y v1ov[i] /= diag[1] v = numpy.stack((v1vo, v1ov), axis=1) return v.reshape(nz,-1) # FIXME: krylov solver is not accurate enough for many freqs. Using tight # tol and lindep could offer small help. A better linear equation solver # is needed. mo1 = lib.krylov(vind, mo1base, tol=tol, max_cycle=max_cycle, hermi=hermi, lindep=1e-18, verbose=log) mo1 = mo1.reshape(-1,2,nvir,nocc) log.timer('krylov solver in CPHF', *t0) dms = numpy.empty((ncomp,nao,nao)) for i in range(ncomp): x, y = mo1[i] dmx = reduce(numpy.dot, (orbv, x *2, orbo.T)) dmy = reduce(numpy.dot, (orbo, y.T*2, orbv.T)) dms[i] = dmx + dmy mo_e1 = lib.einsum('xpq,pi,qj->xij', vresp(dms), orbo, orbo) mo1 = (mo1[:,0], mo1[:,1]) return mo1, mo_e1
def ucphf_with_freq(mf, mo_energy, mo_occ, h1, freq=0, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): log = logger.new_logger(verbose=verbose) t0 = (time.clock(), time.time()) occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 viridxa = ~occidxa viridxb = ~occidxb mo_ea, mo_eb = mo_energy # e_ai - freq may produce very small elements which can cause numerical # issue in krylov solver LEVEL_SHIF = 0.1 e_ai_a = lib.direct_sum('a-i->ai', mo_ea[viridxa], mo_ea[occidxa]).ravel() e_ai_b = lib.direct_sum('a-i->ai', mo_eb[viridxb], mo_eb[occidxb]).ravel() diag = (e_ai_a - freq, e_ai_b - freq, e_ai_a + freq, e_ai_b + freq) diag[0][diag[0] < LEVEL_SHIF] += LEVEL_SHIF diag[1][diag[1] < LEVEL_SHIF] += LEVEL_SHIF diag[2][diag[2] < LEVEL_SHIF] += LEVEL_SHIF diag[3][diag[3] < LEVEL_SHIF] += LEVEL_SHIF mo0a, mo0b = mf.mo_coeff nao, nmoa = mo0a.shape nmob = mo0b.shape orbva = mo0a[:,viridxa] orbvb = mo0b[:,viridxb] orboa = mo0a[:,occidxa] orbob = mo0b[:,occidxb] nvira = orbva.shape[1] nvirb = orbvb.shape[1] nocca = orboa.shape[1] noccb = orbob.shape[1] h1a = h1[0].reshape(-1,nvira*nocca) h1b = h1[1].reshape(-1,nvirb*noccb) ncomp = h1a.shape[0] mo1base = numpy.hstack((-h1a/diag[0], -h1b/diag[1], -h1a/diag[2], -h1b/diag[3])) offsets = numpy.cumsum((nocca*nvira, noccb*nvirb, nocca*nvira)) vresp = _gen_uhf_response(mf, hermi=0) def vind(xys): nz = len(xys) dm1a = numpy.empty((nz,nao,nao)) dm1b = numpy.empty((nz,nao,nao)) for i in range(nz): xa, xb, ya, yb = numpy.split(xys[i], offsets) dmx = reduce(numpy.dot, (orbva, xa.reshape(nvira,nocca) , orboa.T)) dmy = reduce(numpy.dot, (orboa, ya.reshape(nvira,nocca).T, orbva.T)) dm1a[i] = dmx + dmy # AX + BY dmx = reduce(numpy.dot, (orbvb, xb.reshape(nvirb,noccb) , orbob.T)) dmy = reduce(numpy.dot, (orbob, yb.reshape(nvirb,noccb).T, orbvb.T)) dm1b[i] = dmx + dmy # AX + BY v1ao = vresp(numpy.stack((dm1a,dm1b))) v1voa = lib.einsum('xpq,pi,qj->xij', v1ao[0], orbva, orboa).reshape(nz,-1) v1vob = lib.einsum('xpq,pi,qj->xij', v1ao[1], orbvb, orbob).reshape(nz,-1) v1ova = lib.einsum('xpq,pi,qj->xji', v1ao[0], orboa, orbva).reshape(nz,-1) v1ovb = lib.einsum('xpq,pi,qj->xji', v1ao[1], orbob, orbvb).reshape(nz,-1) for i in range(nz): xa, xb, ya, yb = numpy.split(xys[i], offsets) v1voa[i] += (e_ai_a - freq - diag[0]) * xa v1voa[i] /= diag[0] v1vob[i] += (e_ai_b - freq - diag[1]) * xb v1vob[i] /= diag[1] v1ova[i] += (e_ai_a + freq - diag[2]) * ya v1ova[i] /= diag[2] v1ovb[i] += (e_ai_b + freq - diag[3]) * yb v1ovb[i] /= diag[3] v = numpy.hstack((v1voa, v1vob, v1ova, v1ovb)) return v # FIXME: krylov solver is not accurate enough for many freqs. Using tight # tol and lindep could offer small help. A better linear equation solver # is needed. mo1 = lib.krylov(vind, mo1base, tol=tol, max_cycle=max_cycle, hermi=hermi, lindep=1e-18, verbose=log) log.timer('krylov solver in CPHF', *t0) dm1a = numpy.empty((ncomp,nao,nao)) dm1b = numpy.empty((ncomp,nao,nao)) for i in range(ncomp): xa, xb, ya, yb = numpy.split(mo1[i], offsets) dmx = reduce(numpy.dot, (orbva, xa.reshape(nvira,nocca) *2, orboa.T)) dmy = reduce(numpy.dot, (orboa, ya.reshape(nvira,nocca).T*2, orbva.T)) dm1a[i] = dmx + dmy dmx = reduce(numpy.dot, (orbvb, xb.reshape(nvirb,noccb) *2, orbob.T)) dmy = reduce(numpy.dot, (orbob, yb.reshape(nvirb,noccb).T*2, orbvb.T)) dm1b[i] = dmx + dmy v1ao = vresp(numpy.stack((dm1a,dm1b))) mo_e1_a = lib.einsum('xpq,pi,qj->xij', v1ao[0], orboa, orboa) mo_e1_b = lib.einsum('xpq,pi,qj->xij', v1ao[1], orbob, orbob) mo_e1 = (mo_e1_a, mo_e1_b) xa, xb, ya, yb = numpy.split(mo1, offsets, axis=1) mo1 = (xa.reshape(ncomp,nvira,nocca), xb.reshape(ncomp,nvirb,noccb), ya.reshape(ncomp,nvira,nocca), yb.reshape(ncomp,nvirb,noccb)) return mo1, mo_e1