def init_guess(self, mf, nstates=None, wfnsym=None): if nstates is None: nstates = self.nstates if wfnsym is None: wfnsym = self.wfnsym mol = mf.mol mo_energy = mf.mo_energy mo_occ = mf.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] 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 if wfnsym is not None and mol.symmetry: if isinstance(wfnsym, str): wfnsym = symm.irrep_name2id(mol.groupname, wfnsym) orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mf.mo_coeff) wfnsym = wfnsym % 10 # convert to D2h subgroup orbsyma = orbsyma % 10 orbsymb = orbsymb % 10 e_ia_a[(orbsyma[occidxa, None] ^ orbsyma[viridxa]) != wfnsym] = 1e99 e_ia_b[(orbsymb[occidxb, None] ^ orbsymb[viridxb]) != wfnsym] = 1e99 e_ia = numpy.hstack((e_ia_a.ravel(), e_ia_b.ravel())) nov = e_ia.size nroot = min(nstates, nov) x0 = numpy.zeros((nroot, nov)) idx = numpy.argsort(e_ia) for i in range(nroot): x0[i, idx[i]] = 1 # lowest excitations return x0
def rotate_mo(self, mo_coeff, u, log=None): mo = numpy.asarray((numpy.dot(mo_coeff[0], u[0]), numpy.dot(mo_coeff[1], u[1]))) if self._scf.mol.symmetry: orbsym = uhf_symm.get_orbsym(self._scf.mol, mo_coeff) mo = lib.tag_array(mo, orbsym=orbsym) return mo
def update_rotate_matrix(self, dx, mo_occ, u0=1, mo_coeff=None): occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 viridxa = ~occidxa viridxb = ~occidxb nmo = len(occidxa) dr = numpy.zeros((2,nmo,nmo), dtype=dx.dtype) uniq = numpy.array((viridxa[:,None] & occidxa, viridxb[:,None] & occidxb)) dr[uniq] = dx dr = dr - dr.conj().transpose(0,2,1) if WITH_EX_EY_DEGENERACY: mol = self._scf.mol if mol.symmetry and mol.groupname in ('Dooh', 'Coov'): orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) _force_Ex_Ey_degeneracy_(dr[0], orbsyma) _force_Ex_Ey_degeneracy_(dr[0], orbsymb) if isinstance(u0, int) and u0 == 1: return numpy.asarray((expmat(dr[0]), expmat(dr[1]))) else: return numpy.asarray((numpy.dot(u0[0], expmat(dr[0])), numpy.dot(u0[1], expmat(dr[1]))))
def update_rotate_matrix(self, dx, mo_occ, u0=1, mo_coeff=None): occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 viridxa = ~occidxa viridxb = ~occidxb nmo = len(occidxa) dr = numpy.zeros((2, nmo, nmo), dtype=dx.dtype) uniq = numpy.array( (viridxa[:, None] & occidxa, viridxb[:, None] & occidxb)) dr[uniq] = dx dr = dr - dr.conj().transpose(0, 2, 1) if WITH_EX_EY_DEGENERACY: mol = self._scf.mol if mol.symmetry and mol.groupname in ('Dooh', 'Coov'): orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) _force_Ex_Ey_degeneracy_(dr[0], orbsyma) _force_Ex_Ey_degeneracy_(dr[1], orbsymb) if isinstance(u0, int) and u0 == 1: return numpy.asarray((expmat(dr[0]), expmat(dr[1]))) else: return numpy.asarray((numpy.dot(u0[0], expmat(dr[0])), numpy.dot(u0[1], expmat(dr[1]))))
def init_guess(self, mf, nstates=None, wfnsym=None): if nstates is None: nstates = self.nstates if wfnsym is None: wfnsym = self.wfnsym mo_energy = mf.mo_energy mo_occ = mf.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] 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] if wfnsym is not None and mol.symmetry: orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) sym_forbida = (orbsyma[viridxa].reshape(-1, 1) ^ orbsyma[occidxa]) != wfnsym sym_forbidb = (orbsymb[viridxb].reshape(-1, 1) ^ orbsymb[occidxb]) != wfnsym e_ai_a[sym_forbida] = 1e99 e_ai_b[sym_forbidb] = 1e99 eai = numpy.hstack((e_ai_a.ravel(), e_ai_b.ravel())) nov = eai.size nroot = min(nstates, nov) x0 = numpy.zeros((nroot, nov)) idx = numpy.argsort(eai) for i in range(nroot): x0[i, idx[i]] = 1 # lowest excitations return x0
def init_guess(self, mf, nstates=None, wfnsym=None): if nstates is None: nstates = self.nstates if wfnsym is None: wfnsym = self.wfnsym mol = mf.mol mo_energy = mf.mo_energy mo_occ = mf.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] 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_max = max(e_ia_a.max(), e_ia_b.max()) if wfnsym is not None and mol.symmetry: if isinstance(wfnsym, str): wfnsym = symm.irrep_name2id(mol.groupname, wfnsym) orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mf.mo_coeff) wfnsym = wfnsym % 10 # convert to D2h subgroup orbsyma_in_d2h = numpy.asarray(orbsyma) % 10 orbsymb_in_d2h = numpy.asarray(orbsymb) % 10 e_ia_a[(orbsyma_in_d2h[occidxa, None] ^ orbsyma_in_d2h[viridxa]) != wfnsym] = 1e99 e_ia_b[(orbsymb_in_d2h[occidxb, None] ^ orbsymb_in_d2h[viridxb]) != wfnsym] = 1e99 e_ia = numpy.hstack((e_ia_a.ravel(), e_ia_b.ravel())) e_ia_max = e_ia.max() nov = e_ia.size nstates = min(nstates, nov) e_threshold = min(e_ia_max, e_ia[numpy.argsort(e_ia)[nstates - 1]]) # Handle degeneracy e_threshold += 1e-6 idx = numpy.where(e_ia <= e_threshold)[0] x0 = numpy.zeros((idx.size, nov)) for i, j in enumerate(idx): x0[i, j] = 1 # Koopmans' excitations return x0
def gen_tda_operation(mf, fock_ao=None, wfnsym=None): '''(A+B)x Kwargs: wfnsym : int or str Point group symmetry irrep symbol or ID for excited CIS wavefunction. ''' mol = mf.mol mo_coeff = mf.mo_coeff assert (mo_coeff[0].dtype == numpy.double) mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff[0].shape 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) orboa = mo_coeff[0][:, occidxa] orbob = mo_coeff[1][:, occidxb] orbva = mo_coeff[0][:, viridxa] orbvb = mo_coeff[1][:, viridxb] if wfnsym is not None and mol.symmetry: if isinstance(wfnsym, str): wfnsym = symm.irrep_name2id(mol.groupname, wfnsym) orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) wfnsym = wfnsym % 10 # convert to D2h subgroup orbsyma = orbsyma % 10 orbsymb = orbsymb % 10 sym_forbida = (orbsyma[occidxa, None] ^ orbsyma[viridxa]) != wfnsym sym_forbidb = (orbsymb[occidxb, None] ^ orbsymb[viridxb]) != wfnsym sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel())) 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 = hdiag = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1))) if wfnsym is not None and mol.symmetry: hdiag[sym_forbid] = 0 mo_a = numpy.asarray(numpy.hstack((orboa, orbva)), order='F') mo_b = numpy.asarray(numpy.hstack((orbob, orbvb)), order='F') mem_now = lib.current_memory()[0] max_memory = max(2000, mf.max_memory * .8 - mem_now) vresp = _gen_uhf_response(mf, hermi=0, max_memory=max_memory) def vind(zs): nz = len(zs) if wfnsym is not None and mol.symmetry: zs = numpy.copy(zs) zs[:, sym_forbid] = 0 dmov = numpy.empty((2, nz, nao, nao)) for i, z in enumerate(zs): za = z[:nocca * nvira].reshape(nocca, nvira) zb = z[nocca * nvira:].reshape(noccb, nvirb) dmov[0, i] = reduce(numpy.dot, (orboa, za, orbva.conj().T)) dmov[1, i] = reduce(numpy.dot, (orbob, zb, orbvb.conj().T)) v1ao = vresp(dmov) v1a = _ao2mo.nr_e2(v1ao[0], mo_a, (0, nocca, nocca, nmo)).reshape(-1, nocca, nvira) v1b = _ao2mo.nr_e2(v1ao[1], mo_b, (0, noccb, noccb, nmo)).reshape(-1, noccb, nvirb) for i, z in enumerate(zs): za = z[:nocca * nvira].reshape(nocca, nvira) zb = z[nocca * nvira:].reshape(noccb, nvirb) v1a[i] += numpy.einsum('ia,ia->ia', e_ia_a, za) v1b[i] += numpy.einsum('ia,ia->ia', e_ia_b, zb) hx = numpy.hstack((v1a.reshape(nz, -1), v1b.reshape(nz, -1))) if wfnsym is not None and mol.symmetry: hx[:, sym_forbid] = 0 return hx return vind, hdiag
def analyze(tdobj, verbose=None): log = logger.new_logger(tdobj, verbose) mol = tdobj.mol mo_coeff = tdobj._scf.mo_coeff mo_occ = tdobj._scf.mo_occ nocc_a = numpy.count_nonzero(mo_occ[0] == 1) nocc_b = numpy.count_nonzero(mo_occ[1] == 1) e_ev = numpy.asarray(tdobj.e) * nist.HARTREE2EV e_wn = numpy.asarray(tdobj.e) * nist.HARTREE2WAVENUMBER wave_length = 1e11 / e_wn log.note('\n** Excitation energies and oscillator strengths **') if mol.symmetry: orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) orbsyma = orbsyma % 10 x_syma = (orbsyma[mo_occ[0] == 1, None] ^ orbsyma[mo_occ[0] == 0]).ravel() else: x_syma = None f_oscillator = tdobj.oscillator_strength() for i, ei in enumerate(tdobj.e): x, y = tdobj.xy[i] if x_syma is None: log.note('Excited State %3d: %12.5f eV %9.2f nm f=%.4f', i + 1, e_ev[i], wave_length[i], f_oscillator[i]) else: wfnsym_id = x_syma[abs(x[0]).argmax()] wfnsym = symm.irrep_id2name(mol.groupname, wfnsym_id) log.note('Excited State %3d: %4s %12.5f eV %9.2f nm f=%.4f', i + 1, wfnsym, e_ev[i], wave_length[i], f_oscillator[i]) if log.verbose >= logger.INFO: for o, v in zip(*numpy.where(abs(x[0]) > 0.1)): log.info(' %4da -> %4da %12.5f', o + MO_BASE, v + MO_BASE + nocc_a, x[0][o, v]) for o, v in zip(*numpy.where(abs(x[1]) > 0.1)): log.info(' %4db -> %4db %12.5f', o + MO_BASE, v + MO_BASE + nocc_b, x[1][o, v]) if log.verbose >= logger.INFO: log.info('\n** Transition electric dipole moments (AU) **') log.info( 'state X Y Z Dip. S. Osc.' ) trans_dip = tdobj.transition_dipole() for i, ei in enumerate(tdobj.e): dip = trans_dip[i] log.info('%3d %11.4f %11.4f %11.4f %11.4f %11.4f', i + 1, dip[0], dip[1], dip[2], numpy.dot(dip, dip), f_oscillator[i]) log.info( '\n** Transition velocity dipole moments (imaginary part AU) **') log.info( 'state X Y Z Dip. S. Osc.' ) trans_v = tdobj.transition_velocity_dipole() f_v = tdobj.oscillator_strength(gauge='velocity', order=0) for i, ei in enumerate(tdobj.e): v = trans_v[i] log.info('%3d %11.4f %11.4f %11.4f %11.4f %11.4f', i + 1, v[0], v[1], v[2], numpy.dot(v, v), f_v[i]) log.info('\n** Transition magnetic dipole moments (AU) **') log.info('state X Y Z') trans_m = tdobj.transition_magnetic_dipole() for i, ei in enumerate(tdobj.e): m = trans_m[i] log.info('%3d %11.4f %11.4f %11.4f', i + 1, m[0], m[1], m[2]) return tdobj
def get_vind(self, mf): wfnsym = self.wfnsym singlet = self.singlet mol = mf.mol mo_coeff = mf.mo_coeff assert (mo_coeff[0].dtype == numpy.double) mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff[0].shape 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) orboa = mo_coeff[0][:, occidxa] orbob = mo_coeff[1][:, occidxb] orbva = mo_coeff[0][:, viridxa] orbvb = mo_coeff[1][:, viridxb] if wfnsym is not None and mol.symmetry: if isinstance(wfnsym, str): wfnsym = symm.irrep_name2id(mol.groupname, wfnsym) orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) wfnsym = wfnsym % 10 # convert to D2h subgroup orbsyma = orbsyma % 10 orbsymb = orbsymb % 10 sym_forbida = (orbsyma[occidxa, None] ^ orbsyma[viridxa]) != wfnsym sym_forbidb = (orbsymb[occidxb, None] ^ orbsymb[viridxb]) != wfnsym sym_forbid = numpy.hstack( (sym_forbida.ravel(), sym_forbidb.ravel())) 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))) if wfnsym is not None and mol.symmetry: e_ia[sym_forbid] = 0 d_ia = numpy.sqrt(e_ia).ravel() ed_ia = e_ia.ravel() * d_ia hdiag = e_ia.ravel()**2 vresp = mf.gen_response(mo_coeff, mo_occ, hermi=1) def vind(zs): nz = len(zs) zs = numpy.asarray(zs).reshape(nz, -1) if wfnsym is not None and mol.symmetry: zs = numpy.copy(zs) zs[:, sym_forbid] = 0 dmsa = (zs[:, :nocca * nvira] * d_ia[:nocca * nvira]).reshape( nz, nocca, nvira) dmsb = (zs[:, nocca * nvira:] * d_ia[nocca * nvira:]).reshape( nz, noccb, nvirb) dmsa = lib.einsum('xov,po,qv->xpq', dmsa, orboa, orbva.conj()) dmsb = lib.einsum('xov,po,qv->xpq', dmsb, orbob, orbvb.conj()) dmsa = dmsa + dmsa.conj().transpose(0, 2, 1) dmsb = dmsb + dmsb.conj().transpose(0, 2, 1) v1ao = vresp(numpy.asarray((dmsa, dmsb))) v1a = lib.einsum('xpq,po,qv->xov', v1ao[0], orboa.conj(), orbva) v1b = lib.einsum('xpq,po,qv->xov', v1ao[1], orbob.conj(), orbvb) hx = numpy.hstack((v1a.reshape(nz, -1), v1b.reshape(nz, -1))) hx += ed_ia * zs hx *= d_ia return hx return vind, hdiag
def get_nto(tdobj, state=1, threshold=OUTPUT_THRESHOLD, verbose=None): r''' Natural transition orbital analysis. The natural transition density matrix between ground state and excited state :math:`Tia = \langle \Psi_{ex} | i a^\dagger | \Psi_0 \rangle` can be transformed to diagonal form through SVD :math:`T = O \sqrt{\lambda} V^\dagger`. O and V are occupied and virtual natural transition orbitals. The diagonal elements :math:`\lambda` are the weights of the occupied-virtual orbital pair in the excitation. Ref: Martin, R. L., JCP, 118, 4775-4777 Note in the TDHF/TDDFT calculations, the excitation part (X) is interpreted as the CIS coefficients and normalized to 1. The de-excitation part (Y) is ignored. Args: state : int Excited state ID. state = 1 means the first excited state. If state < 0, state ID is counted from the last excited state. Kwargs: threshold : float Above which the NTO coefficients will be printed in the output. Returns: A list (weights, NTOs). NTOs are natural orbitals represented in AO basis. The first N_occ NTOs are occupied NTOs and the rest are virtual NTOs. ''' if state == 0: logger.warn( tdobj, 'Excited state starts from 1. ' 'Set state=1 for first excited state.') state_id = state elif state < 0: state_id = state else: state_id = state - 1 mol = tdobj.mol mo_coeff = tdobj._scf.mo_coeff mo_occ = tdobj._scf.mo_occ orbo_a = mo_coeff[0][:, mo_occ[0] == 1] orbv_a = mo_coeff[0][:, mo_occ[0] == 0] orbo_b = mo_coeff[1][:, mo_occ[1] == 1] orbv_b = mo_coeff[1][:, mo_occ[1] == 0] nocc_a = orbo_a.shape[1] nvir_a = orbv_a.shape[1] nocc_b = orbo_b.shape[1] nvir_b = orbv_b.shape[1] cis_t1a, cis_t1b = tdobj.xy[state_id][0] norm = numpy.linalg.norm(cis_t1a)**2 + numpy.linalg.norm(cis_t1b)**2 cis_t1a *= 1. / norm cis_t1b *= 1. / norm if mol.symmetry: orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) o_sym_a = orbsyma[mo_occ[0] == 1] v_sym_a = orbsyma[mo_occ[0] == 0] o_sym_b = orbsymb[mo_occ[1] == 1] v_sym_b = orbsymb[mo_occ[1] == 0] nto_o_a = numpy.eye(nocc_a) nto_v_a = numpy.eye(nvir_a) nto_o_b = numpy.eye(nocc_b) nto_v_b = numpy.eye(nvir_b) weights_o_a = numpy.zeros(nocc_a) weights_v_a = numpy.zeros(nvir_a) weights_o_b = numpy.zeros(nocc_b) weights_v_b = numpy.zeros(nvir_b) for ir in set(orbsyma): idx = numpy.where(o_sym_a == ir)[0] if idx.size > 0: dm_oo = numpy.dot(cis_t1a[idx], cis_t1a[idx].T) weights_o_a[idx], nto_o_a[idx[:, None], idx] = numpy.linalg.eigh(dm_oo) idx = numpy.where(v_sym_a == ir)[0] if idx.size > 0: dm_vv = numpy.dot(cis_t1a[:, idx].T, cis_t1a[:, idx]) weights_v_a[idx], nto_v_a[idx[:, None], idx] = numpy.linalg.eigh(dm_vv) for ir in set(orbsymb): idx = numpy.where(o_sym_b == ir)[0] if idx.size > 0: dm_oo = numpy.dot(cis_t1b[idx], cis_t1b[idx].T) weights_o_b[idx], nto_o_b[idx[:, None], idx] = numpy.linalg.eigh(dm_oo) idx = numpy.where(v_sym_b == ir)[0] if idx.size > 0: dm_vv = numpy.dot(cis_t1b[:, idx].T, cis_t1b[:, idx]) weights_v_b[idx], nto_v_b[idx[:, None], idx] = numpy.linalg.eigh(dm_vv) def sort(weights, nto, sym): # weights in descending order idx = numpy.argsort(-weights) weights = weights[idx] nto = nto[:, idx] sym = sym[idx] return weights, nto, sym weights_o_a, nto_o_a, o_sym_a = sort(weights_o_a, nto_o_a, o_sym_a) weights_v_a, nto_v_a, v_sym_a = sort(weights_v_a, nto_v_a, v_sym_a) weights_o_b, nto_o_b, o_sym_b = sort(weights_o_b, nto_o_b, o_sym_b) weights_v_b, nto_v_b, v_sym_b = sort(weights_v_b, nto_v_b, v_sym_b) nto_orbsyma = numpy.hstack((o_sym_a, v_sym_a)) nto_orbsymb = numpy.hstack((o_sym_b, v_sym_b)) if nocc_a < nvir_a: weights_a = weights_o_a else: weights_a = weights_v_a if nocc_b < nvir_b: weights_b = weights_o_b else: weights_b = weights_v_b else: nto_o_a, w_a, nto_v_aT = numpy.linalg.svd(cis_t1a) nto_o_b, w_b, nto_v_bT = numpy.linalg.svd(cis_t1b) nto_v_a = nto_v_aT.conj().T nto_v_b = nto_v_bT.conj().T weights_a = w_a**2 weights_b = w_b**2 nto_orbsyma = nto_orbsymb = None def _set_phase_(c): idx = numpy.argmax(abs(c.real), axis=0) c[:, c[idx, numpy.arange(c.shape[1])].real < 0] *= -1 _set_phase_(nto_o_a) _set_phase_(nto_o_b) _set_phase_(nto_v_a) _set_phase_(nto_v_b) occupied_nto_a = numpy.dot(orbo_a, nto_o_a) occupied_nto_b = numpy.dot(orbo_b, nto_o_b) virtual_nto_a = numpy.dot(orbv_a, nto_v_a) virtual_nto_b = numpy.dot(orbv_b, nto_v_b) nto_coeff = (numpy.hstack((occupied_nto_a, virtual_nto_a)), numpy.hstack((occupied_nto_b, virtual_nto_b))) if mol.symmetry: nto_coeff = (lib.tag_array(nto_coeff[0], orbsym=nto_orbsyma), lib.tag_array(nto_coeff[1], orbsym=nto_orbsymb)) log = logger.new_logger(tdobj, verbose) if log.verbose >= logger.INFO: log.info('State %d: %g eV NTO largest component %s', state_id + 1, tdobj.e[state_id] * nist.HARTREE2EV, weights_a[0] + weights_b[0]) fmt = '%' + str(lib.param.OUTPUT_DIGITS) + 'f (MO #%d)' o_idx_a = numpy.where(abs(nto_o_a[:, 0]) > threshold)[0] v_idx_a = numpy.where(abs(nto_v_a[:, 0]) > threshold)[0] o_idx_b = numpy.where(abs(nto_o_b[:, 0]) > threshold)[0] v_idx_b = numpy.where(abs(nto_v_b[:, 0]) > threshold)[0] log.info(' alpha occ-NTO: ' + ' + '.join([(fmt % (nto_o_a[i, 0], i + MO_BASE)) for i in o_idx_a])) log.info(' alpha vir-NTO: ' + ' + '.join([(fmt % (nto_v_a[i, 0], i + MO_BASE + nocc_a)) for i in v_idx_a])) log.info(' beta occ-NTO: ' + ' + '.join([(fmt % (nto_o_b[i, 0], i + MO_BASE)) for i in o_idx_b])) log.info(' beta vir-NTO: ' + ' + '.join([(fmt % (nto_v_b[i, 0], i + MO_BASE + nocc_b)) for i in v_idx_b])) return (weights_a, weights_b), nto_coeff
def get_vind(self, mf): wfnsym = self.wfnsym singlet = self.singlet mol = mf.mol mo_coeff = mf.mo_coeff assert(mo_coeff[0].dtype == numpy.double) mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff[0].shape 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) orboa = mo_coeff[0][:,occidxa] orbob = mo_coeff[1][:,occidxb] orbva = mo_coeff[0][:,viridxa] orbvb = mo_coeff[1][:,viridxb] if wfnsym is not None and mol.symmetry: orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) sym_forbida = (orbsyma[viridxa].reshape(-1,1) ^ orbsyma[occidxa]) != wfnsym sym_forbidb = (orbsymb[viridxb].reshape(-1,1) ^ orbsymb[occidxb]) != wfnsym sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel())) 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] e_ai = numpy.hstack((e_ai_a.reshape(-1), e_ai_b.reshape(-1))) if wfnsym is not None and mol.symmetry: e_ai[sym_forbid] = 0 dai = numpy.sqrt(e_ai).ravel() edai = e_ai.ravel() * dai hdiag = e_ai.ravel() ** 2 if mf.grids.coords is None: mf.grids.build() ni = mf._numint hyb = ni.hybrid_coeff(mf.xc, spin=mol.spin) dm0 = None # mf.make_rdm1(mf.mo_coeff, mf.mo_occ) rho0, vxc, fxc = ni.cache_xc_kernel(mf.mol, mf.grids, mf.xc, mo_coeff, mo_occ, spin=1) mem_now = lib.current_memory()[0] max_memory = max(2000, self.max_memory*.8-mem_now) def vind(zs): nz = len(zs) if wfnsym is not None and mol.symmetry: zs = numpy.copy(zs) zs[:,sym_forbid] = 0 dmvo = numpy.empty((2,nz,nao,nao)) for i in range(nz): z = dai * zs[i] za = z[:nocca*nvira].reshape(nvira,nocca) zb = z[nocca*nvira:].reshape(nvirb,noccb) dm = reduce(numpy.dot, (orbva, za, orboa.T)) dmvo[0,i] = dm + dm.T dm = reduce(numpy.dot, (orbvb, zb, orbob.T)) dmvo[1,i] = dm + dm.T v1ao = ni.nr_uks_fxc(mol, mf.grids, mf.xc, dm0, dmvo, 0, 1, rho0, vxc, fxc, max_memory) if self.singlet: vj = mf.get_j(mf.mol, dmvo, hermi=1) v1ao += vj[0] + vj[1] v1a = _ao2mo.nr_e2(v1ao[0], mo_coeff[0], (nocca,nmo,0,nocca)) v1b = _ao2mo.nr_e2(v1ao[1], mo_coeff[1], (noccb,nmo,0,noccb)) hx = numpy.hstack((v1a.reshape(nz,-1), v1b.reshape(nz,-1))) for i, z in enumerate(zs): hx[i] += edai * z hx[i] *= dai return hx return vind, hdiag
def get_vind(self, mf): wfnsym = self.wfnsym singlet = self.singlet mol = mf.mol mo_coeff = mf.mo_coeff assert (mo_coeff[0].dtype == numpy.double) mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff[0].shape 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) orboa = mo_coeff[0][:, occidxa] orbob = mo_coeff[1][:, occidxb] orbva = mo_coeff[0][:, viridxa] orbvb = mo_coeff[1][:, viridxb] if wfnsym is not None and mol.symmetry: if isinstance(wfnsym, str): wfnsym = symm.irrep_name2id(mol.groupname, wfnsym) orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) wfnsym = wfnsym % 10 # convert to D2h subgroup orbsyma = orbsyma % 10 orbsymb = orbsymb % 10 sym_forbida = (orbsyma[occidxa, None] ^ orbsyma[viridxa]) != wfnsym sym_forbidb = (orbsymb[occidxb, None] ^ orbsymb[viridxb]) != wfnsym sym_forbid = numpy.hstack( (sym_forbida.ravel(), sym_forbidb.ravel())) 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))) if wfnsym is not None and mol.symmetry: e_ia[sym_forbid] = 0 d_ia = numpy.sqrt(e_ia).ravel() ed_ia = e_ia.ravel() * d_ia hdiag = e_ia.ravel()**2 vresp = _gen_uhf_response(mf, mo_coeff, mo_occ, hermi=1) def vind(zs): nz = len(zs) if wfnsym is not None and mol.symmetry: zs = numpy.copy(zs) zs[:, sym_forbid] = 0 dmov = numpy.empty((2, nz, nao, nao)) for i in range(nz): z = d_ia * zs[i] za = z[:nocca * nvira].reshape(nocca, nvira) zb = z[nocca * nvira:].reshape(noccb, nvirb) dm = reduce(numpy.dot, (orboa, za, orbva.T)) dmov[0, i] = dm + dm.T dm = reduce(numpy.dot, (orbob, zb, orbvb.T)) dmov[1, i] = dm + dm.T v1ao = vresp(dmov) v1a = _ao2mo.nr_e2(v1ao[0], mo_coeff[0], (0, nocca, nocca, nmo)) v1b = _ao2mo.nr_e2(v1ao[1], mo_coeff[1], (0, noccb, noccb, nmo)) hx = numpy.hstack((v1a.reshape(nz, -1), v1b.reshape(nz, -1))) for i, z in enumerate(zs): hx[i] += ed_ia * z hx[i] *= d_ia return hx return vind, hdiag
def _gen_hop_uhf_external(mf, with_symmetry=True, verbose=None): mol = mf.mol mo_coeff = mf.mo_coeff mo_energy = mf.mo_energy mo_occ = mf.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) orboa = mo_coeff[0][:,occidxa] orbob = mo_coeff[1][:,occidxb] orbva = mo_coeff[0][:,viridxa] orbvb = mo_coeff[1][:,viridxb] if with_symmetry and mol.symmetry: orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) sym_forbida = orbsyma[viridxa].reshape(-1,1) != orbsyma[occidxa] sym_forbidb = orbsymb[viridxb].reshape(-1,1) != orbsymb[occidxb] sym_forbid1 = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel())) h1e = mf.get_hcore() dm0 = mf.make_rdm1(mo_coeff, mo_occ) fock_ao = h1e + mf.get_veff(mol, dm0) focka = reduce(numpy.dot, (mo_coeff[0].conj().T, fock_ao[0], mo_coeff[0])) fockb = reduce(numpy.dot, (mo_coeff[1].conj().T, fock_ao[1], mo_coeff[1])) fooa = focka[occidxa[:,None],occidxa] fvva = focka[viridxa[:,None],viridxa] foob = fockb[occidxb[:,None],occidxb] fvvb = fockb[viridxb[:,None],viridxb] h_diaga =(focka[viridxa,viridxa].reshape(-1,1) - focka[occidxa,occidxa]) h_diagb =(fockb[viridxb,viridxb].reshape(-1,1) - fockb[occidxb,occidxb]) hdiag1 = numpy.hstack((h_diaga.reshape(-1), h_diagb.reshape(-1))) if with_symmetry and mol.symmetry: hdiag1[sym_forbid1] = 0 mem_now = lib.current_memory()[0] max_memory = max(2000, mf.max_memory*.8-mem_now) vrespz = _gen_uhf_response(mf, with_j=False, hermi=2) def hop_real2complex(x1): if with_symmetry and mol.symmetry: x1 = x1.copy() x1[sym_forbid1] = 0 x1a = x1[:nvira*nocca].reshape(nvira,nocca) x1b = x1[nvira*nocca:].reshape(nvirb,noccb) x2a = numpy.einsum('pr,rq->pq', fvva, x1a) x2a-= numpy.einsum('sq,ps->pq', fooa, x1a) x2b = numpy.einsum('pr,rq->pq', fvvb, x1b) x2b-= numpy.einsum('qs,ps->pq', foob, x1b) d1a = reduce(numpy.dot, (orbva, x1a, orboa.conj().T)) d1b = reduce(numpy.dot, (orbvb, x1b, orbob.conj().T)) dm1 = numpy.array((d1a-d1a.conj().T, d1b-d1b.conj().T)) v1 = vrespz(dm1) x2a += reduce(numpy.dot, (orbva.conj().T, v1[0], orboa)) x2b += reduce(numpy.dot, (orbvb.conj().T, v1[1], orbob)) x2 = numpy.hstack((x2a.ravel(), x2b.ravel())) if with_symmetry and mol.symmetry: x2[sym_forbid1] = 0 return x2 if with_symmetry and mol.symmetry: orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) sym_forbidab = orbsyma[viridxa].reshape(-1,1) != orbsymb[occidxb] sym_forbidba = orbsymb[viridxb].reshape(-1,1) != orbsyma[occidxa] sym_forbid2 = numpy.hstack((sym_forbidab.ravel(), sym_forbidba.ravel())) hdiagab = fvva.diagonal().reshape(-1,1) - foob.diagonal() hdiagba = fvvb.diagonal().reshape(-1,1) - fooa.diagonal() hdiag2 = numpy.hstack((hdiagab.ravel(), hdiagba.ravel())) if with_symmetry and mol.symmetry: hdiag2[sym_forbid2] = 0 vresp1 = _gen_uhf_response(mf, with_j=False, hermi=0) # Spin flip GHF solution is not considered def hop_uhf2ghf(x1): if with_symmetry and mol.symmetry: x1 = x1.copy() x1[sym_forbid2] = 0 x1ab = x1[:nvira*noccb].reshape(nvira,noccb) x1ba = x1[nvira*noccb:].reshape(nvirb,nocca) x2ab = numpy.einsum('pr,rq->pq', fvva, x1ab) x2ab-= numpy.einsum('sq,ps->pq', foob, x1ab) x2ba = numpy.einsum('pr,rq->pq', fvvb, x1ba) x2ba-= numpy.einsum('qs,ps->pq', fooa, x1ba) d1ab = reduce(numpy.dot, (orbva, x1ab, orbob.conj().T)) d1ba = reduce(numpy.dot, (orbvb, x1ba, orboa.conj().T)) dm1 = numpy.array((d1ab+d1ba.conj().T, d1ba+d1ab.conj().T)) v1 = vresp1(dm1) x2ab += reduce(numpy.dot, (orbva.conj().T, v1[0], orbob)) x2ba += reduce(numpy.dot, (orbvb.conj().T, v1[1], orboa)) x2 = numpy.hstack((x2ab.real.ravel(), x2ba.real.ravel())) if with_symmetry and mol.symmetry: x2[sym_forbid2] = 0 return x2 return hop_real2complex, hdiag1, hop_uhf2ghf, hdiag2
def _gen_hop_uhf_external(mf, with_symmetry=True, verbose=None): mol = mf.mol mo_coeff = mf.mo_coeff mo_energy = mf.mo_energy mo_occ = mf.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) orboa = mo_coeff[0][:,occidxa] orbob = mo_coeff[1][:,occidxb] orbva = mo_coeff[0][:,viridxa] orbvb = mo_coeff[1][:,viridxb] if with_symmetry and mol.symmetry: orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) sym_forbida = orbsyma[viridxa].reshape(-1,1) != orbsyma[occidxa] sym_forbidb = orbsymb[viridxb].reshape(-1,1) != orbsymb[occidxb] sym_forbid1 = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel())) h1e = mf.get_hcore() dm0 = mf.make_rdm1(mo_coeff, mo_occ) fock_ao = h1e + mf.get_veff(mol, dm0) focka = reduce(numpy.dot, (mo_coeff[0].T, fock_ao[0], mo_coeff[0])) fockb = reduce(numpy.dot, (mo_coeff[1].T, fock_ao[1], mo_coeff[1])) fooa = focka[occidxa[:,None],occidxa] fvva = focka[viridxa[:,None],viridxa] foob = fockb[occidxb[:,None],occidxb] fvvb = fockb[viridxb[:,None],viridxb] h_diaga =(focka[viridxa,viridxa].reshape(-1,1) - focka[occidxa,occidxa]) h_diagb =(fockb[viridxb,viridxb].reshape(-1,1) - fockb[occidxb,occidxb]) hdiag1 = numpy.hstack((h_diaga.reshape(-1), h_diagb.reshape(-1))) if with_symmetry and mol.symmetry: hdiag1[sym_forbid1] = 0 mem_now = lib.current_memory()[0] max_memory = max(2000, mf.max_memory*.8-mem_now) vrespz = _gen_uhf_response(mf, with_j=False, hermi=2) def hop_real2complex(x1): if with_symmetry and mol.symmetry: x1 = x1.copy() x1[sym_forbid1] = 0 x1a = x1[:nvira*nocca].reshape(nvira,nocca) x1b = x1[nvira*nocca:].reshape(nvirb,noccb) x2a = numpy.einsum('pr,rq->pq', fvva, x1a) x2a-= numpy.einsum('sq,ps->pq', fooa, x1a) x2b = numpy.einsum('pr,rq->pq', fvvb, x1b) x2b-= numpy.einsum('qs,ps->pq', foob, x1b) d1a = reduce(numpy.dot, (orbva, x1a, orboa.T.conj())) d1b = reduce(numpy.dot, (orbvb, x1b, orbob.T.conj())) dm1 = numpy.array((d1a-d1a.T.conj(), d1b-d1b.T.conj())) v1 = vrespz(dm1) x2a += reduce(numpy.dot, (orbva.T.conj(), v1[0], orboa)) x2b += reduce(numpy.dot, (orbvb.T.conj(), v1[1], orbob)) x2 = numpy.hstack((x2a.ravel(), x2b.ravel())) if with_symmetry and mol.symmetry: x2[sym_forbid1] = 0 return x2 if with_symmetry and mol.symmetry: orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) sym_forbidab = orbsyma[viridxa].reshape(-1,1) != orbsymb[occidxb] sym_forbidba = orbsymb[viridxb].reshape(-1,1) != orbsyma[occidxa] sym_forbid2 = numpy.hstack((sym_forbidab.ravel(), sym_forbidba.ravel())) hdiagab = fvva.diagonal().reshape(-1,1) - foob.diagonal() hdiagba = fvvb.diagonal().reshape(-1,1) - fooa.diagonal() hdiag2 = numpy.hstack((hdiagab.ravel(), hdiagba.ravel())) if with_symmetry and mol.symmetry: hdiag2[sym_forbid2] = 0 vresp1 = _gen_uhf_response(mf, with_j=False, hermi=0) # Spin flip GHF solution is not considered def hop_uhf2ghf(x1): if with_symmetry and mol.symmetry: x1 = x1.copy() x1[sym_forbid2] = 0 x1ab = x1[:nvira*noccb].reshape(nvira,noccb) x1ba = x1[nvira*noccb:].reshape(nvirb,nocca) x2ab = numpy.einsum('pr,rq->pq', fvva, x1ab) x2ab-= numpy.einsum('sq,ps->pq', foob, x1ab) x2ba = numpy.einsum('pr,rq->pq', fvvb, x1ba) x2ba-= numpy.einsum('qs,ps->pq', fooa, x1ba) d1ab = reduce(numpy.dot, (orbva, x1ab, orbob.T.conj())) d1ba = reduce(numpy.dot, (orbvb, x1ba, orboa.T.conj())) dm1 = numpy.array((d1ab+d1ba.T.conj(), d1ba+d1ab.T.conj())) v1 = vresp1(dm1) x2ab += reduce(numpy.dot, (orbva.T.conj(), v1[0], orbob)) x2ba += reduce(numpy.dot, (orbvb.T.conj(), v1[1], orboa)) x2 = numpy.hstack((x2ab.ravel(), x2ba.ravel())) if with_symmetry and mol.symmetry: x2[sym_forbid2] = 0 return x2 return hop_real2complex, hdiag1, hop_uhf2ghf, hdiag2
def get_vind(self, mf): wfnsym = self.wfnsym singlet = self.singlet mol = mf.mol mo_coeff = mf.mo_coeff assert(mo_coeff[0].dtype == numpy.double) mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff[0].shape 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) orboa = mo_coeff[0][:,occidxa] orbob = mo_coeff[1][:,occidxb] orbva = mo_coeff[0][:,viridxa] orbvb = mo_coeff[1][:,viridxb] if wfnsym is not None and mol.symmetry: if isinstance(wfnsym, str): wfnsym = symm.irrep_name2id(mol.groupname, wfnsym) orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) wfnsym = wfnsym % 10 # convert to D2h subgroup orbsyma = orbsyma % 10 orbsymb = orbsymb % 10 sym_forbida = (orbsyma[occidxa,None] ^ orbsyma[viridxa]) != wfnsym sym_forbidb = (orbsymb[occidxb,None] ^ orbsymb[viridxb]) != wfnsym sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel())) 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))) if wfnsym is not None and mol.symmetry: e_ia[sym_forbid] = 0 d_ia = numpy.sqrt(e_ia).ravel() ed_ia = e_ia.ravel() * d_ia hdiag = e_ia.ravel() ** 2 vresp = _gen_uhf_response(mf, mo_coeff, mo_occ, hermi=1) def vind(zs): nz = len(zs) if wfnsym is not None and mol.symmetry: zs = numpy.copy(zs) zs[:,sym_forbid] = 0 dmov = numpy.empty((2,nz,nao,nao)) for i in range(nz): z = d_ia * zs[i] za = z[:nocca*nvira].reshape(nocca,nvira) zb = z[nocca*nvira:].reshape(noccb,nvirb) dm = reduce(numpy.dot, (orboa, za, orbva.T)) dmov[0,i] = dm + dm.T dm = reduce(numpy.dot, (orbob, zb, orbvb.T)) dmov[1,i] = dm + dm.T v1ao = vresp(dmov) v1a = _ao2mo.nr_e2(v1ao[0], mo_coeff[0], (0,nocca,nocca,nmo)) v1b = _ao2mo.nr_e2(v1ao[1], mo_coeff[1], (0,noccb,noccb,nmo)) hx = numpy.hstack((v1a.reshape(nz,-1), v1b.reshape(nz,-1))) for i, z in enumerate(zs): hx[i] += ed_ia * z hx[i] *= d_ia return hx return vind, hdiag
def gen_g_hop_uhf(mf, mo_coeff, mo_occ, fock_ao=None, h1e=None, with_symmetry=True): mol = mf.mol mo_coeff0 = mo_coeff if getattr(mf, '_scf', None) and mf._scf.mol != mol: #TODO: construct vind with dual-basis treatment, (see also JCP, 118, 9497) mo_coeff = (addons.project_mo_nr2nr(mf._scf.mol, mo_coeff[0], mol), addons.project_mo_nr2nr(mf._scf.mol, mo_coeff[1], mol)) 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) orboa = mo_coeff[0][:,occidxa] orbob = mo_coeff[1][:,occidxb] orbva = mo_coeff[0][:,viridxa] orbvb = mo_coeff[1][:,viridxb] if with_symmetry and mol.symmetry: orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) sym_forbida = orbsyma[viridxa,None] != orbsyma[occidxa] sym_forbidb = orbsymb[viridxb,None] != orbsymb[occidxb] sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel())) if fock_ao is None: dm0 = mf.make_rdm1(mo_coeff, mo_occ) fock_ao = mf.get_fock(h1e, dm=dm0) focka = reduce(numpy.dot, (mo_coeff[0].conj().T, fock_ao[0], mo_coeff[0])) fockb = reduce(numpy.dot, (mo_coeff[1].conj().T, fock_ao[1], mo_coeff[1])) else: focka = reduce(numpy.dot, (mo_coeff0[0].conj().T, fock_ao[0], mo_coeff0[0])) fockb = reduce(numpy.dot, (mo_coeff0[1].conj().T, fock_ao[1], mo_coeff0[1])) fooa = focka[occidxa[:,None],occidxa] fvva = focka[viridxa[:,None],viridxa] foob = fockb[occidxb[:,None],occidxb] fvvb = fockb[viridxb[:,None],viridxb] g = numpy.hstack((focka[viridxa[:,None],occidxa].ravel(), fockb[viridxb[:,None],occidxb].ravel())) h_diaga = fvva.diagonal().real[:,None] - fooa.diagonal().real h_diagb = fvvb.diagonal().real[:,None] - foob.diagonal().real h_diag = numpy.hstack((h_diaga.reshape(-1), h_diagb.reshape(-1))) if with_symmetry and mol.symmetry: g[sym_forbid] = 0 h_diag[sym_forbid] = 0 vind = _gen_uhf_response(mf, mo_coeff, mo_occ, hermi=1) def h_op(x): if with_symmetry and mol.symmetry: x = x.copy() x[sym_forbid] = 0 x1a = x[:nvira*nocca].reshape(nvira,nocca) x1b = x[nvira*nocca:].reshape(nvirb,noccb) x2a = numpy.einsum('pr,rq->pq', fvva, x1a) x2a-= numpy.einsum('sq,ps->pq', fooa, x1a) x2b = numpy.einsum('pr,rq->pq', fvvb, x1b) x2b-= numpy.einsum('sq,ps->pq', foob, x1b) d1a = reduce(numpy.dot, (orbva, x1a, orboa.conj().T)) d1b = reduce(numpy.dot, (orbvb, x1b, orbob.conj().T)) dm1 = numpy.array((d1a+d1a.conj().T,d1b+d1b.conj().T)) v1 = vind(dm1) x2a += reduce(numpy.dot, (orbva.conj().T, v1[0], orboa)) x2b += reduce(numpy.dot, (orbvb.conj().T, v1[1], orbob)) x2 = numpy.hstack((x2a.ravel(), x2b.ravel())) if with_symmetry and mol.symmetry: x2[sym_forbid] = 0 return x2 return g, h_op, h_diag
def gen_g_hop_uhf(mf, mo_coeff, mo_occ, fock_ao=None, h1e=None, with_symmetry=True): mol = mf.mol if hasattr(mf, '_scf') and id(mf._scf.mol) != id(mol): mo_coeff = (addons.project_mo_nr2nr(mf._scf.mol, mo_coeff[0], mol), addons.project_mo_nr2nr(mf._scf.mol, mo_coeff[1], mol)) 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) orboa = mo_coeff[0][:, occidxa] orbob = mo_coeff[1][:, occidxb] orbva = mo_coeff[0][:, viridxa] orbvb = mo_coeff[1][:, viridxb] if with_symmetry and mol.symmetry: orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) sym_forbida = orbsyma[viridxa].reshape(-1, 1) != orbsyma[occidxa] sym_forbidb = orbsymb[viridxb].reshape(-1, 1) != orbsymb[occidxb] sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel())) if fock_ao is None: if h1e is None: h1e = mf.get_hcore() dm0 = mf.make_rdm1(mo_coeff, mo_occ) fock_ao = h1e + mf.get_veff(mol, dm0) focka = reduce(numpy.dot, (mo_coeff[0].T, fock_ao[0], mo_coeff[0])) fockb = reduce(numpy.dot, (mo_coeff[1].T, fock_ao[1], mo_coeff[1])) fooa = focka[occidxa[:, None], occidxa] fvva = focka[viridxa[:, None], viridxa] foob = fockb[occidxb[:, None], occidxb] fvvb = fockb[viridxb[:, None], viridxb] g = numpy.hstack((focka[occidxa[:, None], viridxa].T.ravel(), fockb[occidxb[:, None], viridxb].T.ravel())) h_diaga = focka[viridxa, viridxa].reshape(-1, 1) - focka[occidxa, occidxa] h_diagb = fockb[viridxb, viridxb].reshape(-1, 1) - fockb[occidxb, occidxb] h_diag = numpy.hstack((h_diaga.reshape(-1), h_diagb.reshape(-1))) if with_symmetry and mol.symmetry: g[sym_forbid] = 0 h_diag[sym_forbid] = 0 vind = _gen_uhf_response(mf, mo_coeff, mo_occ, hermi=1) def h_op(x): if with_symmetry and mol.symmetry: x = x.copy() x[sym_forbid] = 0 x1a = x[:nvira * nocca].reshape(nvira, nocca) x1b = x[nvira * nocca:].reshape(nvirb, noccb) x2a = numpy.einsum('pr,rq->pq', fvva, x1a) x2a -= numpy.einsum('sq,ps->pq', fooa, x1a) x2b = numpy.einsum('pr,rq->pq', fvvb, x1b) x2b -= numpy.einsum('sq,ps->pq', foob, x1b) d1a = reduce(numpy.dot, (orbva, x1a, orboa.T.conj())) d1b = reduce(numpy.dot, (orbvb, x1b, orbob.T.conj())) dm1 = numpy.array((d1a + d1a.T.conj(), d1b + d1b.T.conj())) v1 = vind(dm1) x2a += reduce(numpy.dot, (orbva.T.conj(), v1[0], orboa)) x2b += reduce(numpy.dot, (orbvb.T.conj(), v1[1], orbob)) x2 = numpy.hstack((x2a.ravel(), x2b.ravel())) if with_symmetry and mol.symmetry: x2[sym_forbid] = 0 return x2 return g, h_op, h_diag
def get_vind(self, mf): ''' [ A B][X] [-B -A][Y] ''' wfnsym = self.wfnsym singlet = self.singlet mol = mf.mol mo_coeff = mf.mo_coeff assert (mo_coeff[0].dtype == numpy.double) mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff[0].shape 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) orboa = mo_coeff[0][:, occidxa] orbob = mo_coeff[1][:, occidxb] orbva = mo_coeff[0][:, viridxa] orbvb = mo_coeff[1][:, viridxb] if wfnsym is not None and mol.symmetry: orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) sym_forbida = (orbsyma[viridxa].reshape(-1, 1) ^ orbsyma[occidxa]) != wfnsym sym_forbidb = (orbsymb[viridxb].reshape(-1, 1) ^ orbsymb[occidxb]) != wfnsym sym_forbid = numpy.hstack( (sym_forbida.ravel(), sym_forbidb.ravel())) 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] e_ai = hdiag = numpy.hstack((e_ai_a.reshape(-1), e_ai_b.reshape(-1))) if wfnsym is not None and mol.symmetry: hdiag[sym_forbid] = 0 hdiag = numpy.hstack((hdiag.ravel(), hdiag.ravel())) mo_a = numpy.asarray(numpy.hstack((orboa, orbva)), order='F') mo_b = numpy.asarray(numpy.hstack((orbob, orbvb)), order='F') mem_now = lib.current_memory()[0] max_memory = max(2000, self.max_memory * .8 - mem_now) vresp = _gen_uhf_response(mf, hermi=0, max_memory=max_memory) def vind(xys): nz = len(xys) if wfnsym is not None and mol.symmetry: # shape(nz,2,-1): 2 ~ X,Y xys = numpy.copy(zs).reshape(nz, 2, -1) xys[:, :, :, sym_forbid] = 0 dms = numpy.empty((2, nz, nao, nao)) # 2 ~ alpha,beta for i in range(nz): x, y = xys[i].reshape(2, -1) xa = x[:nocca * nvira].reshape(nvira, nocca) xb = x[nocca * nvira:].reshape(nvirb, noccb) ya = y[:nocca * nvira].reshape(nvira, nocca) yb = y[nocca * nvira:].reshape(nvirb, noccb) dmx = reduce(numpy.dot, (orbva, xa, orboa.T)) dmy = reduce(numpy.dot, (orboa, ya.T, orbva.T)) dms[0, i] = dmx + dmy # AX + BY dmx = reduce(numpy.dot, (orbvb, xb, orbob.T)) dmy = reduce(numpy.dot, (orbob, yb.T, orbvb.T)) dms[1, i] = dmx + dmy # AX + BY v1ao = vresp(dms) v1avo = _ao2mo.nr_e2(v1ao[0], mo_a, (nocca, nmo, 0, nocca)) v1bvo = _ao2mo.nr_e2(v1ao[1], mo_b, (noccb, nmo, 0, noccb)) v1aov = _ao2mo.nr_e2(v1ao[0], mo_a, (0, nocca, nocca, nmo)) v1bov = _ao2mo.nr_e2(v1ao[1], mo_b, (0, noccb, noccb, nmo)) hx = numpy.empty((nz, 2, nvira * nocca + nvirb * noccb), dtype=v1avo.dtype) for i in range(nz): x, y = xys[i].reshape(2, -1) hx[i, 0, :nvira * nocca] = v1avo[i].ravel() hx[i, 0, nvira * nocca:] = v1bvo[i].ravel() hx[i, 0] += e_ai * x # AX hx[i, 1, :nvira * nocca] = -v1aov[i].reshape(nocca, nvira).T.ravel() hx[i, 1, nvira * nocca:] = -v1bov[i].reshape(noccb, nvirb).T.ravel() hx[i, 1] -= e_ai * y #-AY if wfnsym is not None and mol.symmetry: hx[:, :, sym_forbid] = 0 return hx.reshape(nz, -1) return vind, hdiag
def gen_tda_hop(mf, fock_ao=None, wfnsym=None, max_memory=2000): '''(A+B)x Kwargs: wfnsym : int Point group symmetry for excited CIS wavefunction. ''' mol = mf.mol mo_coeff = mf.mo_coeff assert (mo_coeff[0].dtype == numpy.double) mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff[0].shape 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) orboa = mo_coeff[0][:, occidxa] orbob = mo_coeff[1][:, occidxb] orbva = mo_coeff[0][:, viridxa] orbvb = mo_coeff[1][:, viridxb] if wfnsym is not None and mol.symmetry: orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) sym_forbida = (orbsyma[viridxa].reshape(-1, 1) ^ orbsyma[occidxa]) != wfnsym sym_forbidb = (orbsymb[viridxb].reshape(-1, 1) ^ orbsymb[occidxb]) != wfnsym sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel())) 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] e_ai = hdiag = numpy.hstack((e_ai_a.reshape(-1), e_ai_b.reshape(-1))) if wfnsym is not None and mol.symmetry: hdiag[sym_forbid] = 0 mo_a = numpy.asarray(numpy.hstack((orboa, orbva)), order='F') mo_b = numpy.asarray(numpy.hstack((orbob, orbvb)), order='F') mem_now = lib.current_memory()[0] max_memory = max(2000, max_memory * .8 - mem_now) vresp = _gen_uhf_response(mf, hermi=0, max_memory=max_memory) def vind(zs): nz = len(zs) if wfnsym is not None and mol.symmetry: zs = numpy.copy(zs) zs[:, sym_forbid] = 0 dmvo = numpy.empty((2, nz, nao, nao)) for i, z in enumerate(zs): za = z[:nocca * nvira].reshape(nvira, nocca) zb = z[nocca * nvira:].reshape(nvirb, noccb) dmvo[0, i] = reduce(numpy.dot, (orbva, za, orboa.T)) dmvo[1, i] = reduce(numpy.dot, (orbvb, zb, orbob.T)) v1ao = vresp(dmvo) v1a = _ao2mo.nr_e2(v1ao[0], mo_a, (nocca, nmo, 0, nocca)).reshape(-1, nvira, nocca) v1b = _ao2mo.nr_e2(v1ao[1], mo_b, (noccb, nmo, 0, noccb)).reshape(-1, nvirb, noccb) for i, z in enumerate(zs): za = z[:nocca * nvira].reshape(nvira, nocca) zb = z[nocca * nvira:].reshape(nvirb, noccb) v1a[i] += numpy.einsum('ai,ai->ai', e_ai_a, za) v1b[i] += numpy.einsum('ai,ai->ai', e_ai_b, zb) hx = numpy.hstack((v1a.reshape(nz, -1), v1b.reshape(nz, -1))) if wfnsym is not None and mol.symmetry: hx[:, sym_forbid] = 0 return hx return vind, hdiag
def gen_tdhf_operation(mf, fock_ao=None, singlet=True, wfnsym=None): '''Generate function to compute [ A B][X] [-B -A][Y] ''' mol = mf.mol mo_coeff = mf.mo_coeff assert (mo_coeff[0].dtype == numpy.double) mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff[0].shape 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) orboa = mo_coeff[0][:, occidxa] orbob = mo_coeff[1][:, occidxb] orbva = mo_coeff[0][:, viridxa] orbvb = mo_coeff[1][:, viridxb] if wfnsym is not None and mol.symmetry: if isinstance(wfnsym, str): wfnsym = symm.irrep_name2id(mol.groupname, wfnsym) orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) wfnsym = wfnsym % 10 # convert to D2h subgroup orbsyma = orbsyma % 10 orbsymb = orbsymb % 10 sym_forbida = (orbsyma[occidxa, None] ^ orbsyma[viridxa]) != wfnsym sym_forbidb = (orbsymb[occidxb, None] ^ orbsymb[viridxb]) != wfnsym sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel())) 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 = hdiag = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1))) if wfnsym is not None and mol.symmetry: hdiag[sym_forbid] = 0 hdiag = numpy.hstack((hdiag.ravel(), hdiag.ravel())) mo_a = numpy.asarray(numpy.hstack((orboa, orbva)), order='F') mo_b = numpy.asarray(numpy.hstack((orbob, orbvb)), order='F') mem_now = lib.current_memory()[0] max_memory = max(2000, mf.max_memory * .8 - mem_now) vresp = _gen_uhf_response(mf, hermi=0, max_memory=max_memory) def vind(xys): nz = len(xys) if wfnsym is not None and mol.symmetry: # shape(nz,2,-1): 2 ~ X,Y xys = numpy.copy(xys).reshape(nz, 2, -1) xys[:, :, sym_forbid] = 0 dms = numpy.empty((2, nz, nao, nao)) # 2 ~ alpha,beta for i in range(nz): x, y = xys[i].reshape(2, -1) xa = x[:nocca * nvira].reshape(nocca, nvira) xb = x[nocca * nvira:].reshape(noccb, nvirb) ya = y[:nocca * nvira].reshape(nocca, nvira) yb = y[nocca * nvira:].reshape(noccb, nvirb) dmx = reduce(numpy.dot, (orboa, xa, orbva.T)) dmy = reduce(numpy.dot, (orbva, ya.T, orboa.T)) dms[0, i] = dmx + dmy # AX + BY dmx = reduce(numpy.dot, (orbob, xb, orbvb.T)) dmy = reduce(numpy.dot, (orbvb, yb.T, orbob.T)) dms[1, i] = dmx + dmy # AX + BY v1ao = vresp(dms) v1avo = _ao2mo.nr_e2(v1ao[0], mo_a, (nocca, nmo, 0, nocca)) v1bvo = _ao2mo.nr_e2(v1ao[1], mo_b, (noccb, nmo, 0, noccb)) v1aov = _ao2mo.nr_e2(v1ao[0], mo_a, (0, nocca, nocca, nmo)) v1bov = _ao2mo.nr_e2(v1ao[1], mo_b, (0, noccb, noccb, nmo)) hx = numpy.empty((nz, 2, nvira * nocca + nvirb * noccb), dtype=v1avo.dtype) for i in range(nz): x, y = xys[i].reshape(2, -1) hx[i, 0, :nvira * nocca] = v1aov[i].ravel() hx[i, 0, nvira * nocca:] = v1bov[i].ravel() hx[i, 0] += e_ia * x # AX hx[i, 1, :nvira * nocca] = -v1avo[i].reshape(nvira, nocca).T.ravel() hx[i, 1, nvira * nocca:] = -v1bvo[i].reshape(nvirb, noccb).T.ravel() hx[i, 1] -= e_ia * y #-AY if wfnsym is not None and mol.symmetry: hx[:, :, sym_forbid] = 0 return hx.reshape(nz, -1) return vind, hdiag
def gen_tda_operation(mf, fock_ao=None, wfnsym=None): '''(A+B)x Kwargs: wfnsym : int or str Point group symmetry irrep symbol or ID for excited CIS wavefunction. ''' mol = mf.mol mo_coeff = mf.mo_coeff assert (mo_coeff[0].dtype == numpy.double) mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff[0].shape 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) orboa = mo_coeff[0][:, occidxa] orbob = mo_coeff[1][:, occidxb] orbva = mo_coeff[0][:, viridxa] orbvb = mo_coeff[1][:, viridxb] if wfnsym is not None and mol.symmetry: if isinstance(wfnsym, str): wfnsym = symm.irrep_name2id(mol.groupname, wfnsym) orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) wfnsym = wfnsym % 10 # convert to D2h subgroup orbsyma_in_d2h = numpy.asarray(orbsyma) % 10 orbsymb_in_d2h = numpy.asarray(orbsymb) % 10 sym_forbida = (orbsyma_in_d2h[occidxa, None] ^ orbsyma_in_d2h[viridxa]) != wfnsym sym_forbidb = (orbsymb_in_d2h[occidxb, None] ^ orbsymb_in_d2h[viridxb]) != wfnsym sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel())) e_ia_a = mo_energy[0][viridxa] - mo_energy[0][occidxa, None] e_ia_b = mo_energy[1][viridxb] - mo_energy[1][occidxb, None] e_ia = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1))) hdiag = e_ia if wfnsym is not None and mol.symmetry: hdiag[sym_forbid] = 0 mem_now = lib.current_memory()[0] max_memory = max(2000, mf.max_memory * .8 - mem_now) vresp = mf.gen_response(hermi=0, max_memory=max_memory) def vind(zs): zs = numpy.asarray(zs) if wfnsym is not None and mol.symmetry: zs = numpy.copy(zs) zs[:, sym_forbid] = 0 za = zs[:, :nocca * nvira].reshape(-1, nocca, nvira) zb = zs[:, nocca * nvira:].reshape(-1, noccb, nvirb) dmova = lib.einsum('xov,po,qv->xpq', za, orboa, orbva.conj()) dmovb = lib.einsum('xov,po,qv->xpq', zb, orbob, orbvb.conj()) v1ao = vresp(numpy.asarray((dmova, dmovb))) v1a = lib.einsum('xpq,po,qv->xov', v1ao[0], orboa.conj(), orbva) v1b = lib.einsum('xpq,po,qv->xov', v1ao[1], orbob.conj(), orbvb) v1a += numpy.einsum('xia,ia->xia', za, e_ia_a) v1b += numpy.einsum('xia,ia->xia', zb, e_ia_b) nz = zs.shape[0] hx = numpy.hstack((v1a.reshape(nz, -1), v1b.reshape(nz, -1))) if wfnsym is not None and mol.symmetry: hx[:, sym_forbid] = 0 return hx return vind, hdiag
def gen_g_hop_uhf(mf, mo_coeff, mo_occ, fock_ao=None, h1e=None, with_symmetry=True): mol = mf.mol mo_coeff0 = mo_coeff if getattr(mf, '_scf', None) and mf._scf.mol != mol: #TODO: construct vind with dual-basis treatment, (see also JCP, 118, 9497) mo_coeff = (addons.project_mo_nr2nr(mf._scf.mol, mo_coeff[0], mol), addons.project_mo_nr2nr(mf._scf.mol, mo_coeff[1], mol)) 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) orboa = mo_coeff[0][:, occidxa] orbob = mo_coeff[1][:, occidxb] orbva = mo_coeff[0][:, viridxa] orbvb = mo_coeff[1][:, viridxb] if with_symmetry and mol.symmetry: orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) sym_forbida = orbsyma[viridxa, None] != orbsyma[occidxa] sym_forbidb = orbsymb[viridxb, None] != orbsymb[occidxb] sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel())) if fock_ao is None: if getattr(mf, '_scf', None) and mf._scf.mol != mol: h1e = mf.get_hcore(mol) dm0 = mf.make_rdm1(mo_coeff, mo_occ) fock_ao = mf.get_fock(h1e, dm=dm0) focka = reduce(numpy.dot, (mo_coeff[0].conj().T, fock_ao[0], mo_coeff[0])) fockb = reduce(numpy.dot, (mo_coeff[1].conj().T, fock_ao[1], mo_coeff[1])) else: focka = reduce(numpy.dot, (mo_coeff0[0].conj().T, fock_ao[0], mo_coeff0[0])) fockb = reduce(numpy.dot, (mo_coeff0[1].conj().T, fock_ao[1], mo_coeff0[1])) fooa = focka[occidxa[:, None], occidxa] fvva = focka[viridxa[:, None], viridxa] foob = fockb[occidxb[:, None], occidxb] fvvb = fockb[viridxb[:, None], viridxb] g = numpy.hstack((focka[viridxa[:, None], occidxa].ravel(), fockb[viridxb[:, None], occidxb].ravel())) h_diaga = fvva.diagonal().real[:, None] - fooa.diagonal().real h_diagb = fvvb.diagonal().real[:, None] - foob.diagonal().real h_diag = numpy.hstack((h_diaga.reshape(-1), h_diagb.reshape(-1))) if with_symmetry and mol.symmetry: g[sym_forbid] = 0 h_diag[sym_forbid] = 0 vind = _gen_uhf_response(mf, mo_coeff, mo_occ, hermi=1) def h_op(x): if with_symmetry and mol.symmetry: x = x.copy() x[sym_forbid] = 0 x1a = x[:nvira * nocca].reshape(nvira, nocca) x1b = x[nvira * nocca:].reshape(nvirb, noccb) x2a = numpy.einsum('pr,rq->pq', fvva, x1a) x2a -= numpy.einsum('sq,ps->pq', fooa, x1a) x2b = numpy.einsum('pr,rq->pq', fvvb, x1b) x2b -= numpy.einsum('sq,ps->pq', foob, x1b) d1a = reduce(numpy.dot, (orbva, x1a, orboa.conj().T)) d1b = reduce(numpy.dot, (orbvb, x1b, orbob.conj().T)) dm1 = numpy.array((d1a + d1a.conj().T, d1b + d1b.conj().T)) v1 = vind(dm1) x2a += reduce(numpy.dot, (orbva.conj().T, v1[0], orboa)) x2b += reduce(numpy.dot, (orbvb.conj().T, v1[1], orbob)) x2 = numpy.hstack((x2a.ravel(), x2b.ravel())) if with_symmetry and mol.symmetry: x2[sym_forbid] = 0 return x2 return g, h_op, h_diag
def gen_tdhf_operation(mf, fock_ao=None, singlet=True, wfnsym=None): '''Generate function to compute [ A B][X] [-B -A][Y] ''' mol = mf.mol mo_coeff = mf.mo_coeff assert (mo_coeff[0].dtype == numpy.double) mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff[0].shape 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) orboa = mo_coeff[0][:, occidxa] orbob = mo_coeff[1][:, occidxb] orbva = mo_coeff[0][:, viridxa] orbvb = mo_coeff[1][:, viridxb] if wfnsym is not None and mol.symmetry: if isinstance(wfnsym, str): wfnsym = symm.irrep_name2id(mol.groupname, wfnsym) orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff) wfnsym = wfnsym % 10 # convert to D2h subgroup orbsyma_in_d2h = numpy.asarray(orbsyma) % 10 orbsymb_in_d2h = numpy.asarray(orbsymb) % 10 sym_forbida = (orbsyma_in_d2h[occidxa, None] ^ orbsyma_in_d2h[viridxa]) != wfnsym sym_forbidb = (orbsymb_in_d2h[occidxb, None] ^ orbsymb_in_d2h[viridxb]) != wfnsym sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel())) e_ia_a = mo_energy[0][viridxa] - mo_energy[0][occidxa, None] e_ia_b = mo_energy[1][viridxb] - mo_energy[1][occidxb, None] e_ia = hdiag = numpy.hstack((e_ia_a.ravel(), e_ia_b.ravel())) if wfnsym is not None and mol.symmetry: hdiag[sym_forbid] = 0 hdiag = numpy.hstack((hdiag, -hdiag)) mem_now = lib.current_memory()[0] max_memory = max(2000, mf.max_memory * .8 - mem_now) vresp = mf.gen_response(hermi=0, max_memory=max_memory) def vind(xys): nz = len(xys) xys = numpy.asarray(xys).reshape(nz, 2, -1) if wfnsym is not None and mol.symmetry: # shape(nz,2,-1): 2 ~ X,Y xys = numpy.copy(xys) xys[:, :, sym_forbid] = 0 xs, ys = xys.transpose(1, 0, 2) xa = xs[:, :nocca * nvira].reshape(nz, nocca, nvira) xb = xs[:, nocca * nvira:].reshape(nz, noccb, nvirb) ya = ys[:, :nocca * nvira].reshape(nz, nocca, nvira) yb = ys[:, nocca * nvira:].reshape(nz, noccb, nvirb) # dms = AX + BY dmsa = lib.einsum('xov,po,qv->xpq', xa, orboa, orbva.conj()) dmsa += lib.einsum('xov,pv,qo->xpq', ya, orbva, orboa.conj()) dmsb = lib.einsum('xov,po,qv->xpq', xb, orbob, orbvb.conj()) dmsb += lib.einsum('xov,pv,qo->xpq', yb, orbvb, orbob.conj()) v1ao = vresp(numpy.asarray((dmsa, dmsb))) v1aov = lib.einsum('xpq,po,qv->xov', v1ao[0], orboa.conj(), orbva) v1bov = lib.einsum('xpq,po,qv->xov', v1ao[1], orbob.conj(), orbvb) v1avo = lib.einsum('xpq,pv,qo->xov', v1ao[0], orbva.conj(), orboa) v1bvo = lib.einsum('xpq,pv,qo->xov', v1ao[1], orbvb.conj(), orbob) v1ov = xs * e_ia # AX v1vo = ys * e_ia # AY v1ov[:, :nocca * nvira] += v1aov.reshape(nz, -1) v1vo[:, :nocca * nvira] += v1avo.reshape(nz, -1) v1ov[:, nocca * nvira:] += v1bov.reshape(nz, -1) v1vo[:, nocca * nvira:] += v1bvo.reshape(nz, -1) if wfnsym is not None and mol.symmetry: v1ov[:, sym_forbid] = 0 v1vo[:, sym_forbid] = 0 hx = numpy.hstack((v1ov, -v1vo)) return hx return vind, hdiag