def test_enforce_pbcs(): # TEST 1: Check if any electron in new config # is out of the simulation box for set # of non-orthogonal lattice vectors. We # do a controlled comparison between # initial configs and final ones. nconf = 7 lattvecs = np.array([[1.2, 0, 0], [0.6, 1.2 * np.sqrt(3) / 2, 0], [0, 0, 0.8]]) # Triangular lattice trans = np.array([[0.1, 0.1, 0.1], [1.3, 0, 0.2], [0.9, 1.8 * np.sqrt(3) / 2, 0], [0, 0, 1.1], [2.34, 1.35099963, 0], [0.48, 1.24707658, 0], [-2.52, 2.28630707, -0.32]]) check_final = np.array([[0.1, 0.1, 0.1], [0.1, 0, 0.2], [0.3, 0.6 * np.sqrt(3) / 2, 0.], [0, 0, 0.3], [0.54, 0.31176915, 0], [1.08, 0.2078461, 0], [1.08, 0.2078461, 0.48]]) check_wrap = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 0], [-1, 1, 0], [-4, 2, -1]]) final_trans, final_wrap = enforce_pbc(lattvecs, trans) # Checks output configs relative_tol = 1e-8 absolute_tol = 1e-8 test1a = np.all( np.isclose(final_trans, check_final, rtol=relative_tol, atol=absolute_tol)) # Checks wraparound matrix test1b = np.all( np.isclose(final_wrap, check_wrap, rtol=relative_tol, atol=absolute_tol)) test1 = test1a * test1b print('Test 1 success:', test1) # TEST 2: Check if any electron in new config # is out of the simulation box for set # of non-orthogonal lattice vectors. nconf = 50 lattvecs = np.array([[1.2, 0, 0], [0.6, 1.2 * np.sqrt(3) / 2, 0], [0, 0, 0.8]]) # Triangular lattice recpvecs = np.linalg.inv(lattvecs) # Old config epos = np.random.random((nconf, 3)) epos = np.einsum('ij,jk->ik', epos, lattvecs) # New config step = 0.5 trans = epos + step * (np.random.random((nconf, 3)) - 0.5 * np.ones( (nconf, 3))) final_trans, wrap = enforce_pbc(lattvecs, trans) # Configs in lattice vectors basis ff = np.einsum('ij,jk->ik', final_trans, recpvecs) test2 = np.all(ff < 1) & np.all(ff >= 0) print('Test 2 success:', test2) assert (test1 * test2)
def aos(self, eval_str, configs, mask=None): """ Returns an ndarray in order [k,..., orbital] of the ao's if value is requested if a derivative is requested, will instead return [k,d,...,orbital]. The ... is the total length of mycoords. You'll need to reshape if you want the original shape """ mycoords = configs.configs if mask is None else configs.configs[mask] mycoords = mycoords.reshape((-1, mycoords.shape[-1])) primcoords, primwrap = pbc.enforce_pbc(self.Lprim, mycoords) # coordinate, dimension wrap = configs.wrap if mask is None else configs.wrap[mask] wrap = np.dot(wrap, self.S) wrap = wrap.reshape((-1, wrap.shape[-1])) + primwrap kdotR = np.linalg.multi_dot( (self._kpts, self._cell.lattice_vectors().T, wrap.T)) # k, coordinate wrap_phase = get_wrapphase_complex(kdotR) # k,coordinate, orbital ao = gpu.cp.asarray( self._cell.eval_gto( "PBC" + eval_str, primcoords, kpts=self._kpts, )) ao = gpu.cp.einsum("k...,k...a->k...a", wrap_phase, ao) if len(ao.shape) == 4: # if derivatives are included return ao.reshape( (ao.shape[0], ao.shape[1], *mycoords.shape[:-1], ao.shape[-1])) else: return ao.reshape( (ao.shape[0], *mycoords.shape[:-1], ao.shape[-1]))
def test_compare_enforcements(): import time nconf = 500000 lattvecs = np.array([[1, -0.75, 0], [0.5, 2 / 3., 0], [0, 0, 2]]) epos0 = np.random.random((nconf, 3)) epos0 = np.einsum('ij,jk->ik', epos0, lattvecs) # Using enforce_pbc_orth() t1 = time.time() epos = epos0.copy() final_epos_o, wrap_o = enforce_pbc_orth(lattvecs, epos) t2 = time.time() # Using enforce_pbc() epos = epos0.copy() final_epos_no, wrap_no = enforce_pbc(lattvecs, epos) t3 = time.time() relative_tol = 1e-8 absolute_tol = 1e-8 test1 = np.all( np.isclose(final_epos_o, final_epos_no, rtol=relative_tol, atol=absolute_tol)) test2 = np.all( np.isclose(wrap_o, wrap_no, rtol=relative_tol, atol=absolute_tol)) print('Same result for enforce_pbc_orth() and enforce_pbc()?', test1 * test2) print('time[enforce_pbc_orth()] = %f' % (t2 - t1)) print('time[enforce_pbc()] = %f' % (t3 - t2)) assert (test1 * test2)
def __init__(self, configs, lattice_vectors, wrap=None): configs, wrap_ = enforce_pbc(lattice_vectors, configs) self.configs = configs self.wrap = wrap_ if wrap is not None: self.wrap += wrap self.lvecs = lattice_vectors self.dist = MinimalImageDistance(lattice_vectors)
def make_irreducible(self, e, vec): """ Input: a (nconfig, 3) vector Output: a tuple with the wrapped vector and the number of wraps """ epos, wrap = enforce_pbc(self.lvecs, vec) currentwrap = self.wrap if len(self.wrap.shape) == 2 else self.wrap[:, e] if len(vec.shape) == 3: currentwrap = currentwrap[:, np.newaxis] return PeriodicConfigs(epos, self.lvecs, wrap=wrap + currentwrap)
def _evaluate_orbitals_pbc(self, configs): # wrap supercell positions into primitive cell lvecs = self._mol.lattice_vectors() prim_coords, prim_wrap = pbc.enforce_pbc(lvecs, configs.configs) wrap = prim_wrap + np.dot(configs.wrap, self.supercell.S) wrap = wrap.reshape(-1, 3) prim_coords = prim_coords.reshape(-1, 3) kdotR = np.linalg.multi_dot((self._kpts, lvecs.T, wrap.T)) wrap_phase = self.get_wrapphase(kdotR) # evaluate AOs for all electron positions ao = self._mol.eval_gto("PBCGTOval_sph", prim_coords, kpts=self._kpts) ao = [aok * wrap_phase[k][:, np.newaxis] for k, aok in enumerate(ao)] borb = [aok.dot(ock) for aok, ock in zip(ao, self._orb_coeff)] return np.concatenate(borb, axis=1)
def test_enforce_pbcs(): # TEST 1: Check if any electron in new config # is out of the simulation box for set # of non-orthogonal lattice vectors. We # do a controlled comparison between # initial configs and final ones. nconf = 7 lattvecs = np.array([[1.2, 0, 0], [0.6, 1.2 * np.sqrt(3) / 2, 0], [0, 0, 0.8]]) # Triangular lattice trans = (np.array([ [0.1, 0.1, 0.1], [1.3, 0, 0.2], [0.9, 1.8 * np.sqrt(3) / 2, 0], [0, 0, 1.1], [2.34, 1.35099963, 0], [0.48, 1.24707658, 0], [-2.52, 2.28630707, -0.32], ]) + 1e-14) check_final = (np.array([ [0.1, 0.1, 0.1], [0.1, 0, 0.2], [0.3, 0.6 * np.sqrt(3) / 2, 0.0], [0, 0, 0.3], [0.54, 0.31176915, 0], [1.08, 0.2078461, 0], [1.08, 0.2078461, 0.48], ]) + 1e-14) check_wrap = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 0], [-1, 1, 0], [-4, 2, -1]]) final_trans, final_wrap = enforce_pbc(lattvecs, trans) # Checks output configs relative_tol = 1e-8 absolute_tol = 1e-8 test1a = np.all( np.isclose(final_trans, check_final, rtol=relative_tol, atol=absolute_tol)) # Checks wraparound matrix test1b = np.all( np.isclose(final_wrap, check_wrap, rtol=relative_tol, atol=absolute_tol)) test1 = test1a * test1b assert test1
def make_irreducible(self, e, vec, mask=None): """ Input: a (nconfig, 3) vector or a (nconfig, N, 3) vector Output: A Periodic Electron """ if mask is None: mask = np.ones(vec.shape[0:-1], dtype=bool) epos_, wrap_ = pbc.enforce_pbc(self.lvecs, vec[mask]) epos = vec.copy() epos[mask] = epos_ wrap = self.wrap[:, e, :].copy() if len(vec.shape) == 3: wrap = np.repeat(self.wrap[:, e][:, np.newaxis], vec.shape[1], axis=1) wrap[mask] += wrap_ return PeriodicElectron(epos, self.lvecs, wrap=wrap, dist=self.dist)
def evaluate_orbitals(self, configs, mask=None, eval_str="PBCGTOval_sph"): mycoords = configs.configs if mask is not None: mycoords = mycoords[mask] mycoords = mycoords.reshape((-1, mycoords.shape[-1])) # wrap supercell positions into primitive cell prim_coords, prim_wrap = pbc.enforce_pbc(self._cell.lattice_vectors(), mycoords) configswrap = configs.wrap.reshape(prim_wrap.shape) wrap = prim_wrap + np.dot(configswrap, self.supercell.S) kdotR = np.linalg.multi_dot( (self._kpts, self._cell.lattice_vectors().T, wrap.T)) wrap_phase = np.exp(1j * kdotR) # evaluate AOs for all electron positions ao = self._cell.eval_gto(eval_str, prim_coords, kpts=self._kpts) ao = [ao[k] * wrap_phase[k][:, np.newaxis] for k in range(self.nk)] return ao
def test_non_orthogonal(): # TEST 2: Check if any electron in new config # is out of the simulation box for set # of non-orthogonal lattice vectors. nconf = 50 lattvecs = np.array([[1.2, 0, 0], [0.6, 1.2 * np.sqrt(3) / 2, 0], [0, 0, 0.8]]) # Triangular lattice recpvecs = np.linalg.inv(lattvecs) # Old config epos = np.random.random((nconf, 3)) epos = np.einsum("ij,jk->ik", epos, lattvecs) # New config step = 0.5 trans = epos + step * (np.random.random((nconf, 3)) - 0.5 * np.ones( (nconf, 3))) final_trans, wrap = enforce_pbc(lattvecs, trans) # Configs in lattice vectors basis ff = np.einsum("ij,jk->ik", final_trans, recpvecs) test2 = np.all(ff < 1) & np.all(ff >= 0) assert test2
def runtest(mol, mf, kind=0): for k, occ in enumerate(mf.mo_occ): print(k, occ) kpt = mf.kpts[kind] twist = np.dot(kpt, mol.lattice_vectors().T / (2 * np.pi)) print("kpt", kpt) print("twist", twist) wf0 = pyqmc.PySCFSlaterPBC(mol, mf) wft = pyqmc.PySCFSlaterPBC(mol, mf, twist=twist) ##################################### ## compare values across boundary ## psi, KE, ecp, ##################################### nconfig = 100 coords = pyqmc.initial_guess(mol, nconfig, 1) nelec = coords.configs.shape[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 = pyqmc.accumulators.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-10, rat0 - 1 ratt = wft.testvalue(e, newcoords.electron(e)) rattdiff = ratt - 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(): print(k) 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.linalg.norm(diff0) < 1e-10, diff0 assert np.linalg.norm(difft) < 1e-10, difft