def get_wfn_response(self, atmlst=None, state=None, verbose=None, mo=None, ci=None, **kwargs): if state is None: state = self.state if atmlst is None: atmlst = self.atmlst if verbose is None: verbose = self.verbose if mo is None: mo = self.base.mo_coeff if ci is None: ci = self.base.ci ndet = self.na_states[state] * self.nb_states[state] fcasscf = self.make_fcasscf(state) fcasscf.mo_coeff = mo fcasscf.ci = ci[state] eris = fcasscf.ao2mo(mo) g_all_state = newton_casscf.gen_g_hop(fcasscf, mo, ci[state], eris, verbose)[0] g_all = np.zeros(self.nlag) g_all[:self.ngorb] = g_all_state[:self.ngorb] # No need to reshape or anything, just use the magic of repeated slicing offs = sum([ na * nb for na, nb in zip(self.na_states[:state], self.nb_states[:state]) ]) if state > 0 else 0 g_all[self.ngorb:][offs:][:ndet] = g_all_state[self.ngorb:] return g_all
def get_Aop_Adiag(self, atmlst=None, state=None, verbose=None, mo=None, ci=None, eris=None, level_shift=None, **kwargs): if state is None: state = self.state if atmlst is None: atmlst = self.atmlst if verbose is None: verbose = self.verbose if mo is None: mo = self.base.mo_coeff if ci is None: ci = self.base.ci if eris is None and self.eris is None: eris = self.eris = self.base.ao2mo(mo) elif eris is None: eris = self.eris if not isinstance(self.base, StateAverageMCSCFSolver) and isinstance( ci, list): ci = ci[0] fcasscf = self.make_fcasscf_sa() Aop, Adiag = newton_casscf.gen_g_hop(fcasscf, mo, ci, eris, verbose)[2:] # Eliminate the component of Aop (x) which is parallel to the state-average space # The Lagrange multiplier equations are not defined there return self.project_Aop(Aop, ci, state), Adiag
def test_derivatives(self): np.random.seed(1) las = LASSCF(mf, (4, ), (4, ), spin_sub=(1, )).set(max_cycle_macro=1, ah_level_shift=0).run() ugg = las.get_ugg() ci0_csf = np.random.rand(ugg.ncsf_sub[0][0]) ci0_csf /= np.linalg.norm(ci0_csf) ci0 = ugg.ci_transformers[0][0].vec_csf2det(ci0_csf) las_gorb, las_gci = las.get_grad(mo_coeff=mf.mo_coeff, ci=[[ci0]])[:2] las_grad = np.append(las_gorb, las_gci) las_hess = las.get_hop(ugg=ugg, mo_coeff=mf.mo_coeff, ci=[[ci0]]) self.assertAlmostEqual(lib.fp(las_grad), lib.fp(las_hess.get_grad()), 8) cas_grad, _, cas_hess, _ = newton_casscf.gen_g_hop( mc, mf.mo_coeff, ci0, mc.ao2mo(mf.mo_coeff)) _pack_ci, _unpack_ci = newton_casscf._pack_ci_get_H( mc, mf.mo_coeff, ci0)[-2:] def pack_cas(kappa, ci1): return np.append(mc.pack_uniq_var(kappa), _pack_ci(ci1)) def unpack_cas(x): return mc.unpack_uniq_var(x[:ugg.nvar_orb]), _unpack_ci( x[ugg.nvar_orb:]) def cas2las(y, mode='hx'): yorb, yci = unpack_cas(y) yc = yci[0].ravel().dot(ci0.ravel()) yci[0] -= yc * ci0 yorb *= (0.5 if mode == 'hx' else 1) return ugg.pack(yorb, [yci]) def las2cas(y, mode='x'): yorb, yci = ugg.unpack(y) yc = yci[0][0].ravel().dot(ci0.ravel()) yci[0][0] -= yc * ci0 yorb *= (0.5 if mode == 'x' else 1) return pack_cas(yorb, yci[0]) cas_grad = cas2las(cas_grad) self.assertAlmostEqual(lib.fp(las_grad), lib.fp(cas_grad), 8) x = np.random.rand(ugg.nvar_tot) # orb on input x_las = x.copy() x_las[ugg.nvar_orb:] = 0.0 x_cas = las2cas(x_las, mode='x') hx_las = las_hess._matvec(x_las) hx_cas = cas2las(cas_hess(x_cas), mode='x') self.assertAlmostEqual(lib.fp(hx_las), lib.fp(hx_cas), 8) # CI on input x_las = x.copy() x_las[:ugg.nvar_orb] = 0.0 x_cas = las2cas(x_las, mode='hx') hx_las = las_hess._matvec(x_las) hx_cas = cas2las(cas_hess(x_cas), mode='hx') self.assertAlmostEqual(lib.fp(hx_las), lib.fp(hx_cas), 8)
def test_gen_g_hop(self): mo = mc.mo_coeff gall, gop, hop, hdiag = newton_casscf.gen_g_hop( mc, mo, ci0, mc.ao2mo(mo)) self.assertAlmostEqual(lib.finger(gall), 21.288022525148595, 8) self.assertAlmostEqual(lib.finger(hdiag), -4.6864640132374618, 8) x = numpy.random.random(gall.size) u, ci1 = newton_casscf.extract_rotation(mc, x, 1, ci0) self.assertAlmostEqual(lib.finger(gop(u, ci1)), -412.9441873541524, 8) self.assertAlmostEqual(lib.finger(hop(x)), 73.358310983341198, 8)
def test_gen_g_hop(self): mo = mc.mo_coeff gall, gop, hop, hdiag = newton_casscf.gen_g_hop( mc, mo, ci0, mc.ao2mo(mo)) self.assertAlmostEqual(lib.finger(gall), 6.3906103343021083, 8) self.assertAlmostEqual(lib.finger(hdiag), -7.9071928112940615, 8) x = numpy.random.random(gall.size) u, ci1 = newton_casscf.extract_rotation(mc, x, 1, ci0) self.assertAlmostEqual(lib.finger(gop(u, ci1)), -419.68206754700418, 8) self.assertAlmostEqual(lib.finger(hop(x)), 78.31792009930723, 8)
def test_gen_g_hop(self): numpy.random.seed(1) mo = numpy.random.random(mf.mo_coeff.shape) ci0 = numpy.random.random((6,6)) ci0/= numpy.linalg.norm(ci0) gall, gop, hop, hdiag = newton_casscf.gen_g_hop(mc, mo, ci0, mc.ao2mo(mo)) self.assertAlmostEqual(lib.finger(gall), 21.288022525148595, 8) self.assertAlmostEqual(lib.finger(hdiag), -4.6864640132374618, 8) x = numpy.random.random(gall.size) u, ci1 = newton_casscf.extract_rotation(mc, x, 1, ci0) self.assertAlmostEqual(lib.finger(gop(u, ci1)), -412.9441873541524, 8) self.assertAlmostEqual(lib.finger(hop(x)), 73.358310983341198, 8)
def test_sa_gen_g_hop(self): numpy.random.seed(1) mo = numpy.random.random(mf.mo_coeff.shape) ci0 = numpy.random.random((2, 36)) ci0 /= numpy.linalg.norm(ci0, axis=1)[:, None] ci0 = list(ci0.reshape((2, 6, 6))) gall, gop, hop, hdiag = newton_casscf.gen_g_hop( sa, mo, ci0, sa.ao2mo(mo)) self.assertAlmostEqual(lib.finger(gall), 32.46973284682045, 8) self.assertAlmostEqual(lib.finger(hdiag), -63.6527761153809, 8) x = numpy.random.random(gall.size) u, ci1 = newton_casscf.extract_rotation(sa, x, 1, ci0) self.assertAlmostEqual(lib.finger(gop(u, ci1)), -49.017079186126, 8) self.assertAlmostEqual(lib.finger(hop(x)), 169.47893548740288, 8)
def test_derivatives (self): np.random.seed(1) las = LASSCF (mf, (4,), (4,), spin_sub=(1,)).set (max_cycle_macro=1, ah_level_shift=0) las.state_average_(weights=[0.5,0.5], charges=[0,0], spins=[0,2], smults=[1,3]).run () ugg = las.get_ugg () ci0_csf = [np.random.rand (ncsf) for ncsf in ugg.ncsf_sub[0]] ci0_csf = [c / np.linalg.norm (c) for c in ci0_csf] ci0 = [t.vec_csf2det (c) for t, c in zip (ugg.ci_transformers[0], ci0_csf)] las_gorb, las_gci = las.get_grad (mo_coeff=mf.mo_coeff, ci=[ci0])[:2] las_grad = np.append (las_gorb, las_gci) las_hess = las.get_hop (ugg=ugg, mo_coeff=mf.mo_coeff, ci=[ci0]) self.assertAlmostEqual (lib.fp (las_grad), lib.fp (las_hess.get_grad ()), 8) cas_grad, _, cas_hess, _ = newton_casscf.gen_g_hop (mc, mf.mo_coeff, ci0, mc.ao2mo (mf.mo_coeff)) _pack_ci, _unpack_ci = newton_casscf._pack_ci_get_H (mc, mf.mo_coeff, ci0)[-2:] def pack_cas (kappa, ci1): return np.append (mc.pack_uniq_var (kappa), _pack_ci (ci1)) def unpack_cas (x): return mc.unpack_uniq_var (x[:ugg.nvar_orb]), _unpack_ci (x[ugg.nvar_orb:]) def cas2las (y, mode='hx'): yorb, yci = unpack_cas (y) yci = [2 * (yc - c * c.ravel ().dot (yc.ravel ())) for c, yc in zip (ci0, yci)] yorb *= (0.5 if mode=='hx' else 1) return ugg.pack (yorb, [yci]) def las2cas (y, mode='x'): yorb, yci = ugg.unpack (y) yci = [yc - c * c.ravel ().dot (yc.ravel ()) for c, yc in zip (ci0, yci[0])] yorb *= (0.5 if mode=='x' else 1) return pack_cas (yorb, yci) cas_grad = cas2las (cas_grad) self.assertAlmostEqual (lib.fp (las_grad), lib.fp (cas_grad), 8) x = np.random.rand (ugg.nvar_tot) # orb on input x_las = x.copy () x_las[ugg.nvar_orb:] = 0.0 x_cas = las2cas (x_las, mode='x') hx_las = las_hess._matvec (x_las) hx_cas = cas2las (cas_hess (x_cas), mode='x') self.assertAlmostEqual (lib.fp (hx_las), lib.fp (hx_cas), 8) # CI on input x_las = x.copy () x_las[:ugg.nvar_orb] = 0.0 x_cas = las2cas (x_las, mode='hx') hx_las = las_hess._matvec (x_las) hx_cas = cas2las (cas_hess (x_cas), mode='hx') self.assertAlmostEqual (lib.fp (hx_las), lib.fp (hx_cas), 8)
def get_wfn_response(self, atmlst=None, state=None, verbose=None, mo=None, ci=None, veff1=None, veff2=None, **kwargs): if state is None: state = self.state if atmlst is None: atmlst = self.atmlst if verbose is None: verbose = self.verbose if mo is None: mo = self.base.mo_coeff if ci is None: ci = self.base.ci if (veff1 is None) or (veff2 is None): assert (False), kwargs veff1, veff2 = self.base.get_pdft_veff(mo, ci[state], incl_coul=True, paaa_only=True) ndet = ci[state].size fcasscf = self.make_fcasscf(state) fcasscf.mo_coeff = mo fcasscf.ci = ci[state] def my_hcore(): return self.base.get_hcore() + veff1 fcasscf.get_hcore = my_hcore g_all_state = newton_casscf.gen_g_hop(fcasscf, mo, ci[state], veff2, verbose)[0] g_all = np.zeros(self.nlag) g_all[:self.ngorb] = g_all_state[:self.ngorb] # Eliminate gradient of self-rotation gci_state = g_all_state[self.ngorb:] ci_arr = np.asarray(ci).reshape(self.nroots, -1) gci_sa = np.dot(ci_arr[state], gci_state) gci_state -= gci_sa * gci_state gci = g_all[self.ngorb:].reshape(self.nroots, -1) gci[state] += gci_state return g_all
def get_wfn_response(self, atmlst=None, iroot=None, verbose=None, mo=None, ci=None, **kwargs): if iroot is None: iroot = self.iroot if atmlst is None: atmlst = self.atmlst if verbose is None: verbose = self.verbose if mo is None: mo = self.base.mo_coeff if ci is None: ci = self.base.ci ndet = ci[iroot].size fcasscf = self.make_fcasscf() fcasscf.mo_coeff = mo fcasscf.ci = ci[iroot] eris = fcasscf.ao2mo(mo) g_all_iroot = newton_casscf.gen_g_hop(fcasscf, mo, ci[iroot], eris, verbose)[0] g_all = np.zeros(self.nlag) g_all[:self.ngorb] = g_all_iroot[:self.ngorb] # No need to reshape or anything, just use the magic of repeated slicing g_all[self.ngorb:][ndet * iroot:][:ndet] = g_all_iroot[self.ngorb:] return g_all
mc.kernel () #mo_coeff = mc.mo_coeff.copy () print (mc.converged, mc.e_tot) las = LASSCFNoSymm (mf, (4,), ((2,2),), spin_sub=(1,)) las.kernel (mo_coeff) mc.mo_coeff = mo_coeff.copy () las.mo_coeff = mo_coeff.copy () las.ci = [[mc.ci.copy ()]] nao, nmo = mo_coeff.shape ncore, ncas = mc.ncore, mc.ncas nocc = ncore + ncas eris = mc.ao2mo () from pyscf.mcscf.newton_casscf import gen_g_hop, _pack_ci_get_H g_all_cas, g_update_cas, h_op_cas, hdiag_all_cas = gen_g_hop (mc, mo_coeff, mc.ci, eris) _pack_ci, _unpack_ci = _pack_ci_get_H (mc, mo_coeff, mc.ci)[-2:] nvar_orb_cas = np.count_nonzero (mc.uniq_var_indices (nmo, mc.ncore, mc.ncas, mc.frozen)) nvar_tot_cas = g_all_cas.size def pack_cas (kappa, ci1): return np.append (mc.pack_uniq_var (kappa), _pack_ci (ci1)) def unpack_cas (x): return mc.unpack_uniq_var (x[:nvar_orb_cas]), _unpack_ci (x[nvar_orb_cas:]) ugg = las.get_ugg (las.mo_coeff, las.ci) h_op_las = las.get_hop (ugg=ugg) print ("Total # variables: {} CAS ; {} LAS".format (nvar_tot_cas, ugg.nvar_tot)) print ("# orbital variables: {} CAS ; {} LAS".format (nvar_orb_cas, ugg.nvar_orb)) gorb_cas, gci_cas = unpack_cas (g_all_cas)
def gen_g_hop(casscf, mo, ci0, eris, verbose=None): # MRH: I'm just going to pass this to the newton_casscf version and average/weight/change to and from CSF's post facto! ncas = casscf.ncas ncore = casscf.ncore nocc = ncas + ncore nelecas = casscf.nelecas neleca, nelecb = _unpack_nelec(nelecas) nmo = mo.shape[1] nroot = len(ci0) ndet = ci0[0].size norb = mo.shape[-1] ngorb = np.count_nonzero( casscf.uniq_var_indices(norb, ncore, ncas, casscf.frozen)) weights_2d = np.asarray(casscf.weights)[:, None] weights_3d = np.asarray(casscf.weights)[:, None, None] mc_fci = casscf.fcisolver is_csf = isinstance(mc_fci, ( csf.FCISolver, csf_symm.FCISolver, )) if is_csf: if hasattr(mc_fci, 'wfnsym') and hasattr(mc_fci, 'confsym'): idx_sym = mc_fci.confsym[mc_fci.econf_csf_mask] == mc_fci.wfnsym else: idx_sym = None smult = mc_fci.smult fcasscf = mc1step.CASSCF(casscf._scf, ncas, nelecas) fcasscf.fcisolver = casscf.ss_fcisolver gh_roots = [ newton_casscf.gen_g_hop(fcasscf, mo, ci0_i, eris, verbose=verbose) for ci0_i in ci0 ] def avg_orb_wgt_ci(x_roots): x_orb = sum([ x_iroot[:ngorb] * w for x_iroot, w in zip(x_roots, casscf.weights) ]) x_ci = np.stack([ x_iroot[ngorb:] * w for x_iroot, w in zip(x_roots, casscf.weights) ], axis=0) if is_csf: x_ci = csf.pack_sym_ci( transform_civec_det2csf(x_ci, ncas, neleca, nelecb, smult, csd_mask=mc_fci.csd_mask, do_normalize=False)[0], idx_sym) x_all = np.append(x_orb, x_ci.ravel()).ravel() return x_all g_all = avg_orb_wgt_ci([gh_iroot[0] for gh_iroot in gh_roots]) hdiag_all = avg_orb_wgt_ci([gh_iroot[3] for gh_iroot in gh_roots]) def g_update(u, fcivec): return avg_orb_wgt_ci( [gh_iroot[1](u, ci) for gh_iroot, ci in zip(gh_roots, fcivec)]) def h_op(x): x_orb = x[:ngorb] x_ci = x[ngorb:].reshape(nroot, -1) if is_csf: x_ci = transform_civec_csf2det(csf.unpack_sym_ci(x_ci, idx_sym), ncas, neleca, nelecb, smult, csd_mask=mc_fci.csd_mask, do_normalize=False)[0] return avg_orb_wgt_ci([ gh_iroot[2](np.append(x_orb, x_ci_iroot)) for gh_iroot, x_ci_iroot in zip(gh_roots, x_ci) ]) return g_all, g_update, h_op, hdiag_all