def update_all(self): """ update all relevant attributes given that electron has been updated """ #k is in reciprocal coord and r is in crystal coord #but since this is cubic you just need a factor of 2pi kr_up = np.matmul(self.k[:self.N], self.electron.up.transpose()) kr_dn = np.matmul(self.k[:self.N], self.electron.dn.transpose()) kr_up *= 2*np.pi kr_dn *= 2*np.pi self.slater_up = np.exp(1j*kr_up) self.slater_dn = np.exp(1j*kr_dn) #update inverses self.inverse_up = np.linalg.inv(self.slater_up) self.inverse_dn = np.linalg.inv(self.slater_dn) #update u kvecs = (2*np.pi/self.L)*self.k[1:] self.u_lr_uu = pbc.ewald_lr(self.L*self.electron.uu_table,\ self.kappa, kvecs, self.supercell.volume) self.u_lr_dd = pbc.ewald_lr(self.L*self.electron.dd_table,\ self.kappa, kvecs, self.supercell.volume) self.u_lr_ud = pbc.ewald_lr(self.L*self.electron.ud_table,\ self.kappa, kvecs, self.supercell.volume) r_uu = np.linalg.norm(self.electron.uu_table, axis=-1) r_dd = np.linalg.norm(self.electron.dd_table, axis=-1) r_ud = np.linalg.norm(self.electron.ud_table, axis=-1) r_uu[np.diag_indices(self.N)] = np.inf r_dd[np.diag_indices(self.N)] = np.inf self.u_sr_uu = pbc.ewald_sr(self.kappa, r_uu*self.L) self.u_sr_dd = pbc.ewald_sr(self.kappa, r_dd*self.L) self.u_sr_ud = pbc.ewald_sr(self.kappa, r_ud*self.L) self.u_exp_uu = u_exp(r_uu*self.L, self.F_uu) self.u_exp_dd = u_exp(r_dd*self.L, self.F_uu) self.u_exp_ud = u_exp(r_ud*self.L, self.F_ud)
def update_u_dn(self, i): """ update u tables associated with down electron i """ kvecs = (2*np.pi/self.L)*self.k[1:] vol = self.supercell.volume lr_dd = pbc.ewald_lr(self.electron.dd_table[i]*self.L,\ self.kappa, kvecs, vol) lr_ud = pbc.ewald_lr(self.electron.ud_table[:,i]*self.L,\ self.kappa, kvecs, vol) self.u_lr_dd[i,:] = np.copy(lr_dd) #ewald_lr is an even function of r, so no minus sign self.u_lr_dd[:,i] = np.copy(lr_dd) self.u_lr_ud[:,i] = np.copy(lr_ud) #first index is for up electron, not updated here r_dd = np.linalg.norm(self.electron.dd_table[i], axis=-1) r_ud = np.linalg.norm(self.electron.ud_table[:,i], axis=-1) r_dd[i] = np.inf sr_dd = pbc.ewald_sr(self.kappa, r_dd*self.L) sr_ud = pbc.ewald_sr(self.kappa, r_ud*self.L) self.u_sr_dd[i,:] = np.copy(sr_dd) self.u_sr_dd[:,i] = np.copy(sr_dd) self.u_sr_ud[:,i] = np.copy(sr_ud) exp_dd = u_exp(r_dd*self.L, self.F_uu) exp_ud = u_exp(r_ud*self.L, self.F_ud) self.u_exp_dd[i,:] = np.copy(exp_dd) self.u_exp_dd[:,i] = np.copy(exp_dd) self.u_exp_ud[:,i] = np.copy(exp_ud)
def test_laplacian_ewald_lr(): L = 5*np.random.rand() v = L*np.eye(3) supercell = pbc.cell(v[0], v[1], v[2]) volume = supercell.volume kvecs = supercell.kvecs(3)[1:,:3] kvecs *= 2*np.pi/L kappa = 5/L r = L*np.random.rand(3) #compute derivatives f = pbc.ewald_lr(r, kappa, kvecs, volume) #h = 0 h = 0.00001 #finite difference step lap = 0 for i in range(3): r[i] += h f_fwd = pbc.ewald_lr(r, kappa, kvecs, volume) r[i] -= 2*h f_bwd = pbc.ewald_lr(r, kappa, kvecs, volume) r[i] += h #restore original r lap += (f_fwd + f_bwd - 2*f) / h**2 assert np.isclose(lap, pbc.laplacian_ewald_lr(r, kappa, kvecs, volume),\ rtol=1e-2)
def test_grad_ewald_lr(): L = 5*np.random.rand() v = L*np.eye(3) supercell = pbc.cell(v[0], v[1], v[2]) volume = supercell.volume kvecs = supercell.kvecs(3)[1:,:3] kvecs *= 2*np.pi/L kappa = 5/L r = L*np.random.rand(3) #compute derivatives f = pbc.ewald_lr(r, kappa, kvecs, volume) #h = 0 h = 0.00001 #finite difference step grad = np.zeros(3) for i in range(3): r[i] += h fwd = pbc.ewald_lr(r, kappa, kvecs, volume) r[i] -= 2*h bwd = pbc.ewald_lr(r, kappa, kvecs, volume) r[i] += h grad[i] = (fwd - bwd) / (2*h) assert np.isclose(grad, pbc.grad_ewald_lr(r, kappa, kvecs, volume),\ rtol=1e-2).all()
def test_ewald_lr(): """ test ewald_lr, which performs the sum over k with matmul against a manual sum over k """ #make supercell L = 5*np.random.rand() v = L*np.eye(3) supercell = pbc.cell(v[0], v[1], v[2]) volume = supercell.volume kvecs = supercell.kvecs(3)[1:,:3] kvecs *= 2*np.pi/L kappa = 5/L r = L*np.random.rand(17, 3) u = np.zeros(17) for n in range(17): for k in kvecs: ksq = np.dot(k, k) kr = np.dot(k, r[n]) u[n] += np.cos(kr)*np.exp(-ksq / (4*kappa**2)) / ksq u *= 4*np.pi/volume assert np.isclose(pbc.ewald_lr(r, kappa, kvecs, volume), u).all()