def test_transform(): """ Just prints things out; TODO: figure out a thing to test. """ from pyscf import gto, scf r = 1.54 / 0.529177 mol = gto.M( atom="H 0. 0. 0.; H 0. 0. %g" % r, ecp="bfd", basis="bfd_vtz", unit="bohr", verbose=1, ) mf = scf.RHF(mol).run() wf, to_opt = pyqmc.default_sj(mol, mf) enacc = pyqmc.EnergyAccumulator(mol) print(list(wf.parameters.keys())) transform = LinearTransform(wf.parameters) x = transform.serialize_parameters(wf.parameters) nconfig = 10 configs = pyqmc.initial_guess(mol, nconfig) wf.recompute(configs) pgrad = wf.pgradient() gradtrans = transform.serialize_gradients(pgrad) assert gradtrans.shape[1] == len(x) assert gradtrans.shape[0] == nconfig
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 test_transform(): """ Just prints things out; TODO: figure out a thing to test. """ from pyscf import gto, scf import pyqmc r = 1.54 / .529177 mol = gto.M(atom='H 0. 0. 0.; H 0. 0. %g' % r, ecp='bfd', basis='bfd_vtz', unit='bohr', verbose=1) mf = scf.RHF(mol).run() wf = pyqmc.slater_jastrow(mol, mf) enacc = pyqmc.EnergyAccumulator(mol) print(list(wf.parameters.keys())) transform = LinearTransform(wf.parameters) x = transform.serialize_parameters(wf.parameters) nconfig = 10 configs = pyqmc.initial_guess(mol, nconfig) wf.recompute(configs) pgrad = wf.pgradient() gradtrans = transform.serialize_gradients(pgrad) assert gradtrans.shape[1] == len(x) assert gradtrans.shape[0] == nconfig
def test_constraints(H2_ccecp_casci_s0): mol, mf, mc = H2_ccecp_casci_s0 wf, to_opt = pyq.generate_wf(mol, mf, mc=mc) old_parms = copy.deepcopy(wf.parameters) lt = LinearTransform(wf.parameters, to_opt) # Test serialize parameters x0 = lt.serialize_parameters(wf.parameters) x0 += np.random.normal(size=x0.shape) for k, it in lt.deserialize(wf, x0).items(): assert wf.parameters[k].shape == it.shape wf.parameters[k] = it # to_opt is supposed to be false for both of these. assert wf.parameters["wf1det_coeff"][0] == old_parms["wf1det_coeff"][0] assert np.sum(wf.parameters["wf2bcoeff"][0] - old_parms["wf2bcoeff"][0]) == 0 # While this one is supposed to change. assert np.sum(wf.parameters["wf2bcoeff"][1] - old_parms["wf2bcoeff"][1]) != 0 # Test serialize gradients configs = pyq.initial_guess(mol, 10) wf.recompute(configs) pgrad = wf.pgradient() pgrad_serial = lt.serialize_gradients(pgrad) # Pgrad should be walkers, configs assert pgrad_serial.shape[1] == x0.shape[0]
def test_transform(LiH_sto3g_rhf): """Tests that the shapes are ok""" mol, mf = LiH_sto3g_rhf wf, to_opt = pyq.generate_wf(mol, mf) transform = LinearTransform(wf.parameters) x = transform.serialize_parameters(wf.parameters) nconfig = 10 configs = pyq.initial_guess(mol, nconfig) wf.recompute(configs) pgrad = wf.pgradient() gradtrans = transform.serialize_gradients(pgrad) assert gradtrans.shape[1] == len(x) assert gradtrans.shape[0] == nconfig
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 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 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 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 gradient_generator(mol, wf, to_opt=None, **ewald_kwargs): return PGradTransform(EnergyAccumulator(mol, **ewald_kwargs), LinearTransform(wf.parameters, to_opt))
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 }
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 gradient_generator(mol, wf, to_opt=None, freeze=None): return PGradTransform(EnergyAccumulator(mol), LinearTransform(wf.parameters, to_opt, freeze))
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 test(): import parsl from pyscf import lib, gto, scf import numpy as np import pandas as pd import logging from parsl.config import Config from parsl.providers import LocalProvider from parsl.channels import LocalChannel from parsl.launchers import SimpleLauncher from parsl.executors import ExtremeScaleExecutor ncore = 4 config = Config( executors=[ ExtremeScaleExecutor(label="Extreme_Local", worker_debug=True, ranks_per_node=ncore, provider=LocalProvider( channel=LocalChannel(), init_blocks=1, max_blocks=1, launcher=SimpleLauncher())) ], strategy=None, ) parsl.load(config) mol = gto.M(atom='H 0. 0. 0.; H 0. 0. 2.0', unit='bohr', ecp='bfd', basis='bfd_vtz') mf = scf.RHF(mol).run() mol.output = None mol.stdout = None mf.output = None mf.stdout = None mf.chkfile = None from pyqmc import ExpCuspFunction, GaussianFunction, MultiplyWF, PySCFSlaterRHF, JastrowSpin, initial_guess, EnergyAccumulator from pyqmc.accumulators import PGradTransform, LinearTransform nconf = 1600 basis = [ ExpCuspFunction(2.0, 1.5), GaussianFunction(0.5), GaussianFunction(2.0), GaussianFunction(.25), GaussianFunction(1.0), GaussianFunction(4.0), GaussianFunction(8.0) ] wf = MultiplyWF(PySCFSlaterRHF(mol, mf), JastrowSpin(mol, basis, basis)) coords = initial_guess(mol, nconf) energy_acc = EnergyAccumulator(mol) pgrad_acc = PGradTransform( energy_acc, LinearTransform(wf.parameters, ['wf2acoeff', 'wf2bcoeff'])) from pyqmc.optsr import gradient_descent gradient_descent(wf, coords, pgrad_acc, vmc=distvmc, vmcoptions={ 'npartitions': ncore, 'nsteps': 100, 'nsteps_per': 100 })