def test_pbc_wfs(): """ Ensure that the wave function objects are consistent in several situations. """ from pyscf.pbc import lib, gto, scf from pyqmc.supercell import get_supercell from pyqmc.slater import Slater from pyqmc.multiplywf import MultiplyWF from pyqmc import default_jastrow import pyqmc mol = gto.M( atom="H 0. 0. 0.; H 1. 1. 1.", basis="sto-3g", unit="bohr", a=(np.ones((3, 3)) - np.eye(3)) * 4, ) mf = scf.KRKS(mol, mol.make_kpts((2, 2, 2))).run() # mf_rohf = scf.KROKS(mol).run() # mf_uhf = scf.KUKS(mol).run() epsilon = 1e-5 nconf = 10 supercell = get_supercell(mol, S=(np.ones((3, 3)) - 2 * np.eye(3))) epos = pyqmc.initial_guess(supercell, nconf) # For multislaterpbc # kinds = 0, 3, 5, 6 # G, X, Y, Z # d1 = {kind: [0] for kind in kinds} # d2 = d1.copy() # d2.update({0: [], 3: [0, 1]}) # detwt = [2 ** 0.5, 2 ** 0.5] # occup = [[d1, d2], [d1]] # map_dets = [[0, 1], [0, 0]] for wf in [ MultiplyWF(Slater(supercell, mf), default_jastrow(supercell)[0]), Slater(supercell, mf), ]: for k in wf.parameters: if "mo_coeff" not in k and k != "det_coeff": wf.parameters[k] = np.random.rand(*wf.parameters[k].shape) _, epos = pyqmc.vmc(wf, epos, nblocks=1, nsteps=2, tstep=1) # move off node for fname, func in zip( ["gradient", "laplacian", "pgradient"], [ testwf.test_wf_gradient, testwf.test_wf_laplacian, testwf.test_wf_pgradient, ], ): err = [] for delta in [1e-4, 1e-5, 1e-6, 1e-7, 1e-8]: err.append(func(wf, epos, delta)) print(type(wf), fname, min(err)) assert min(err) < epsilon for k, item in testwf.test_updateinternals(wf, epos).items(): print(k, item) assert item < epsilon
def test_vmc(): """ Test that a VMC calculation of a Slater determinant matches Hartree-Fock within error bars. """ nconf = 1000 mol = gto.M(atom="Li 0. 0. 0.; Li 0. 0. 1.5", basis="cc-pvtz", unit="bohr", verbose=1) mf_rhf = scf.RHF(mol).run() mf_uhf = scf.UHF(mol).run() nsteps = 300 warmup = 30 for wf, mf in [ (Slater(mol, mf_rhf), mf_rhf), (Slater(mol, mf_uhf), mf_uhf), ]: # Without blocks coords = initial_guess(mol, nconf) df, coords = vmc( wf, coords, nsteps=nsteps, accumulators={"energy": EnergyAccumulator(mol)}, verbose=True, ) df = pd.DataFrame(df) df = reblock(df["energytotal"][warmup:], 20) en = df.mean() err = df.sem() assert en - mf.energy_tot( ) < 5 * err, "pyscf {0}, vmc {1}, err {2}".format( mf.energy_tot(), en, err) # With blocks coords = initial_guess(mol, nconf) df, coords = vmc( wf, coords, nblocks=int(nsteps / 30), nsteps_per_block=30, accumulators={"energy": EnergyAccumulator(mol)}, ) df = pd.DataFrame(df)["energytotal"][int(warmup / 30):] en = df.mean() err = df.sem() assert en - mf.energy_tot( ) < 5 * err, "pyscf {0}, vmc {1}, err {2}".format( mf.energy_tot(), en, err)
def test_wfs(): """ Ensure that the wave function objects are consistent in several situations. """ from pyscf import lib, gto, scf from pyqmc import Slater from pyqmc.multiplywf import MultiplyWF from pyqmc.manybody_jastrow import J3 from pyqmc import default_jastrow import pyqmc mol = gto.M(atom="Li 0. 0. 0.; H 0. 0. 1.5", basis="sto-3g", unit="bohr") mf = scf.RHF(mol).run() mf_rohf = scf.ROHF(mol).run() mf_uhf = scf.UHF(mol).run() epsilon = 1e-5 nconf = 10 epos = pyqmc.initial_guess(mol, nconf) for wf in [ default_jastrow(mol)[0], J3(mol), MultiplyWF(Slater(mol, mf), default_jastrow(mol)[0]), MultiplyWF(Slater(mol, mf), default_jastrow(mol)[0], J3(mol)), Slater(mol, mf_uhf), Slater(mol, mf), Slater(mol, mf_rohf), ]: for k in wf.parameters: if k != "mo_coeff": wf.parameters[k] = np.random.rand(*wf.parameters[k].shape) for k, item in testwf.test_updateinternals(wf, epos).items(): print(k, item) assert item < epsilon testwf.test_mask(wf, 0, epos) _, epos = pyqmc.vmc(wf, epos, nblocks=1, nsteps=2, tstep=1) # move off node for fname, func in zip( ["gradient", "laplacian", "pgradient"], [ testwf.test_wf_gradient, testwf.test_wf_laplacian, testwf.test_wf_pgradient, ], ): err = [] for delta in [1e-4, 1e-5, 1e-6, 1e-7, 1e-8]: err.append(func(wf, epos, delta)) print(type(wf), fname, min(err)) assert min(err) < epsilon, "epsilon {0}".format(epsilon)
def test_ecp(): mol = gto.M( atom="""C 0 0 0 C 1 0 0 """, ecp="bfd", basis="bfd_vtz", ) mf = scf.RHF(mol).run() nconf = 1000 coords = initial_guess(mol, nconf) thresholds = [1e15, 100, 50, 20, 10, 5, 1] label = ["S", "J", "SJ"] ind = 0 for wf in [ Slater(mol, mf), default_jastrow(mol)[0], MultiplyWF(Slater(mol, mf), default_jastrow(mol)[0]), ]: wf.recompute(coords) print(label[ind]) ind += 1 for threshold in thresholds: eacc = EnergyAccumulator(mol, threshold) start = time.time() eacc(coords, wf) end = time.time() print("Threshold=", threshold, np.around(end - start, 2), "s") mc = mcscf.CASCI(mf, ncas=4, nelecas=(2, 2)) mc.kernel() label = ["MS"] ind = 0 for wf in [Slater(mol, mf, mc)]: wf.recompute(coords) print(label[ind]) ind += 1 for threshold in thresholds: eacc = EnergyAccumulator(mol, threshold) start = time.time() eacc(coords, wf) end = time.time() print("Threshold=", threshold, np.around(end - start, 2), "s")
def test(): mol = gto.M(atom="Li 0. 0. 0.; Li 0. 0. 1.5", basis="sto-3g", unit="bohr", verbose=0) mf = scf.RHF(mol).run() # Lowdin orthogonalized AO basis. lowdin = lo.orth_ao(mol, "lowdin") # MOs in the Lowdin basis. mo = solve(lowdin, mf.mo_coeff) # make AO to localized orbital coefficients. mfobdm = mf.make_rdm1(mo, mf.mo_occ) ### Test OBDM calculation. nconf = 500 nsteps = 400 warmup = 15 wf = Slater(mol, mf) configs = initial_guess(mol, nconf) obdm_dict = dict(mol=mol, orb_coeff=lowdin, nsweeps=5, warmup=15) obdm = OBDMAccumulator(**obdm_dict) obdm_up = OBDMAccumulator(**obdm_dict, spin=0) obdm_down = OBDMAccumulator(**obdm_dict, spin=1) df, coords = vmc( wf, configs, nsteps=nsteps, accumulators={ "obdm": obdm, "obdm_up": obdm_up, "obdm_down": obdm_down }, ) obdm_est = {} for k in ["obdm", "obdm_up", "obdm_down"]: avg_norm = np.mean(df[k + "norm"][warmup:], axis=0) avg_obdm = np.mean(df[k + "value"][warmup:], axis=0) obdm_est[k] = normalize_obdm(avg_obdm, avg_norm) print("Average OBDM(orb,orb)", obdm_est["obdm"].diagonal().round(3)) print("mf obdm", mfobdm.diagonal().round(3)) assert np.max(np.abs(obdm_est["obdm"] - mfobdm)) < 0.05 print(obdm_est["obdm_up"].diagonal().round(3)) print(obdm_est["obdm_down"].diagonal().round(3)) assert np.mean( np.abs(obdm_est["obdm_up"] + obdm_est["obdm_down"] - mfobdm)) < 0.05
def test_accumulator(): """Tests that the accumulator gets inserted into the data output correctly.""" mol = gto.M(atom="Li 0. 0. 0.; Li 0. 0. 1.5", basis="cc-pvtz", unit="bohr", verbose=5) mf = scf.RHF(mol).run() nconf = 5000 wf = Slater(mol, mf) coords = initial_guess(mol, nconf) df, coords = vmc(wf, coords, nsteps=30, accumulators={"energy": EnergyAccumulator(mol)}) df = pd.DataFrame(df) eaccum = EnergyAccumulator(mol) eaccum_energy = eaccum(coords, wf) df = pd.DataFrame(df) print(df["energytotal"][29] == np.average(eaccum_energy["total"])) assert df["energytotal"][29] == np.average(eaccum_energy["total"])
def test_ecp(): mol = gto.M(atom="C 0. 0. 0.", ecp="bfd", basis="bfd_vtz") mf = scf.RHF(mol).run() nconf = 5000 wf = Slater(mol, mf) coords = initial_guess(mol, nconf) df, coords = vmc(wf, coords, nsteps=100, accumulators={"energy": EnergyAccumulator(mol)}) df = pd.DataFrame(df) warmup = 30 print( "mean field", mf.energy_tot(), "vmc estimation", np.mean(df["energytotal"][warmup:]), np.std(df["energytotal"][warmup:]), ) assert abs(mf.energy_tot() - np.mean(df["energytotal"][warmup:])) <= np.std( df["energytotal"][warmup:])
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.UHF(mol).run() ]: # [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 = Slater(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) < epsilon assert testwf.test_wf_laplacian(wf, epos, delta=delta) < epsilon assert testwf.test_wf_pgradient(wf, epos, delta=delta) < 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) < epsilon assert testwf.test_wf_laplacian(wf, epos, delta=delta) < epsilon assert testwf.test_wf_pgradient(wf, epos, delta=delta) < epsilon # Test different number of elecs mc = mcscf.CASCI(mf, ncas=4, nelecas=(2, 0)) mc.kernel() wf = Slater(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) < epsilon assert testwf.test_wf_laplacian(wf, epos, delta=delta) < epsilon assert testwf.test_wf_pgradient(wf, epos, delta=delta) < 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
def test(atom="He", total_spin=0, total_charge=0, scf_basis="sto-3g"): mol = gto.M( atom="%s 0. 0. 0.; %s 0. 0. 1.5" % (atom, atom), basis=scf_basis, unit="bohr", verbose=4, spin=total_spin, charge=total_charge, ) mf = scf.UHF(mol).run() # Intrinsic Atomic Orbitals iaos = make_separate_spin_iaos(mol, mf, np.array([i for i in range(mol.natm)]), iao_basis="minao") # iaos=make_combined_spin_iaos(mol,mf,np.array([i for i in range(mol.natm)]),iao_basis='minao') # MOs in the IAO basis mo = reps_combined_spin_iaos( iaos, mf, np.einsum("i,j->ji", np.arange(mf.mo_coeff[0].shape[1]), np.array([1, 1])), ) # Mean-field obdm in IAO basis mfobdm = mf.make_rdm1(mo, mf.mo_occ) # Mean-field tbdm in IAO basis mftbdm = singledet_tbdm(mf, mfobdm) ### Test TBDM calculation. # VMC params nconf = 500 n_vmc_steps = 400 vmc_tstep = 0.3 vmc_warmup = 30 # TBDM params tbdm_sweeps = 4 tbdm_tstep = 0.5 wf = Slater(mol, mf) # Single-Slater (no jastrow) wf configs = initial_guess(mol, nconf) energy = EnergyAccumulator(mol) obdm_up = OBDMAccumulator(mol=mol, orb_coeff=iaos[0], nsweeps=tbdm_sweeps, spin=0) obdm_down = OBDMAccumulator(mol=mol, orb_coeff=iaos[1], nsweeps=tbdm_sweeps, spin=1) tbdm_upup = TBDMAccumulator(mol=mol, orb_coeff=iaos, nsweeps=tbdm_sweeps, tstep=tbdm_tstep, spin=(0, 0)) tbdm_updown = TBDMAccumulator(mol=mol, orb_coeff=iaos, nsweeps=tbdm_sweeps, tstep=tbdm_tstep, spin=(0, 1)) tbdm_downup = TBDMAccumulator(mol=mol, orb_coeff=iaos, nsweeps=tbdm_sweeps, tstep=tbdm_tstep, spin=(1, 0)) tbdm_downdown = TBDMAccumulator(mol=mol, orb_coeff=iaos, nsweeps=tbdm_sweeps, tstep=tbdm_tstep, spin=(1, 1)) print("VMC...") df, coords = vmc( wf, configs, nsteps=n_vmc_steps, tstep=vmc_tstep, accumulators={ "energy": energy, "obdm_up": obdm_up, "obdm_down": obdm_down, "tbdm_upup": tbdm_upup, "tbdm_updown": tbdm_updown, "tbdm_downup": tbdm_downup, "tbdm_downdown": tbdm_downdown, }, verbose=True, ) # Compares obdm from QMC and MF obdm_est = {} for k in ["obdm_up", "obdm_down"]: avg_norm = np.mean(df[k + "norm"][vmc_warmup:], axis=0) avg_obdm = np.mean(df[k + "value"][vmc_warmup:], axis=0) obdm_est[k] = normalize_obdm(avg_obdm, avg_norm) qmcobdm = np.array([obdm_est["obdm_up"], obdm_est["obdm_down"]]) print("\nComparing QMC and MF obdm:") for s in [0, 1]: # print('QMC obdm[%d]:\n'%s,qmcobdm[s]) # print('MF obdm[%d]:\n'%s,mfobdm[s]) print("diff[%d]:\n" % s, qmcobdm[s] - mfobdm[s]) # Compares tbdm from QMC and MF avg_norm = {} avg_tbdm = {} for t in ["tbdm_upup", "tbdm_updown", "tbdm_downup", "tbdm_downdown"]: for k in df.keys(): if k.startswith(t + "norm_"): avg_norm[k.split("_")[-1]] = np.mean(df[k][vmc_warmup:], axis=0) if k.startswith(t + "value"): avg_tbdm[k.split("_")[-1]] = np.mean(df[k][vmc_warmup:], axis=0) tbdm_est = { k: normalize_tbdm(avg_tbdm[k].reshape(2, 2, 2, 2), avg_norm["a"], avg_norm["b"]) for k in avg_tbdm } qmctbdm = np.array([ [tbdm_est["upupvalue"], tbdm_est["updownvalue"]], [tbdm_est["downupvalue"], tbdm_est["downdownvalue"]], ]) print("\nComparing QMC and MF tbdm:") for sa, sb in [[0, 0], [0, 1], [1, 0], [1, 1]]: print("spins", sa, sb) print("QMC tbdm[%d,%d]:\n" % (sa, sb), qmctbdm[sa, sb].round(3)) print("MF tbdm[%d,%d]:\n" % (sa, sb), mftbdm[sa, sb].round(3)) diff = qmctbdm[sa, sb] - mftbdm[sa, sb] print("diff[%d,%d]:\n" % (sa, sb), diff) assert np.max(np.abs(diff)) < 0.05
def test_pbc(): from pyscf.pbc import gto, scf from pyqmc import supercell import scipy lvecs = (np.ones((3, 3)) - 2 * np.eye(3)) * 2.0 mol = gto.M( atom="H 0. 0. -{0}; H 0. 0. {0}".format(0.7), basis="sto-3g", unit="bohr", verbose=0, a=lvecs, ) mf = scf.KRHF(mol, kpts=mol.make_kpts((2, 2, 2))) mf = mf.run() S = np.ones((3, 3)) - np.eye(3) mol = supercell.get_supercell(mol, S) kpts = supercell.get_supercell_kpts(mol)[:2] kdiffs = mf.kpts[np.newaxis] - kpts[:, np.newaxis] kinds = np.nonzero(np.linalg.norm(kdiffs, axis=-1) < 1e-12)[1] # Lowdin orthogonalized AO basis. # lowdin = lo.orth_ao(mol, "lowdin") loiao = lo.iao.iao(mol.original_cell, mf.mo_coeff, kpts=kpts) occs = [mf.mo_occ[k] for k in kinds] coefs = [mf.mo_coeff[k] for k in kinds] ovlp = mf.get_ovlp()[kinds] lowdin = [lo.vec_lowdin(l, o) for l, o in zip(loiao, ovlp)] lreps = [ np.linalg.multi_dot([l.T, o, c]) for l, o, c in zip(lowdin, ovlp, coefs) ] # make AO to localized orbital coefficients. mfobdm = [ np.einsum("ij,j,kj->ik", l.conj(), o, l) for l, o in zip(lreps, occs) ] ### Test OBDM calculation. nconf = 800 nsteps = 50 warmup = 6 wf = Slater(mol, mf) configs = initial_guess(mol, nconf) obdm_dict = dict(mol=mol, orb_coeff=lowdin, kpts=kpts, nsweeps=4, warmup=10) obdm = OBDMAccumulator(**obdm_dict) obdm_up = OBDMAccumulator(**obdm_dict, spin=0) obdm_down = OBDMAccumulator(**obdm_dict, spin=1) df, coords = vmc( wf, configs, nsteps=nsteps, accumulators={ "obdm": obdm, "obdm_up": obdm_up, "obdm_down": obdm_down }, verbose=True, ) obdm_est = {} for k in ["obdm", "obdm_up", "obdm_down"]: avg_norm = np.mean(df[k + "norm"][warmup:], axis=0) avg_obdm = np.mean(df[k + "value"][warmup:], axis=0) obdm_est[k] = normalize_obdm(avg_obdm, avg_norm) print("Average OBDM(orb,orb)", obdm_est["obdm"].round(3)) mfobdm = scipy.linalg.block_diag(*mfobdm) print("mf obdm", mfobdm.round(3)) max_abs_err = np.max(np.abs(obdm_est["obdm"] - mfobdm)) assert max_abs_err < 0.05, "max abs err {0}".format(max_abs_err) print(obdm_est["obdm_up"].diagonal().round(3)) print(obdm_est["obdm_down"].diagonal().round(3)) mae = np.mean(np.abs(obdm_est["obdm_up"] + obdm_est["obdm_down"] - mfobdm)) maup = np.mean(np.abs(obdm_est["obdm_up"])) madn = np.mean(np.abs(obdm_est["obdm_down"])) mamf = np.mean(np.abs(mfobdm)) assert mae < 0.05, "mae {0}\n maup {1}\n madn {2}\n mamf {3}".format( mae, maup, madn, mamf)
def test(): """ Ensure that DMC obtains the exact result for a hydrogen atom """ from pyscf import gto, scf from pyqmc.jastrowspin import JastrowSpin from pyqmc.dmc import limdrift, rundmc from pyqmc.mc import vmc from pyqmc.accumulators import EnergyAccumulator from pyqmc.func3d import CutoffCuspFunction from pyqmc.multiplywf import MultiplyWF from pyqmc.coord import OpenConfigs from pyqmc import Slater import pandas as pd mol = gto.M(atom="H 0. 0. 0.", basis="sto-3g", unit="bohr", spin=1) mf = scf.UHF(mol).run() nconf = 1000 configs = OpenConfigs(np.random.randn(nconf, 1, 3)) wf1 = Slater(mol, mf) wf = wf1 wf2 = JastrowSpin(mol, a_basis=[CutoffCuspFunction(5, 0.2)], b_basis=[]) wf2.parameters["acoeff"] = np.asarray([[[1.0, 0]]]) wf = MultiplyWF(wf1, wf2) dfvmc, configs_ = vmc(wf, configs, nsteps=50, accumulators={"energy": EnergyAccumulator(mol)}) dfvmc = pd.DataFrame(dfvmc) print( "vmc energy", np.mean(dfvmc["energytotal"]), np.std(dfvmc["energytotal"]) / np.sqrt(len(dfvmc)), ) warmup = 200 branchtime = 5 dfdmc, configs_, weights_ = rundmc( wf, configs, nsteps=4000 + warmup * branchtime, branchtime=branchtime, accumulators={"energy": EnergyAccumulator(mol)}, ekey=("energy", "total"), tstep=0.01, drift_limiter=limdrift, verbose=True, ) dfdmc = pd.DataFrame(dfdmc) dfdmc.sort_values("step", inplace=True) dfprod = dfdmc[dfdmc.step >= warmup] rb_summary = reblock.reblock_summary(dfprod[["energytotal", "energyei"]], 20) print(rb_summary) energy, err = [ rb_summary[v]["energytotal"] for v in ("mean", "standard error") ] assert (np.abs(energy + 0.5) < 5 * err), "energy not within {0} of -0.5: energy {1}".format( 5 * err, np.mean(energy))