def test_accumulator(): """ Tests that the accumulator gets inserted into the data output correctly. """ import pandas as pd from pyqmc.mc import vmc, initial_guess from pyscf import gto, scf from pyqmc.energy import energy from pyqmc.slateruhf import PySCFSlaterUHF from pyqmc.accumulators import EnergyAccumulator 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 = PySCFSlaterUHF(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(): """ Ensure that DMC obtains the exact result for a hydrogen atom """ from pyscf import lib, gto, scf from pyqmc.slater import PySCFSlater 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 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 = PySCFSlater(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))
def test(): """ Ensure that DMC obtains the exact result for a hydrogen atom """ from pyscf import lib, gto, scf from pyqmc.slateruhf import PySCFSlaterUHF from pyqmc.jastrowspin import JastrowSpin from pyqmc.dmc import limdrift, dmc from pyqmc.mc import vmc from pyqmc.accumulators import EnergyAccumulator from pyqmc.func3d import ExpCuspFunction from pyqmc.multiplywf import MultiplyWF 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 = np.random.randn(nconf, 1, 3) wf1 = PySCFSlaterUHF(mol, mf) wf = wf1 wf2 = JastrowSpin(mol, a_basis=[ExpCuspFunction(5, .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))) dfdmc, configs_, weights_ = dmc( wf, configs, nsteps=5000, branchtime=5, 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) warmup = 200 dfprod = dfdmc[dfdmc.step > warmup] reblock = pyblock.reblock(dfprod[['energytotal', 'energyei']]) print(reblock[1]) dfoptimal = reblock[1][reblock[1][('energytotal', 'optimal block')] != ''] energy = dfoptimal[('energytotal', 'mean')].values[0] err = dfoptimal[('energytotal', 'standard error')].values[0] print("energy", energy, "+/-", err) assert np.abs( energy + 0.5) < 5 * err, "energy not within {0} of -0.5: energy {1}".format( 5 * err, np.mean(energy))
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 [ (PySCFSlater(mol, mf_rhf), mf_rhf), (PySCFSlater(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(): from pyscf import lib, gto, scf from pyqmc.slater import PySCFSlaterRHF from pyqmc.accumulators import EnergyAccumulator import pandas as pd mol = gto.M(atom='Li 0. 0. 0.; Li 0. 0. 1.5', basis='cc-pvtz', unit='bohr', verbose=5) #mol = gto.M(atom='C 0. 0. 0.', ecp='bfd', basis='bfd_vtz') mf = scf.RHF(mol).run() #import pyscf2qwalk #pyscf2qwalk.print_qwalk(mol,mf) nconf = 5000 wf = PySCFSlaterRHF(mol, mf) coords = initial_guess(mol, nconf) import time tstart = time.process_time() df, coords = vmc(wf, coords, nsteps=100, accumulators={'energy': EnergyAccumulator(mol)}) tend = time.process_time() print("VMC took", tend - tstart, "seconds") df = pd.DataFrame(df) df.to_csv("data.csv") warmup = 30 print('mean field', mf.energy_tot(), 'vmc estimation', np.mean(df['energytotal'][warmup:]), np.std(df['energytotal'][warmup:]))
def test_single_opt(): from pyqmc.accumulators import EnergyAccumulator from pyscf import lib, gto, scf import pandas as pd from pyqmc.multiplywf import MultiplyWF from pyqmc.jastrow import Jastrow2B from pyqmc.func3d import GaussianFunction from pyqmc.slater import PySCFSlaterRHF from pyqmc.multiplywf import MultiplyWF from pyqmc.jastrow import Jastrow2B from pyqmc.mc import initial_guess,vmc mol = gto.M(atom='Li 0. 0. 0.; Li 0. 0. 1.5', basis='bfd_vtz',ecp='bfd',unit='bohr',verbose=5) mf = scf.RHF(mol).run() nconf=1000 nsteps=10 coords = initial_guess(mol,nconf) wf=MultiplyWF(PySCFSlaterRHF(mol,mf),Jastrow2B(mol, basis=[GaussianFunction(1.0),GaussianFunction(2.0)])) vmc(wf,coords,nsteps=nsteps) opt_var,wf=optvariance(EnergyAccumulator(mol),wf,coords,['wf2coeff']) print('Final variance:',opt_var)
def eval_configs(data, cutoffs): """ Evaluate values using the regularization we have constructed """ mol, wf, to_opt, freeze = wavefunction() eacc = EnergyAccumulator(mol) transform = LinearTransform(wf.parameters, to_opt, freeze) print("data loaded") r2 = data['distance_squared'] weight = data['weight_total'] d = {} for cutoff in list(cutoffs): node_cut = r2 < cutoff**2 print(cutoff, node_cut.sum()) c = 7. / (cutoff**6) b = -15. / (cutoff**4) a = 9. / (cutoff**2) l2 = r2[node_cut] dpH = np.copy(data['dpH']) dpH[node_cut] *= a * l2 + b * l2**2 + c * l2**3 hist, bin_edges = np.histogram(np.log10(np.abs(dpH)[np.abs(dpH) > 0]), bins=200, density=True, weights=weight[np.abs(dpH) > 0]) d['hist' + str(cutoff)] = list(np.log10(hist)) + [None] d['bins' + str(cutoff)] = bin_edges df = pd.DataFrame(d) df.to_pickle('histogram.pickle')
def test_vmc(): """ Test that a VMC calculation of a Slater determinant matches Hartree-Fock within error bars. """ nconf = 5000 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 = 100 warmup = 30 for wf, mf in [ (PySCFSlaterUHF(mol, mf_rhf), mf_rhf), (PySCFSlaterUHF(mol, mf_uhf), mf_uhf), ]: coords = initial_guess(mol, nconf) df, coords = vmc(wf, coords, nsteps=nsteps, accumulators={"energy": EnergyAccumulator(mol)}) df = pd.DataFrame(df) en = np.mean(df["energytotal"][warmup:]) err = np.std(df["energytotal"][warmup:]) / np.sqrt(nsteps - warmup) assert en - mf.energy_tot() < 10 * err
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(): 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 obdm_steps = 4 warmup = 15 wf = PySCFSlaterUHF(mol, mf) configs = initial_guess(mol, nconf) energy = EnergyAccumulator(mol) obdm = OBDMAccumulator(mol=mol, orb_coeff=lowdin, nsweeps=1) obdm_up = OBDMAccumulator(mol=mol, orb_coeff=lowdin, nsweeps=1, spin=0) obdm_down = OBDMAccumulator(mol=mol, orb_coeff=lowdin, nsweeps=1, spin=1) df, coords = vmc( wf, configs, nsteps=nsteps, accumulators={ "energy": energy, "obdm": obdm, "obdm_up": obdm_up, "obdm_down": obdm_down, }, ) df = DataFrame(df) obdm_est = {} for k in ["obdm", "obdm_up", "obdm_down"]: avg_norm = np.array(df.loc[warmup:, k + "norm"].values.tolist()).mean(axis=0) avg_obdm = np.array(df.loc[warmup:, k + "value"].values.tolist()).mean(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_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_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 [ PySCFSlaterUHF(mol, mf), JastrowSpin(mol), MultiplyWF(PySCFSlaterUHF(mol, mf), JastrowSpin(mol)) ]: 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 [MultiSlater(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 viznode(node_coords, node_grad, cutoffs, vizfile='viznode.pdf'): from wavefunction import wavefunction mol, wf, to_opt, freeze = wavefunction() eacc = EnergyAccumulator(mol) transform = LinearTransform(wf.parameters, to_opt, freeze) #Generate the distances we want x = np.arange(np.sqrt(1 / 0.01), 1001) x = 1. / x**2 x = np.append(x, np.linspace(0.01, 0.12, 100)) x = np.append(x, np.array([0, 1e-15, 1e-12, 1e-8] + [-y for y in x])) x = np.sort(x) coord_path = np.einsum('ij,l->lij', node_grad[0], x) + node_coords[0] coord_path = OpenConfigs(coord_path) #Move across the node in this path val = wf.recompute(coord_path) fig, ax = plt.subplots(nrows=2, ncols=1, figsize=(3, 6), sharex=True) for k, cutoff in enumerate([1e-8] + cutoffs): pgrad = PGradTransform_new(eacc, transform, nodal_cutoff=np.array([cutoff])) d = pgrad(coord_path, wf) total = d['total'] dpH = np.array(d['dpH'])[:, 0, 0] if (cutoff == 1e-8): ax[0].plot(x, dpH * (val[0] * np.exp(val[1]))**2, 'k-', label=r'$10^{' + str(int(np.log10(cutoff))) + '}$') ax[1].plot(x, np.log10(dpH**2 * (val[0] * np.exp(val[1]))**2), 'k-') else: ax[0].plot(x, dpH * (val[0] * np.exp(val[1]))**2, '-', label=r'$10^{' + str(int(np.log10(cutoff))) + '}$') ax[1].plot(x, np.log10(dpH**2 * (val[0] * np.exp(val[1]))**2), '-') ax[0].set_ylabel(r'$E_L\frac{\partial_p \Psi}{\Psi} f_\epsilon |\Psi|^2$') ax[1].set_ylabel( r'log$_{10}((E_L\frac{\partial_p \Psi}{\Psi})^2 f_\epsilon^2|\Psi|^2)$' ) ax[1].set_xlabel(r'$l$ (Bohr)') ax[0].set_xlim((-max(x) - 0.02, max(x) + 0.02)) ax[1].set_xlim((-max(x) - 0.02, max(x) + 0.02)) ax[0].legend(loc='best', title=r'$\epsilon$ (Bohr)') plt.savefig(vizfile, bbox_inches='tight') plt.close()
def test_ecp(): mol = gto.M(atom='C 0. 0. 0.', ecp='bfd', basis='bfd_vtz') mf = scf.RHF(mol).run() nconf=5000 wf=PySCFSlaterUHF(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_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 collectconfigs(n, dump_file): """ Collect all the configurations from genconfig into a single place """ dpH_total = [] weight_total = [] logweight_total = [] distance_squared = [] mol, wf, to_opt, freeze = wavefunction() eacc = EnergyAccumulator(mol) transform = LinearTransform(wf.parameters, to_opt, freeze) pgrad_bare = PGradTransform_new(eacc, transform, 1e-20) for i in range(1, n + 1): print(i) coords = OpenConfigs(pd.read_pickle('vmc/coords' + str(i) + '.pickle')) df = pd.read_json('vmc/evals' + str(i) + '.json') wf.recompute(coords) print("Recomputed") node_cut, r2 = pgrad_bare._node_cut(coords, wf) print("nodes cut") dpH = df['dpH'].values wfval = df['wfval'].values wfpval = df['wfpval'].values logweight = 2 * (wfval - wfpval) weight = np.exp(logweight) print(i, weight[weight == 0]) dpH_total += list(dpH) weight_total += list(weight) logweight_total += list(logweight) distance_squared += list(r2) print(i, np.array(weight_total)[np.array(weight_total) == 0]) df = pd.DataFrame({ 'dpH': dpH_total, 'weight_total': weight_total, 'logweight_total': logweight_total, 'distance_squared': distance_squared }) df.to_pickle(dump_file) return df
def genconfigs(n): """ Generate configurations and weights corresponding to the highest determinant in MD expansion """ import os os.system('mkdir -p vmc/') mol, mf, mc, wf, to_opt, freeze = wavefunction(return_mf=True) #Sample from the wave function which we're taking pderiv relative to mf.mo_coeff = mc.mo_coeff mf.mo_occ *= 0 mf.mo_occ[wf.wf1._det_occup[0][-1]] = 2 wfp = PySCFSlaterUHF(mol, mf) #Lots of configurations coords = pyqmc.initial_guess(mol, 100000) eacc = EnergyAccumulator(mol) transform = LinearTransform(wf.parameters, to_opt, freeze) pgrad_bare = PGradTransform(eacc, transform, 0) #Lots of steps warmup = 10 for i in range(n + warmup + 1): df, coords = vmc(wfp, coords, nsteps=1) print(i) if (i > warmup): coords.configs.dump('vmc/coords' + str(i - warmup) + '.pickle') val = wf.recompute(coords) valp = wfp.value() d = pgrad_bare(coords, wf) data = { 'dpH': np.array(d['dpH'])[:, -1], 'dppsi': np.array(d['dppsi'])[:, -1], 'en': np.array(d['total']), "wfval": val[1], "wfpval": valp[1] } pd.DataFrame(data).to_json('vmc/evals' + str(i - warmup) + '.json') return -1
def test(): from pyscf import lib, gto, scf from pyqmc.accumulators import EnergyAccumulator, PGradTransform, LinearTransform from pyqmc.multiplywf import MultiplyWF from pyqmc.jastrow import Jastrow2B from pyqmc.func3d import GaussianFunction from pyqmc.slater import PySCFSlaterRHF from pyqmc.mc import initial_guess mol = gto.M(atom='H 0. 0. 0.; H 0. 0. 1.5', basis='cc-pvtz', unit='bohr', verbose=5) mf = scf.RHF(mol).run() nconf = 2500 nsteps = 70 warmup = 20 coords = initial_guess(mol, nconf) basis = { 'wf2coeff': [GaussianFunction(0.2), GaussianFunction(0.4), GaussianFunction(0.6)] } wf = MultiplyWF(PySCFSlaterRHF(mol, mf), Jastrow2B(mol, basis['wf2coeff'])) params0 = {'wf2coeff': np.array([-0.8, -0.2, 0.4])} for k, p in wf.parameters.items(): if k in params0: wf.parameters[k] = params0[k] energy_acc = EnergyAccumulator(mol) pgrad_acc = PGradTransform(energy_acc, LinearTransform(wf.parameters)) # Gradient descent wf, data = gradient_descent(wf, coords, pgrad_acc, vmcoptions={'nsteps': nsteps}, warmup=warmup, step=0.5, eps=0.1, maxiters=50, datafile='sropt.json')
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 sweepelectron(): """ Sweep an electron across the molecule to find a guess for the nodal position """ import copy from pyqmc.accumulators import EnergyAccumulator, LinearTransform, PGradTransform #Generate wave function and bare parameter gradient objects mol, wf, to_opt, freeze = wavefunction() eacc = EnergyAccumulator(mol) transform = LinearTransform(wf.parameters, to_opt, freeze) pgrad = PGradTransform(eacc, transform, 1e-20) #Initial coords configs = pyqmc.initial_guess(mol, 1).configs[:,:,:] #Sweep electron 0 full_df = None e = 3 #electron dim = 1 #Coordinate to vary for i in np.linspace(0, 20, 200): new_configs = copy.deepcopy(configs) new_configs[:,e,dim] += i shifted_configs = OpenConfigs(new_configs) wfval = wf.recompute(shifted_configs) d = pgrad(shifted_configs, wf) small_df = pd.DataFrame({ 'ke':[d['ke'][0]], 'total':[d['total'][0]], 'dppsi':[d['dppsi'][0][0]], 'dpH' :[d['dpH'][0][0]], 'wfval':[wfval[0][0]*np.exp(wfval[1][0])], 'ycoord': i, 'configs':[copy.deepcopy(new_configs)], }) if(full_df is None): full_df = small_df else: full_df = pd.concat((full_df, small_df), axis=0) return full_df.reset_index()
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 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_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 integratenode(node_coords, node_grad, vizfile='integratenode.pdf', integ_range=1e-1, poly=1e-2, max_cutoff=0.1): from wavefunction import wavefunction import scipy.integrate as integrate from numpy.polynomial import polynomial mol, wf, to_opt, freeze = wavefunction() eacc = EnergyAccumulator(mol) transform = LinearTransform(wf.parameters, to_opt, freeze) pgrad_bare = PGradTransform(eacc, transform, 1e-15) #Integrate biases and variances biases = [] biases_err = [] variances = [] cutoffs = list(np.logspace(-6, -1, 20)) + [0.05, 0.075] ''' normalization = integrate.quad(lambda x: psi2(x, node_coords, node_grad, wf), -integ_range, integ_range, epsabs = 1e-15, epsrel = 1e-15) for cutoff in cutoffs: print(cutoff) pgrad = PGradTransform_new(eacc, transform, nodal_cutoff = np.array([cutoff])) bias = integrate.quad(lambda x: dpH(x, pgrad, pgrad_bare, node_coords, node_grad, wf)/1e-40, -cutoff, cutoff, epsabs = 1e-15, epsrel = 1e-15, points=[0]) variance = integrate.quad(lambda x: dpH2(x, pgrad, node_coords, node_grad, wf), -cutoff, cutoff, epsabs = 1e-15, epsrel = 1e-15, points=[0]) variance += integrate.quad(lambda x: dpH2(x, pgrad, node_coords, node_grad, wf), -integ_range + cutoff, integ_range - cutoff, epsabs = 1e-15, epsrel = 1e-15) biases.append(bias[0]*1e-40/normalization[0]) variances.append(variance[0]/normalization[0]) df = pd.DataFrame({'cutoff': cutoffs, 'bias': biases, 'variance': variances}) df.to_pickle('integratenode.pickle') ''' df = pd.read_pickle('integratenode.pickle') #Fit theory curves and visualize ind = np.argsort(df['cutoff']) ind = ind[df['cutoff'].iloc[ind] <= max_cutoff] fig, ax = plt.subplots(nrows=2, ncols=1, figsize=(3, 6), sharex=True) x = df['cutoff'].iloc[ind] y = np.abs(df['bias']).iloc[ind] y = y[2:] x = x[2:] p = polynomial.polyfit(x, y, [3]) print("Fit for bias ", p) xfit = np.linspace(min(x), max(x[x < poly]), 1000) fit = p[3] * (xfit)**3 ax[0].plot(np.log10(x), np.log10(y), 'o') ax[0].plot(np.log10(xfit), np.log10(fit), '--') ax[0].set_ylabel(r'log$_{10}$(Bias)') x = df['cutoff'].iloc[ind] y = df['variance'].iloc[ind] y = y[2:] x = x[2:] x = np.log10(x) y = np.log10(y) poly = np.log10(poly) p = polynomial.polyfit(x[x < poly], y[x < poly], [1, 0]) print("Fit for variance ", p) xfit = np.logspace(min(x), max(x[x <= poly]), 1000) fit = p[0] + p[1] * np.log10(xfit) ax[1].plot(x, y, 'o') ax[1].plot(np.log10(xfit), fit, '--') ax[1].set_xlabel(r'$log_{10}(\epsilon/$Bohr$)$') ax[1].set_ylabel(r'log$_{10}$(Variance)') #ax[1].set_xlim((-3.2, 2.3)) #ax[1].set_xticks(np.arange(-3,3)) plt.savefig(vizfile, bbox_inches='tight') plt.close()
def gradient_generator(mol, wf, to_opt=None, **ewald_kwargs): return PGradTransform(EnergyAccumulator(mol, **ewald_kwargs), LinearTransform(wf.parameters, to_opt))
def gradient_generator(mol, wf, to_opt=None, freeze=None): return PGradTransform(EnergyAccumulator(mol), LinearTransform(wf.parameters, to_opt, freeze))
def setuph2(r, obdm_steps=5): from pyscf import gto, scf, lo from pyqmc.accumulators import LinearTransform, EnergyAccumulator from pyqmc.obdm import OBDMAccumulator from pyqmc.cvmc import DescriptorFromOBDM, PGradDescriptor import itertools # ccECP from A. Annaberdiyev et al. Journal of Chemical Physics 149, 134108 (2018) basis = { "H": gto.basis.parse(""" H S 23.843185 0.00411490 10.212443 0.01046440 4.374164 0.02801110 1.873529 0.07588620 0.802465 0.18210620 0.343709 0.34852140 0.147217 0.37823130 0.063055 0.11642410 """) } """ H S 0.040680 1.00000000 H S 0.139013 1.00000000 H P 0.166430 1.00000000 H P 0.740212 1.00000000 """ ecp = { "H": gto.basis.parse_ecp(""" H nelec 0 H ul 1 21.24359508259891 1.00000000000000 3 21.24359508259891 21.24359508259891 2 21.77696655044365 -10.85192405303825 """) } mol = gto.M(atom=f"H 0. 0. 0.; H 0. 0. {r}", unit="bohr", basis=basis, ecp=ecp, verbose=5) mf = scf.RHF(mol).run() mo_occ = mf.mo_coeff[:, mf.mo_occ > 0] a = lo.iao.iao(mol, mo_occ) a = lo.vec_lowdin(a, mf.get_ovlp()) obdm_up = OBDMAccumulator(mol=mol, orb_coeff=a, nstep=obdm_steps, spin=0) obdm_down = OBDMAccumulator(mol=mol, orb_coeff=a, nstep=obdm_steps, spin=1) wf = pyqmc.slater_jastrow(mol, mf) freeze = {} for k in wf.parameters: freeze[k] = np.zeros(wf.parameters[k].shape, dtype='bool') print(freeze.keys()) print(wf.parameters['wf1mo_coeff_alpha']) #this freezing allows us to easily go between bonding and # AFM configurations. freeze['wf1mo_coeff_alpha'][0, 0] = True freeze['wf1mo_coeff_beta'][1, 0] = True descriptors = { "t": [[(1.0, (0, 1)), (1.0, (1, 0))], [(1.0, (0, 1)), (1.0, (1, 0))]], "trace": [[(1.0, (0, 0)), (1.0, (1, 1))], [(1.0, (0, 0)), (1.0, (1, 1))]], } for i in [0, 1]: descriptors[f"nup{i}"] = [[(1.0, (i, i))], []] descriptors[f"ndown{i}"] = [[], [(1.0, (i, i))]] acc = PGradDescriptor( EnergyAccumulator(mol), LinearTransform(wf.parameters, freeze=freeze), [obdm_up, obdm_down], DescriptorFromOBDM(descriptors, norm=2.0), ) return { "wf": wf, "acc": acc, "mol": mol, "mf": mf, "descriptors": descriptors }
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 = PySCFSlater(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 = {} tbdm_est = {} 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) for k in avg_tbdm: tbdm_est[k] = normalize_tbdm( avg_tbdm[k].reshape(2, 2, 2, 2), avg_norm["a"], avg_norm["b"] ) 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('QMC tbdm[%d,%d]:\n'%(sa,sb),qmctbdm[sa,sb]) # print('MF tbdm[%d,%d]:\n'%(sa,sb),mftbdm[sa,sb]) diff = qmctbdm[sa, sb] - mftbdm[sa, sb] print("diff[%d,%d]:\n" % (sa, sb), diff) assert np.max(np.abs(diff)) < 0.05
from wavefunction import wavefunction if __name__ == '__main__': nconfig_per_core = 100 ncore = 20 nsteps = 2000000 cutoffs = list(np.logspace(-8, -1, 20)) + list([ 0.05, 0.075, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20 ]) cutoffs = np.sort(cutoffs) mol, mf, mc, wf, to_opt, freeze = wavefunction(return_mf=True) wf.parameters['wf1det_coeff'] *= 0 wf.parameters['wf1det_coeff'][[0, 10]] = 1. / np.sqrt(2.) eacc = EnergyAccumulator(mol) transform = LinearTransform(wf.parameters, to_opt, freeze) pgrad = PGradTransform_new(eacc, transform, np.array(cutoffs)) #Client cluster = LocalCluster(n_workers=ncore, threads_per_worker=1) client = Client(cluster) distvmc(wf, pyqmc.initial_guess(mol, nconfig_per_core * ncore), client=client, accumulators={"pgrad": pgrad}, nsteps_per=100, nsteps=nsteps, hdf_file='dedp_vmc_local.hdf5')
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