def test_manual_slater(H2_ccecp_rhf, epsilon=1e-5): mol, mf = H2_ccecp_rhf determinants = [(1.0, [[0], [0]]), (-0.2, [[1], [1]])] wf = Slater(mol, mf, determinants=determinants) configs = pyq.initial_guess(mol, 10) run_tests(wf, configs, epsilon)
def test_pbc_wfs(H_pbc_sto3g_krks, epsilon=1e-5, nconf=10): """ Ensure that the wave function objects are consistent in several situations. """ mol, mf = H_pbc_sto3g_krks supercell = pyq.get_supercell(mol, S=(np.ones((3, 3)) - 2 * np.eye(3))) epos = pyq.initial_guess(supercell, nconf) for wf in [ MultiplyWF(Slater(supercell, mf), generate_jastrow(supercell)[0]), Slater(supercell, mf), ]: for k in wf.parameters: if "mo_coeff" not in k and k != "det_coeff": wf.parameters[k] = cp.asarray( np.random.rand(*wf.parameters[k].shape)) _, epos = pyq.vmc(wf, epos, nblocks=1, nsteps=2, tstep=1) # move off node run_tests(wf, epos, epsilon)
def test_superpose_wf(H2_casci, coeffs=[1 / np.sqrt(2), 1 / np.sqrt(2)], epsilon=1e-5, nconf=10): """ This test makes sure that the superposewf passes all the wftests, when adding two casci wave functions. """ mol, mf, mc = H2_casci ci0, ci1 = mc.ci[0], mc.ci[1] mc.ci = ci0 wf0 = Slater(mol, mf, mc, tol=0.0) mc.ci = ci1 wf1 = Slater(mol, mf, mc, tol=0.0) wfs = [wf0, wf1] wf = AddWF(coeffs, wfs) configs = pyq.initial_guess(mol, nconf) run_tests(wf, configs, epsilon)
def test_pbc(li_cubic_ccecp): from pyqmc import supercell import scipy mol, mf = li_cubic_ccecp # S = np.ones((3, 3)) - np.eye(3) S = np.identity(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 = 500 nsteps = 100 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) 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) mfobdm = scipy.linalg.block_diag(*mfobdm) mae = np.mean(np.abs(obdm_est["obdm"] - mfobdm)) assert mae < 0.05, f"mae {mae}"
def test_obc_wfs(LiH_sto3g_rhf, epsilon=1e-5, nconf=10): """ Ensure that the wave function objects are consistent in several situations. """ mol, mf = LiH_sto3g_rhf for wf in [ generate_jastrow(mol)[0], J3(mol), MultiplyWF(Slater(mol, mf), generate_jastrow(mol)[0]), MultiplyWF(Slater(mol, mf), generate_jastrow(mol)[0], J3(mol)), Slater(mol, mf), ]: for k in wf.parameters: if k != "mo_coeff": wf.parameters[k] = cp.asarray( np.random.rand(*wf.parameters[k].shape)) epos = pyq.initial_guess(mol, nconf) run_tests(wf, epos, epsilon)
def test_shci_wf_is_better(H2_ccecp_hci): mol, mf, cisolver = H2_ccecp_hci configs = pyq.initial_guess(mol, 1000) wf = Slater(mol, mf, cisolver, tol=0.0) data, configs = pyq.vmc( wf, configs, nblocks=40, verbose=True, accumulators={"energy": pyq.EnergyAccumulator(mol)}, ) en, err = avg(data["energytotal"][1:]) nsigma = 4 assert len(wf.parameters["det_coeff"]) == len(cisolver.ci) assert en - nsigma * err < mf.e_tot assert en + nsigma * err > cisolver.energy
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) assert np.mean( np.abs(obdm_est["obdm_up"] + obdm_est["obdm_down"] - mfobdm)) < 0.05
def runtest(mol, mf, kind=0): kpt = mf.kpts[kind] 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 ##################################### wf = Slater(mol, mf) coords = pyq.initial_guess(mol, 1200, 0.7) warmup = 10 start = time.time() df, coords = pyq.vmc( wf, coords, nsteps=100 + warmup, tstep=1, accumulators={"energy": pyq.EnergyAccumulator(mol)}, verbose=False, hdf_file=str(uuid.uuid4()), ) print("VMC time", time.time() - start) df = pd.DataFrame(df) dfke = pyq.avg_reblock(df["energyke"][warmup:], 10) 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_accumulator(C2_ccecp_rhf): """Tests that the accumulator gets inserted into the data output correctly.""" mol, mf = C2_ccecp_rhf nconf = 500 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["energyke"][29] == np.average(eaccum_energy["ke"])) assert df["energyke"][29] == np.average(eaccum_energy["ke"])
def test_manual_pbcs_fail(H_pbc_sto3g_krks, epsilon=1e-5, nconf=10): """ This test makes sure that the number of k-points must match the number of k-points in the mf object. """ mol, mf = H_pbc_sto3g_krks supercell = np.identity(3, dtype=int) supercell[0, 0] = 2 mol = pyq.get_supercell(mol, supercell) try: determinants = [ (1.0, [[0, 1], [0, 1]], [[0, 1], [0, 1]]), # first determinant (-0.2, [[0, 2], [0, 1]], [[0, 2], [0, 1]]), # second determinant ] wf = Slater(mol, mf, determinants=determinants) raise Exception("Should have failed here") except: pass
def test_manual_pbcs_correct(H_pbc_sto3g_kuks, epsilon=1e-5, nconf=10): """ This test makes sure that the number of k-points must match the number of k-points in the mf object. """ from pyqmc.determinant_tools import create_pbc_determinant mol, mf = H_pbc_sto3g_kuks supercell = np.identity(3, dtype=int) supercell[0, 0] = 2 mol = pyq.get_supercell(mol, supercell) determinants = [ (1.0, create_pbc_determinant(mol, mf, [])), (-0.2, create_pbc_determinant(mol, mf, [(0, 0, 0, 0, 1)])), ] wf = Slater(mol, mf, determinants=determinants) configs = pyq.initial_guess(mol, 10) run_tests(wf, configs, epsilon)
def test_casci_energy(H2_ccecp_casci_s0): """ Checks that VMC energy matches energy calculated in PySCF """ nsteps = 200 warmup = 10 mol, mf, mc = H2_ccecp_casci_s0 wf = Slater(mol, mf, mc) nconf = 1000 coords = pyq.initial_guess(mol, nconf) df, coords = pyq.vmc( wf, coords, nsteps=nsteps, accumulators={"energy": EnergyAccumulator(mol)} ) df = pd.DataFrame(df) df = pyq.avg_reblock(df["energytotal"][warmup:], 20) en = df.mean() err = df.sem() assert en - mc.e_tot < 5 * err
def default_multislater(mol, mf, mc, tol=None, optimize_orbitals=False, optimize_zeros=True, epsilon=1e-8): import numpy as np wf = Slater(mol, mf, mc, tol) to_opt = ["det_coeff"] to_opt = { "det_coeff": np.ones(wf.parameters["det_coeff"].shape).astype(bool) } to_opt["det_coeff"][0] = False # Determinant coefficient pivot if optimize_orbitals: for k in ["mo_coeff_alpha", "mo_coeff_beta"]: to_opt[k] = np.ones(wf.parameters[k].shape).astype(bool) if not optimize_zeros: to_opt[k][np.abs(wf.parameters[k]) < epsilon] = False return wf, to_opt
def test_ecp_sj(C2_ccecp_rhf, nconf=10000): """test whether the cutoff saves us time without changing the energy too much. Because it's a stochastic evaluation, random choices can make a big difference, so we only require 10% agreement between these two.""" mol, mf = C2_ccecp_rhf THRESHOLDS = [1e15, 10] np.random.seed(1234) coords = initial_guess(mol, nconf) wf = MultiplyWF(Slater(mol, mf), generate_jastrow(mol)[0]) wf.recompute(coords) times = [] energies = [] for threshold in THRESHOLDS: np.random.seed(1234) eacc = EnergyAccumulator(mol, threshold) start = time.time() energy = eacc(coords, wf) end = time.time() times.append(end - start) energies.append(np.mean(energy["total"])) # print(times, energies) assert times[1] < times[0] assert (energies[1] - energies[0]) / energies[0] < 0.1
def default_slater(mol, mf, optimize_orbitals=False, twist=None, optimize_zeros=True, epsilon=1e-8): """ Construct a Slater determinant Args: optimize_orbitals (bool): make to_opt true for orbital parameters twist (vector): The twist to extract from the mean-field object optimize_zeros (bool): optimize coefficients that are zero in the mean-field object Returns: slater, to_opt """ wf = Slater(mol, mf, twist=twist) to_opt = {} if optimize_orbitals: for k in ["mo_coeff_alpha", "mo_coeff_beta"]: to_opt[k] = np.ones(wf.parameters[k].shape).astype(bool) if not optimize_zeros: to_opt[k][np.abs(wf.parameters[k]) < epsilon] = False return wf, to_opt
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_vmc(C2_ccecp_rhf): """ Test that a VMC calculation of a Slater determinant matches Hartree-Fock within error bars. """ mol, mf = C2_ccecp_rhf nconf = 500 nsteps = 300 warmup = 30 wf = Slater(mol, mf) 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_rohf(C_ccecp_rohf, epsilon=1e-5): mol, mf = C_ccecp_rohf configs = pyq.initial_guess(mol, 10) wf = Slater(mol, mf) run_tests(wf, configs, epsilon)
def test_casci_s2(H2_ccecp_casci_s2, epsilon=1e-5): mol, mf, cisolver = H2_ccecp_casci_s2 configs = pyq.initial_guess(mol, 10) wf = Slater(mol, mf, cisolver, tol=0.0) run_tests(wf, configs, epsilon)
def runtest(mol, mf, kind=0): kpt = mf.kpts[kind] twist = np.dot(kpt, mol.lattice_vectors().T / (2 * np.pi)) wf0 = Slater(mol, mf) wft = Slater(mol, mf, twist=twist) ##################################### ## compare values across boundary ## psi, KE, ecp, ##################################### nconfig = 50 coords = pyq.initial_guess(mol, nconfig, 1) epos, wrap = enforce_pbc(coords.lvecs, coords.configs) coords = PeriodicConfigs(epos, coords.lvecs) shift_ = np.random.randint(10, size=coords.configs.shape) - 5 phase = np.exp(2j * np.pi * np.einsum("ijk,k->ij", shift_, twist)) shift = np.dot(shift_, mol.lattice_vectors()) epos, wrap = enforce_pbc(coords.lvecs, epos + shift) newcoords = PeriodicConfigs(epos, coords.lvecs, wrap=wrap) assert np.linalg.norm(newcoords.configs - coords.configs) < 1e-12 ph0, val0 = wf0.recompute(coords) pht, valt = wft.recompute(coords) enacc = pyq.EnergyAccumulator(mol, threshold=np.inf) np.random.seed(0) en0 = enacc(coords, wf0) np.random.seed(0) ent = enacc(coords, wft) e = 0 rat0 = wf0.testvalue(e, newcoords.electron(e)) assert np.linalg.norm(rat0 - 1) < 1e-9, rat0 - 1 ratt = wft.testvalue(e, newcoords.electron(e)) rattdiff = ratt - phase[:, e] print("phase", phase[:, e]) assert np.linalg.norm(rattdiff) < 1e-9, [ np.round(rattdiff, 10), np.amax(np.abs(rattdiff)), ] ph0new, val0new = wf0.recompute(newcoords) phtnew, valtnew = wft.recompute(newcoords) np.random.seed(0) en0new = enacc(newcoords, wf0) np.random.seed(0) entnew = enacc(newcoords, wft) assert np.linalg.norm(ph0 - ph0new) < 1e-11 assert np.linalg.norm(pht * phase.prod(axis=1) - phtnew) < 1e-11, ( pht * phase.prod(axis=1) - phtnew) assert np.linalg.norm(val0 - val0new) < 1e-11, np.linalg.norm(val0 - val0new) assert np.linalg.norm(valt - valtnew) < 1e-11, np.linalg.norm(valt - valtnew) for k in en0.keys(): diff0 = en0[k] - en0new[k] difft = ent[k] - entnew[k] if k == "ecp": for l, diff in [("0", diff0), ("t", difft)]: mad = np.mean(np.abs(diff)) if True: # mad > 1e-12: print("ecp%s diff" % l, mad, np.linalg.norm(diff)) assert mad < 1e-3, diff else: assert np.mean(np.abs(diff0)) < 1e-6, diff0 assert np.mean(np.abs(difft)) < 1e-6, difft