def mc1step_gen_g_hop(mc, mo, u, casdm1, casdm2, eris): ''' Wrapper to mc1step.gen_g_hop for minimizing the PDFT energy instead of the CASSCF energy by varying orbitals ''' ncore, ncas, nelecas = mc.ncore, mc.ncas, mc.nelecas nocc = ncore + ncas nao, nmo = mo.shape casdm1s = casdm1 * 0.5 casdm1s = np.stack([casdm1s, casdm1s], axis=0) veff1, veff2 = mc.get_pdft_veff(mo=mo, casdm1s=casdm1s, casdm2=casdm2, incl_coul=True) veff2.eot_h_op = EotOrbitalHessianOperator(mc, mo_coeff=mo, casdm1=casdm1, casdm2=casdm2, do_cumulant=True) def get_hcore(mol=None): return mc._scf.get_hcore(mol) + veff1 with lib.temporary_env(mc, get_hcore=get_hcore): g_orb, _, h_op, h_diag = mc1step.gen_g_hop(mc, mo, u, casdm1, casdm2, veff2) gorb_update = get_gorb_update(mc, mo) return g_orb, gorb_update, h_op, h_diag
def __init__(self, mc): oneRDMs = mc.make_rdm1s () casdm1s = mc.fcisolver.make_rdm1s (mc.ci, mc.ncas, mc.nelecas) casdm1, casdm2 = mc.fcisolver.make_rdm12 (mc.ci, mc.ncas, mc.nelecas) twoCDM = get_2CDM_from_2RDM (casdm2, casdm1s) ao2amo = mc.mo_coeff[:,mc.ncore:][:,:mc.ncas] self.calculator = HessianCalculator (mc._scf, oneRDMs, twoCDM, ao2amo) self.cas = mc self.cas_mo = mc.mo_coeff self.ncore, self.ncas, self.nelecas = mc.ncore, mc.ncas, mc.nelecas self.nocc = self.ncore + self.ncas self.nmo = self.cas_mo.shape[1] self.hop, self.hdiag = gen_g_hop (mc, self.cas_mo, 1, casdm1, casdm2, mc.ao2mo (self.cas_mo))[2:]
def gen_g_hop(self, mo, u, casdm1, casdm2, eris): casdm1 = _symmetrize(casdm1, self.orbsym[self.ncore : self.ncore + self.ncas], self.mol.groupname) g_orb, gorb_op, h_op, h_diag = mc1step.gen_g_hop(self, mo, u, casdm1, casdm2, eris) g_orb = _symmetrize(self.unpack_uniq_var(g_orb), self.orbsym, self.mol.groupname) h_diag = _symmetrize(self.unpack_uniq_var(h_diag), self.orbsym, self.mol.groupname) def sym_h_op(x): hx = h_op(x) hx = _symmetrize(self.unpack_uniq_var(hx), self.orbsym, self.mol.groupname) return self.pack_uniq_var(hx) def sym_gorb_op(x): g = gorb_op(x) g = _symmetrize(self.unpack_uniq_var(g), self.orbsym, self.mol.groupname) return self.pack_uniq_var(g) return self.pack_uniq_var(g_orb), sym_gorb_op, sym_h_op, self.pack_uniq_var(h_diag)
def __init__(self, mc, ot=None, mo_coeff=None, ncore=None, ncas=None, casdm1=None, casdm2=None, max_memory=None, do_cumulant=True, incl_d2rho=False): if ot is None: ot = mc.otfnal if mo_coeff is None: mo_coeff = mc.mo_coeff if ncore is None: ncore = mc.ncore if ncas is None: ncas = mc.ncas if max_memory is None: max_memory = mc.max_memory if (casdm1 is None) or (casdm2 is None): dm1, dm2 = mc.fcisolver.make_rdm12 (mc.ci, ncas, mc.nelecas) if casdm1 is None: casdm1 = dm1 if casdm2 is None: casdm2 = dm2 self.ot = ot self.verbose, self.stdout = ot.verbose, ot.stdout self.log = lib.logger.new_logger (self, self.verbose) self.ni, self.xctype = ni, xctype = ot._numint, ot.xctype self.rho_deriv, self.Pi_deriv = ot.dens_deriv, ot.Pi_deriv deriv = ot.dens_deriv self.nderiv_rho = (1,4,10)[int (ot.dens_deriv)] self.nderiv_Pi = (1,4)[int (ot.Pi_deriv)] self.nderiv_ao = (deriv+1)*(deriv+2)*(deriv+3)//6 self.mo_coeff = mo_coeff self.nao, self.nmo = nao, nmo = mo_coeff.shape self.ncore = ncore self.ncas = ncas self.nocc = nocc = ncore + ncas self.casdm2 = casdm2 self.casdm1s = casdm1s = np.stack ([casdm1, casdm1], axis=0)/2 self.cascm2 = cascm2 = get_2CDM_from_2RDM (casdm2, casdm1) self.max_memory = max_memory self.do_cumulant = do_cumulant self.incl_d2rho = incl_d2rho self._col_mask = None self._row_mask = None dm1 = 2 * np.eye (nocc, dtype=casdm1.dtype) dm1[ncore:,ncore:] = casdm1 occ_coeff = mo_coeff[:,:nocc] no_occ, uno = linalg.eigh (dm1) no_coeff = occ_coeff @ uno dm1 = occ_coeff @ dm1 @ occ_coeff.conj ().T self.dm1 = dm1 = lib.tag_array (dm1, mo_coeff=no_coeff, mo_occ=no_occ) self.make_rho = ni._gen_rho_evaluator (ot.mol, dm1, 1)[0] self.pack_uniq_var = mc.pack_uniq_var self.unpack_uniq_var = mc.unpack_uniq_var self.shls_slice = (0, ot.mol.nbas) self.ao_loc = ot.mol.ao_loc_nr() if incl_d2rho: # Include d^2rho/dk^2 type derivatives # Also include a full E_OT value and gradient recalculator # for debugging purposes self.veff1, self.veff2 = mc.get_pdft_veff (mo=mo_coeff, casdm1s=casdm1s, casdm2=casdm2, incl_coul=False) get_hcore = lambda * args: self.veff1 with lib.temporary_env (mc, get_hcore=get_hcore): g_orb, _, h_op, h_diag = mc1step.gen_g_hop (mc, mo_coeff, np.eye (nmo), casdm1, casdm2, self.veff2) # dressed gen_g_hop objects from mrh.my_pyscf.mcpdft.orb_scf import get_gorb_update gorb_update_u = get_gorb_update (mc, mo_coeff, ncore=ncore, ncas=ncas, eot_only=True) def delta_gorb (x): u = mc.update_rotate_matrix (x) g1 = gorb_update_u (u, mc.ci) return g1 - g_orb jk_null = np.zeros ((ncas,nmo)), np.zeros ((ncore,nmo-ncore)) update_jk = lambda * args: jk_null def d2rho_h_op (x): with lib.temporary_env (mc, update_jk_in_ah=update_jk): return h_op (x) self.g_orb = g_orb self.delta_gorb = delta_gorb self.d2rho_h_op = d2rho_h_op self.h_diag = h_diag # on-top energy and calculator mo_cas = mo_coeff[:,ncore:nocc] dm1s = np.dot (mo_cas, casdm1s).transpose (1,0,2) dm1s = np.dot (dm1s, mo_cas.conj ().T) mo_core = mo_coeff[:,:ncore] dm1s += (mo_core @ mo_core.conj ().T)[None,:,:] dm_list = (dm1s, (casdm1s, (cascm2, None, None))) e_ot = mc.energy_dft (ot=ot, mo_coeff=mo_coeff, dm_list=dm_list) def delta_eot (x): u = mc.update_rotate_matrix (x) mo1 = mo_coeff @ u mo_cas = mo1[:,ncore:nocc] dm1s = np.dot (mo_cas, casdm1s).transpose (1,0,2) dm1s = np.dot (dm1s, mo_cas.conj ().T) mo_core = mo1[:,:ncore] dm1s += (mo_core @ mo_core.conj ().T)[None,:,:] dm_list = (dm1s, (casdm1s, (cascm2, None, None))) e1 = mc.energy_dft (ot=ot, mo_coeff=mo1, dm_list=dm_list) return e1 - e_ot self.e_ot = e_ot self.delta_eot = delta_eot if self.verbose > lib.logger.INFO: # TODO: require higher verbosity from mrh.my_pyscf.mcpdft.pdft_veff import lazy_kernel v1, v2 = lazy_kernel (ot, dm1s, cascm2, mo_coeff[:,ncore:nocc]) self._v1 = mo_coeff.conj ().T @ v1 @ mo_coeff self._v2 = ao2mo.full (v2, mo_coeff)