def __init__( self, mol, orb_coeff, nstep=10, tstep=0.50, warmup=100, naux=500, spin=None, electrons=None, ): assert ( len(orb_coeff.shape) == 2 ), "orb_coeff should be a list of orbital coefficients." if not (spin is None): if spin == 0: self._electrons = np.arange(0, mol.nelec[0]) elif spin == 1: self._electrons = np.arange(mol.nelec[0], np.sum(mol.nelec)) else: raise ValueError("Spin not equal to 0 or 1") elif not (electrons is None): self._electrons = electrons else: self._electrons = np.arange(0, np.sum(mol.nelec)) self._orb_coeff = orb_coeff self._tstep = tstep self._mol = mol # self._extra_config = np.random.normal(scale=tstep,size=3) # not zero to avoid sitting on top of atom. nelec = sum(self._mol.nelec) self._extra_config = initial_guess(mol, int(naux / nelec) + 1).configs.reshape( -1, 3 ) self._nstep = nstep for i in range(warmup): accept, self._extra_config = sample_onebody( mol, orb_coeff, self._extra_config, tstep )
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 __init__( self, mol, orb_coeff, nsweeps=5, tstep=0.50, warmup=100, naux=500, spin=None, electrons=None, ): assert (len(orb_coeff.shape) == 2 ), "orb_coeff should be a list of orbital coefficients." if not (spin is None): if spin == 0: self._electrons = np.arange(0, mol.nelec[0]) elif spin == 1: self._electrons = np.arange(mol.nelec[0], np.sum(mol.nelec)) else: raise ValueError("Spin not equal to 0 or 1") elif not (electrons is None): self._electrons = electrons else: self._electrons = np.arange(0, np.sum(mol.nelec)) self._orb_coeff = orb_coeff self._tstep = tstep self._mol = mol nelec = len(self._electrons) self._extra_config = initial_guess(mol, int(naux / nelec) + 1).configs.reshape(-1, 3) self._nsweeps = nsweeps self._nstep = nsweeps * nelec for i in range(warmup): accept, self._extra_config = sample_onebody( mol, orb_coeff, self._extra_config, tstep)
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 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_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_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(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
def __init__( self, mol, orb_coeff, spin, nsweeps=4, tstep=0.50, warmup=200, naux=500, ijkl=None, ): assert ( len(orb_coeff.shape) == 3 ), "orb_coeff should be a list of orbital coefficients with size (2,num_mobasis,num_orb)." self._mol = mol self._orb_coeff = orb_coeff self._tstep = tstep self._nsweeps = nsweeps self._spin = spin self._spin_sector = spin self._electrons_a = np.arange( spin[0] * mol.nelec[0], mol.nelec[0] + spin[0] * mol.nelec[1] ) self._electrons_b = np.arange( spin[1] * mol.nelec[0], mol.nelec[0] + spin[1] * mol.nelec[1] ) self._pairs = np.array( np.meshgrid(self._electrons_a, self._electrons_b) ).T.reshape(-1, 2) self._pairs = self._pairs[ self._pairs[:, 0] != self._pairs[:, 1] ] # Removes repeated electron pairs # Initialization and warmup of aux_configs_a self._aux_configs_a = initial_guess( mol, int(naux / sum(self._mol.nelec)) ).configs.reshape(-1, 3) for i in range(warmup): accept_a, self._aux_configs_a = sample_onebody( mol, orb_coeff[self._spin_sector[0]], self._aux_configs_a, tstep ) # Initialization and warmup of aux_configs_b self._aux_configs_b = initial_guess( mol, int(naux / sum(self._mol.nelec)) ).configs.reshape(-1, 3) for i in range(warmup): accept_b, self._aux_configs_b = sample_onebody( mol, orb_coeff[self._spin_sector[1]], self._aux_configs_b, tstep ) # Default to full 2rdm if ijkl not specified if ijkl is None: norb_up = orb_coeff[0].shape[1] norb_down = orb_coeff[1].shape[1] ijkl = [ [i, j, k, l] for i in range(norb_up) for j in range(norb_up) for k in range(norb_down) for l in range(norb_down) ] self._ijkl = np.array(ijkl).T
def test_pbc(): from pyscf.pbc import gto, scf from pyqmc import PySCFSlaterUHF, PySCFSlaterPBC from pyqmc import slaterpbc import scipy lvecs = (np.ones((3, 3)) - 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)) - 2 * np.eye(3) mol = slaterpbc.get_supercell(mol, S) kpts = slaterpbc.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 = PySCFSlaterPBC(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, ) 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"].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(): """ 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
def __init__( self, mol, orb_coeff, nsweeps=5, tstep=0.50, warmup=100, naux=500, spin=None, electrons=None, kpts=None, ): if spin is not None: if spin == 0: self._electrons = np.arange(0, mol.nelec[0]) elif spin == 1: self._electrons = np.arange(mol.nelec[0], np.sum(mol.nelec)) else: raise ValueError("Spin not equal to 0 or 1") elif electrons is not None: self._electrons = electrons else: self._electrons = np.arange(0, np.sum(mol.nelec)) self.iscomplex = bool(sum(map(np.iscomplexobj, orb_coeff))) if hasattr(mol, "lattice_vectors"): assert kpts is not None assert len(orb_coeff) == len(kpts) self.iscomplex = self.iscomplex or np.linalg.norm(kpts) > 1e-12 self._kpts = kpts self.evaluate_orbitals = self._evaluate_orbitals_pbc if self.iscomplex: self.get_wrapphase = slater.get_wrapphase_complex else: self.get_wrapphase = slater.get_wrapphase_real for attribute in ["original_cell", "S"]: if not hasattr(mol, attribute): from pyqmc.supercell import get_supercell mol = get_supercell(mol, np.eye(3)) self.supercell = mol self._mol = mol.original_cell else: self._mol = mol self.evaluate_orbitals = self._evaluate_orbitals assert (len(orb_coeff.shape) == 2 ), "orb_coeff should be a list of orbital coefficients." self._orb_coeff = orb_coeff if hasattr(self._orb_coeff, "shape"): self.norb = self._orb_coeff.shape[1] else: self.norb = sum(c.shape[1] for c in self._orb_coeff) self._tstep = tstep self.nelec = len(self._electrons) self._nsweeps = nsweeps self._nstep = nsweeps * self.nelec self._extra_config = initial_guess(mol, int(naux / self.nelec) + 1) self._extra_config.reshape((-1, 3)) accept, extra_configs = self.sample_onebody(self._extra_config, warmup) self._extra_config = extra_configs[-1]
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, nstep=obdm_steps) obdm_up = OBDMAccumulator(mol=mol, orb_coeff=lowdin, nstep=obdm_steps, spin=0) obdm_down = OBDMAccumulator(mol=mol, orb_coeff=lowdin, nstep=obdm_steps, 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.max( np.abs(obdm_est["obdm_up"] + obdm_est["obdm_down"] - mfobdm)) < 0.05
def test(): from pyscf import gto, scf, lo from numpy.linalg import solve from pyqmc.slater import PySCFSlaterRHF from pyqmc.mc import initial_guess, vmc from pyqmc.accumulators import EnergyAccumulator from pandas import DataFrame ### Generate some basic objects. # Simple Li2 run. 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) #print(mfobdm.diagonal().round(2)) ### Test one-body sampler. #test_sample_onebody(mol,lowdin,mf,nsample=int(1e4)) #test_sample_onebody(mol,lowdin,mf,nsample=int(4e4)) #test_sample_onebody(mol,lowdin,mf,nsample=int(1e5)) ### Test OBDM calculation. nconf = 500 nsteps = 400 obdm_steps = 2 warmup = 15 wf = PySCFSlaterRHF(mol, mf) configs = initial_guess(mol, nconf) energy = EnergyAccumulator(mol) obdm = OBDMAccumulator(mol=mol, orb_coeff=mf.mo_coeff, nstep=obdm_steps) df, coords = vmc(wf, configs, nsteps=nsteps, accumulators={ 'energy': energy, 'obdm': obdm }) df = DataFrame(df) df['obdm'] = df[['obdmvalue','obdmnorm']]\ .apply(lambda x:normalize_obdm(x['obdmvalue'],x['obdmnorm']),axis=1) print(df[['obdmvalue', 'obdmnorm', 'obdm']].applymap(lambda x: x.ravel()[0])) avg_norm = np.array(df.loc[warmup:, 'obdmnorm'].values.tolist()).mean(axis=0) avg_obdm = np.array(df.loc[warmup:, 'obdm'].values.tolist()).mean(axis=0) std_obdm = np.array( df.loc[warmup:, 'obdm'].values.tolist()).std(axis=0) / nsteps**0.5 print("Average norm(orb)", avg_norm) print("Average OBDM(orb,orb)", avg_obdm.diagonal().round(3)) print("OBDM error (orb,orb)", std_obdm.diagonal().round( 3)) # Note this needs reblocking to be accurate. print("AO occupation", mfobdm[0, 0]) print('mean field', mf.energy_tot(), 'vmc estimation', np.mean(df['energytotal'][warmup:]), np.std(df['energytotal'][warmup:]))
def test_pbc(h_noncubic_sto3g): # from pyscf.pbc import gto, scf from pyqmc import supercell import scipy mol, mf = h_noncubic_sto3g # 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}"