def wavefunction(return_mf = False): """ Returns Full CI wave function multiplied by a Jastrow with cusp conditions applied """ from pyqmc import default_msj, default_multislater mol = gto.M(atom="Li 0. 0. 0.; H 0. 0. 3.015", basis='cc-pvqz', unit="bohr", spin=0) mf = scf.ROHF(mol).run() mc = mcscf.CASCI(mf,ncas=6,nelecas=(2,2)) mc.kernel() wf, to_opt, freeze = default_msj(mol, mf, mc) #Only need to take derivatives wrt determinant coefficients to_opt = ['wf1det_coeff'] freeze = {'wf1det_coeff': freeze['wf1det_coeff']} #Only need to take derivatives wrt the highest energy det #, will have least overlap with nodes! freeze = {'wf1det_coeff': np.ones(freeze['wf1det_coeff'].shape).astype(bool)} freeze['wf1det_coeff'][10] = False wf.parameters['wf1det_coeff'] *= 0 wf.parameters['wf1det_coeff'][[0,10]] = 1./np.sqrt(2.) if(return_mf): return mol, mf, mc, wf, to_opt, freeze else: return mol, wf, to_opt, freeze
def test(): # Default multi-Slater wave function mol = gto.M(atom="Li 0. 0. 0.; H 0. 0. 1.5", basis="cc-pvtz", unit="bohr", spin=0) mf = scf.RHF(mol).run() mc = mcscf.CASCI(mf, ncas=2, nelecas=(1, 1)) mc.kernel() wf, to_opt = default_msj(mol, mf, mc) old_parms = wf.parameters lt = LinearTransform(wf.parameters, to_opt) # Test serialize parameters x0 = lt.serialize_parameters(wf.parameters) x0 += np.random.normal(size=x0.shape) wf.parameters = lt.deserialize(x0) assert wf.parameters["wf1det_coeff"][0] == old_parms["wf1det_coeff"][0] assert np.sum(wf.parameters["wf2bcoeff"][0] - old_parms["wf2bcoeff"][0]) == 0 # Test serialize gradients configs = OpenConfigs(np.random.randn(10, 4, 3)) wf.recompute(configs) pgrad = wf.pgradient() pgrad_serial = lt.serialize_gradients(pgrad) assert np.sum(pgrad_serial[:, :3] - pgrad["wf1det_coeff"][:, 1:4]) == 0
def pyqmc_from_hdf(chkfile): """ Loads pyqmc objects from a pyscf checkfile """ mol = lib.chkfile.load_mol(chkfile) mol.output = None mol.stdout = None mf = scf.RHF(mol) mf.__dict__.update(scf.chkfile.load(chkfile, "scf")) with h5py.File(chkfile, "r") as f: mc = mcscf.CASCI(mf, ncas=int(f["mc/ncas"][...]), nelecas=f["mc/nelecas"][...]) mc.ci = f["mc/ci"][...] wf, to_opt, freeze = pyqmc.default_msj(mol, mf, mc) freeze["wf1det_coeff"][...] = False pgrad = pyqmc.gradient_generator(mol, wf, to_opt, freeze) return { "mol": mol, "mf": mf, "to_opt": to_opt, "freeze": freeze, "wf": wf, "pgrad": pgrad, }
def gen_wf(chkfile, casfile, root_weights): mol = pyscf.lib.chkfile.load_mol(chkfile) mol.output = None mol.stdout = None mf = pyscf.scf.RHF(mol) mf.__dict__.update(pyscf.scf.chkfile.load(chkfile, "scf")) with h5py.File(casfile, "r") as f: mc = pyscf.mcscf.CASCI(mf, ncas=int(f["ncas"][...]), nelecas=f["nelecas"][...]) mc.ci = f["ci"][0, ...] mc.ci=0.0 for root, weight in root_weights.items(): mc.ci+=weight*f['ci'][root, ...] wf, to_opt, freeze = pyqmc.default_msj(mol, mf, mc, ion_cusp=True) return { "mol":mol, "mf":mf, "mc":mc, "freeze":freeze, "to_opt":to_opt, "wf":wf }
def runtest(mol, mf, kind=0, do_mc=False): if do_mc: from pyscf import mcscf mc = mcscf.CASCI(mf, ncas=4, nelecas=(1, 1)) mc.kernel() wf = pyqmc.default_msj(mol, mf, mc)[0] kpt = mf.kpt dm = mc.make_rdm1() if len(dm.shape) == 4: dm = np.sum(dm, axis=0) else: kpt = mf.kpts[kind] wf = pyqmc.Slater(mol, mf) dm = mf.make_rdm1() print("original dm shape", dm.shape) if len(dm.shape) == 4: dm = np.sum(dm, axis=0) dm = dm[kind] ##################################### ## evaluate KE in PySCF ##################################### ke_mat = mol.pbc_intor("int1e_kin", hermi=1, kpts=np.array(kpt)) print("ke_mat", ke_mat.shape) print("dm", dm.shape) pyscfke = np.real(np.einsum("ij,ji->", ke_mat, dm)) print("PySCF kinetic energy: {0}".format(pyscfke)) ##################################### ## evaluate KE integral with VMC ##################################### coords = pyqmc.initial_guess(mol, 1200, 0.7) warmup = 10 start = time.time() df, coords = pyqmc.vmc( wf, coords, nsteps=100 + warmup, tstep=1, accumulators={"energy": pyqmc.accumulators.EnergyAccumulator(mol)}, verbose=False, hdf_file=str(uuid.uuid4()), ) print("VMC time", time.time() - start) df = pd.DataFrame(df) dfke = reblock(df["energyke"][warmup:], 10) dfke /= mol.scale vmcke, err = dfke.mean(), dfke.sem() print("VMC kinetic energy: {0} +- {1}".format(vmcke, err)) assert ( np.abs(vmcke - pyscfke) < 5 * err ), "energy diff not within 5 sigma ({0:.6f}): energies \n{1} \n{2}".format( 5 * err, vmcke, pyscfke)
def test(): """ Tests that the multi-slater wave function value, gradient and parameter gradient evaluations are working correctly. Also checks that VMC energy matches energy calculated in PySCF """ mol = gto.M(atom="Li 0. 0. 0.; H 0. 0. 1.5", basis="cc-pvtz", unit="bohr", spin=0) epsilon = 1e-4 delta = 1e-5 nsteps = 200 warmup = 10 for mf in [scf.RHF(mol).run(), scf.ROHF(mol).run(), scf.UHF(mol).run()]: # Test same number of elecs mc = mcscf.CASCI(mf, ncas=4, nelecas=(1, 1)) mc.kernel() wf = MultiSlater(mol, mf, mc) nconf = 10 nelec = np.sum(mol.nelec) epos = initial_guess(mol, nconf) for k, item in testwf.test_updateinternals(wf, epos).items(): assert item < epsilon assert testwf.test_wf_gradient(wf, epos, delta=delta)[0] < epsilon assert testwf.test_wf_laplacian(wf, epos, delta=delta)[0] < epsilon assert testwf.test_wf_pgradient(wf, epos, delta=delta)[0] < epsilon # Test same number of elecs mc = mcscf.CASCI(mf, ncas=4, nelecas=(1, 1)) mc.kernel() wf = pyqmc.default_msj(mol, mf, mc)[0] nelec = np.sum(mol.nelec) epos = initial_guess(mol, nconf) for k, item in testwf.test_updateinternals(wf, epos).items(): assert item < epsilon assert testwf.test_wf_gradient(wf, epos, delta=delta)[0] < epsilon assert testwf.test_wf_laplacian(wf, epos, delta=delta)[0] < epsilon assert testwf.test_wf_pgradient(wf, epos, delta=delta)[0] < epsilon # Test different number of elecs mc = mcscf.CASCI(mf, ncas=4, nelecas=(2, 0)) mc.kernel() wf = MultiSlater(mol, mf, mc) nelec = np.sum(mol.nelec) epos = initial_guess(mol, nconf) for k, item in testwf.test_updateinternals(wf, epos).items(): assert item < epsilon assert testwf.test_wf_gradient(wf, epos, delta=delta)[0] < epsilon assert testwf.test_wf_laplacian(wf, epos, delta=delta)[0] < epsilon assert testwf.test_wf_pgradient(wf, epos, delta=delta)[0] < epsilon # Quick VMC test nconf = 1000 coords = initial_guess(mol, nconf) df, coords = vmc(wf, coords, nsteps=nsteps, accumulators={"energy": EnergyAccumulator(mol)}) df = pd.DataFrame(df) df = reblock(df["energytotal"][warmup:], 20) en = df.mean() err = df.sem() assert en - mc.e_tot < 5 * err