def test(xc, tol=5e-10): N_c = np.array([10, 6, 4]) # This test is totally serial. gd = GridDescriptor(N_c, N_c * 0.2, pbc_c=(1, 0, 1), comm=world.new_communicator([world.rank])) actual_n = N_c - (1 - gd.pbc_c) gen = np.random.RandomState(17) n_sg = gd.zeros(2) n_sg[:] = gen.rand(*n_sg.shape) #sigma_xg = gd.zeros(3) #sigma_xg[:] = gen.random.rand(*sigma_xg.shape) if hasattr(xc, 'libvdwxc'): xc._nspins = 2 xc.initialize_backend(gd) v_sg = gd.zeros(2) E = xc.calculate(gd, n_sg, v_sg) print('E', E) dn = 1e-6 all_indices = itertools.product(range(2), range(1, actual_n[0], 2), range(0, actual_n[1], 2), range(0, actual_n[2], 2)) for testindex in all_indices: n1_sg = n_sg.copy() n2_sg = n_sg.copy() v = v_sg[testindex] * gd.dv n1_sg[testindex] -= dn n2_sg[testindex] += dn E1 = xc.calculate(gd, n1_sg, v_sg.copy()) E2 = xc.calculate(gd, n2_sg, v_sg.copy()) dedn = 0.5 * (E2 - E1) / dn err = abs(dedn - v) print('{}{} v={} fd={} err={}'.format(xc.name, list(testindex), v, dedn, err)) assert err < tol, err
def f(n, p): N = 2 * n gd = GridDescriptor((N, N, N), (L, L, L)) a = gd.zeros() print(a.shape) #p = PoissonSolver(nn=1, relax=relax) p.set_grid_descriptor(gd) cut = N / 2.0 * 0.9 s = Spline(l=0, rmax=cut, f_g=np.array([1, 0.5, 0.0])) c = LFC(gd, [[s], [s]]) c.set_positions([(0, 0, 0), (0.5, 0.5, 0.5)]) c.add(a) I0 = gd.integrate(a) a -= I0 / L**3 b = gd.zeros() p.solve(b, a, charge=0, eps=1e-20) return gd.collect(b, broadcast=1)
def __init__(self, gd, spline_j, spos_c, index=None): rcut = max([spline.get_cutoff() for spline in spline_j]) corner_c = np.ceil(spos_c * gd.N_c - rcut / gd.h_c).astype(int) size_c = np.ceil(spos_c * gd.N_c + rcut / gd.h_c).astype(int) - corner_c smallgd = GridDescriptor(N_c=size_c + 1, cell_cv=gd.h_c * (size_c + 1), pbc_c=False, comm=mpi.serial_comm) lfc = LFC(smallgd, [spline_j]) lfc.set_positions((spos_c[np.newaxis, :] * gd.N_c - corner_c + 1) / smallgd.N_c) ni = lfc.Mmax f_iG = smallgd.zeros(ni) lfc.add(f_iG, {0: np.eye(ni)}) LocalizedFunctions.__init__(self, gd, f_iG, corner_c, index=index)
def f(n, p): N = 2 * n gd = GridDescriptor((N, N, N), (L, L, L)) a = gd.zeros() print(a.shape) #p = PoissonSolver(nn=1, relax=relax) p.set_grid_descriptor(gd) p.initialize() cut = N / 2.0 * 0.9 s = Spline(l=0, rmax=cut, f_g=np.array([1, 0.5, 0.0])) c = LFC(gd, [[s], [s]]) c.set_positions([(0, 0, 0), (0.5, 0.5, 0.5)]) c.add(a) I0 = gd.integrate(a) a -= gd.integrate(a) / L**3 I = gd.integrate(a) b = gd.zeros() p.solve(b, a, charge=0)#, eps=1e-20) return gd.collect(b, broadcast=1)
def main(): from gpaw.grid_descriptor import GridDescriptor from gpaw.mpi import world serial = world.new_communicator([world.rank]) # Generator which must run on all ranks gen = np.random.RandomState(0) # This one is just used by master gen_serial = np.random.RandomState(17) maxsize = 5 for i in range(1): N1_c = gen.randint(1, maxsize, 3) N2_c = gen.randint(1, maxsize, 3) gd1 = GridDescriptor(N1_c, N1_c) gd2 = GridDescriptor(N2_c, N2_c) serial_gd1 = gd1.new_descriptor(comm=serial) serial_gd2 = gd2.new_descriptor(comm=serial) a1_serial = serial_gd1.empty() a1_serial.flat[:] = gen_serial.rand(a1_serial.size) if world.rank == 0: print('r0: a1 serial', a1_serial.ravel()) a1 = gd1.empty() a1[:] = -1 grid2grid(world, serial_gd1, gd1, a1_serial, a1) print(world.rank, 'a1 distributed', a1.ravel()) world.barrier() a2 = gd2.zeros() a2[:] = -2 grid2grid(world, gd1, gd2, a1, a2) print(world.rank, 'a2 distributed', a2.ravel()) world.barrier() #grid2grid(world, gd2, gd2_serial gd1 = GridDescriptor(N1_c, N1_c * 0.2) #serialgd = gd2.new_descriptor( a1 = gd1.empty() a1.flat[:] = gen.rand(a1.size) #print a1 grid2grid(world, gd1, gd2, a1, a2)
def interpolate_2d(mat): from gpaw.grid_descriptor import GridDescriptor from gpaw.transformers import Transformer nn = 10 N_c = np.zeros([3], dtype=int) N_c[1:] = mat.shape[:2] N_c[0] = nn bmat = np.resize(mat, N_c) gd = GridDescriptor(N_c, N_c) finegd = GridDescriptor(N_c * 2, N_c) interpolator = Transformer(gd, finegd, 3) fine_bmat = finegd.zeros() interpolator.apply(bmat, fine_bmat) return fine_bmat[0]
def make_dummy_kpt_reference(l, function, k_c, rcut=6., a=10., n=60, dtype=complex): r = np.linspace(0., rcut, 300) mcount = 2*l + 1 fcount = 1 kcount = 1 gd = GridDescriptor((n, n, n), (a, a, a), (True, True, True)) kpt = KPoint([], gd, 1., 0, 0, 0, k_c, dtype) spline = Spline(l, r[-1], function(r)) center = (.5, .5, .5) lf = create_localized_functions([spline], gd, center, dtype=dtype) lf.set_phase_factors([kpt.k_c]) psit_nG = gd.zeros(mcount, dtype=dtype) coef_xi = np.identity(mcount * fcount, dtype=dtype) lf.add(psit_nG, coef_xi, k=0) kpt.psit_nG = psit_nG print 'Number of boxes', len(lf.box_b) print 'Phase kb factors shape', lf.phase_kb.shape return gd, kpt, center
def test(): from gpaw.grid_descriptor import GridDescriptor ngpts = 40 h = 1 / ngpts N_c = (ngpts, ngpts, ngpts) a = h * ngpts gd = GridDescriptor(N_c, (a, a, a)) from gpaw.spline import Spline a = np.array([1, 0.9, 0.8, 0.0]) s = Spline(0, 0.2, a) x = LocalizedFunctionsCollection(gd, [[s], [s]]) x.set_positions([(0.5, 0.45, 0.5), (0.5, 0.55, 0.5)]) n_G = gd.zeros() x.add(n_G) import pylab as plt plt.contourf(n_G[20, :, :]) plt.axis('equal') plt.show()
def test(): from gpaw.grid_descriptor import GridDescriptor ngpts = 40 h = 1.0 / ngpts N_c = (ngpts, ngpts, ngpts) a = h * ngpts gd = GridDescriptor(N_c, (a, a, a)) from gpaw.spline import Spline a = np.array([1, 0.9, 0.8, 0.0]) s = Spline(0, 0.2, a) x = LocalizedFunctionsCollection(gd, [[s], [s]]) x.set_positions([(0.5, 0.45, 0.5), (0.5, 0.55, 0.5)]) n_G = gd.zeros() x.add(n_G) import pylab as plt plt.contourf(n_G[20, :, :]) plt.axis('equal') plt.show()
def make_dummy_reference(l, function=None, rcut=6., a=12., n=60, dtype=float): """Make a mock reference wave function using a made-up radial function as reference""" #print 'Dummy reference: l=%d, rcut=%.02f, alpha=%.02f' % (l, rcut, alpha) r = np.arange(0., rcut, .01) if function is None: function = QuasiGaussian(4., rcut) norm = get_norm(r, function(r), l) function.renormalize(norm) #g = QuasiGaussian(alpha, rcut) mcount = 2 * l + 1 fcount = 1 gd = GridDescriptor((n, n, n), (a, a, a), (False, False, False)) spline = Spline(l, r[-1], function(r), points=50) center = (.5, .5, .5) lf = create_localized_functions([spline], gd, center, dtype=dtype) psit_k = gd.zeros(mcount, dtype=dtype) coef_xi = np.identity(mcount * fcount, dtype=dtype) lf.add(psit_k, coef_xi) return gd, psit_k, center, function
def make_dummy_reference(l, function=None, rcut=6., a=12., n=60, dtype=float): """Make a mock reference wave function using a made-up radial function as reference""" #print 'Dummy reference: l=%d, rcut=%.02f, alpha=%.02f' % (l, rcut, alpha) r = np.arange(0., rcut, .01) if function is None: function = QuasiGaussian(4., rcut) norm = get_norm(r, function(r), l) function.renormalize(norm) #g = QuasiGaussian(alpha, rcut) mcount = 2*l + 1 fcount = 1 gd = GridDescriptor((n, n, n), (a, a, a), (False, False, False)) spline = Spline(l, r[-1], function(r), points=50) center = (.5, .5, .5) lf = create_localized_functions([spline], gd, center, dtype=dtype) psit_k = gd.zeros(mcount, dtype=dtype) coef_xi = np.identity(mcount * fcount, dtype=dtype) lf.add(psit_k, coef_xi) return gd, psit_k, center, function
def make_dummy_kpt_reference(l, function, k_c, rcut=6., a=10., n=60, dtype=complex): r = np.linspace(0., rcut, 300) mcount = 2 * l + 1 fcount = 1 kcount = 1 gd = GridDescriptor((n, n, n), (a, a, a), (True, True, True)) kpt = KPoint([], gd, 1., 0, 0, 0, k_c, dtype) spline = Spline(l, r[-1], function(r)) center = (.5, .5, .5) lf = create_localized_functions([spline], gd, center, dtype=dtype) lf.set_phase_factors([kpt.k_c]) psit_nG = gd.zeros(mcount, dtype=dtype) coef_xi = np.identity(mcount * fcount, dtype=dtype) lf.add(psit_nG, coef_xi, k=0) kpt.psit_nG = psit_nG print 'Number of boxes', len(lf.box_b) print 'Phase kb factors shape', lf.phase_kb.shape return gd, kpt, center
from gpaw.poisson import NonPeriodicLauePoissonSolver, GeneralizedLauePoissonSolver, FDPoissonSolver, idst2, dst2 from gpaw.grid_descriptor import GridDescriptor import numpy as np gd = GridDescriptor((10,12,42), (4, 5, 20), pbc_c=(True,True,False)) poisson = GeneralizedLauePoissonSolver(nn=2) poisson.set_grid_descriptor(gd) poisson2 = FDPoissonSolver(nn=2, eps=1e-28) poisson2.set_grid_descriptor(gd) phi_g = gd.zeros() phi2_g = gd.zeros() rho_g = gd.zeros() rho_g[4,5,6] = 1.0 rho_g[4,5,7] = -1.0 poisson.solve(phi_g, rho_g) poisson2.solve(phi2_g, rho_g) print("this", phi_g[4,5,:]) print("ref", phi2_g[4,5,:]) print("diff", phi_g[4,5,:]-phi2_g[4,5,:]) assert np.linalg.norm(phi_g-phi2_g) < 1e-10 gd = GridDescriptor((10,12,42), (10, 12, 42), pbc_c=(False,False,False)) poisson = NonPeriodicLauePoissonSolver(nn=1) poisson.set_grid_descriptor(gd) print("eigs", poisson.eigs_c[0]) poisson2 = FDPoissonSolver(nn=1, eps=1e-24) poisson2.set_grid_descriptor(gd)
Ep = xc.calculate(gd, n, v) if here: n[-1, 1, 2, 3] -= 0.000002 Em = xc.calculate(gd, n, v) x2 = (Ep - Em) / 0.000002 if here: print(xc.name, E, x, x2, x - x2) equal(x, x2, 1e-11) n[-1, 1, 2, 3] += 0.000001 if 0:#xc.type == 'LDA': xc = XC(NonCollinearLDAKernel()) else: xc = NonCollinearFunctional(xc) n2 = gd.zeros(4) n2[0] = n.sum(0) n2[3] = n[0] - n[1] E2 = xc.calculate(gd, n2) print(E, E2-E) assert abs(E2 - E) < 1e-11 n2[1] = 0.1 * n2[3] n2[2] = 0.2 * n2[3] n2[3] *= (1 - 0.1**2 - 0.2**2)**0.5 v = n2 * 0 E2 = xc.calculate(gd, n2, v) print(E, E2-E) assert abs(E2 - E) < 1e-11 for i in range(4): if here:
from gpaw.test import equal from gpaw.grid_descriptor import GridDescriptor from gpaw.spline import Spline import gpaw.mpi as mpi from gpaw.lfc import LocalizedFunctionsCollection as LFC s = Spline(0, 1.0, [1.0, 0.5, 0.0]) n = 40 a = 8.0 gd = GridDescriptor((n, n, n), (a, a, a), comm=mpi.serial_comm) c = LFC(gd, [[s], [s], [s]]) c.set_positions([(0.5, 0.5, 0.25 + 0.25 * i) for i in [0, 1, 2]]) b = gd.zeros() c.add(b) x = gd.integrate(b) gd = GridDescriptor((n, n, n), (a, a, a), comm=mpi.serial_comm) c = LFC(gd, [[s], [s], [s]]) c.set_positions([(0.5, 0.5, 0.25 + 0.25 * i) for i in [0, 1, 2]]) b = gd.zeros() c.add(b) y = gd.integrate(b) equal(x, y, 1e-13)
from gpaw.grid_descriptor import GridDescriptor from gpaw.spline import Spline a = 4.0 gd = GridDescriptor(N_c=[16, 20, 20], cell_cv=[a, a + 1, a + 2], pbc_c=(0, 1, 1)) spos_ac = np.array([[0.25, 0.15, 0.35], [0.5, 0.5, 0.5]]) kpts_kc = None s = Spline(l=0, rmax=2.0, f_g=np.array([1, 0.9, 0.1, 0.0])) p = Spline(l=1, rmax=2.0, f_g=np.array([1, 0.9, 0.1, 0.0])) spline_aj = [[s], [s, p]] c = LFC(gd, spline_aj, cut=True, forces=True) c.set_positions(spos_ac) C_ani = c.dict(3, zero=True) if 1 in C_ani: C_ani[1][:, 1:] = np.eye(3) psi = gd.zeros(3) c.add(psi, C_ani) c.integrate(psi, C_ani) if 1 in C_ani: d = C_ani[1][:, 1:].diagonal() assert d.ptp() < 4e-6 C_ani[1][:, 1:] -= np.diag(d) assert abs(C_ani[1]).max() < 5e-17 d_aniv = c.dict(3, derivative=True) c.derivative(psi, d_aniv) if 1 in d_aniv: for v in range(3): assert abs(d_aniv[1][v - 1, 0, v] + 0.2144) < 5e-5 d_aniv[1][v - 1, 0, v] = 0 assert abs(d_aniv[1]).max() < 3e-16 eps = 0.0001
from gpaw.response.math_func import two_phi_planewave_integrals # Initialize s, p, d (9 in total) wave and put them on grid rc = 2.0 a = 2.5 * rc n = 64 lmax = 2 b = 8.0 m = (lmax + 1)**2 gd = GridDescriptor([n, n, n], [a, a, a]) r = np.linspace(0, rc, 200) g = np.exp(-(r / rc * b)**2) splines = [Spline(l=l, rmax=rc, f_g=g) for l in range(lmax + 1)] c = LFC(gd, [splines]) c.set_positions([(0.5, 0.5, 0.5)]) psi = gd.zeros(m) d0 = c.dict(m) if 0 in d0: d0[0] = np.identity(m) c.add(psi, d0) # Calculate on 3d-grid < phi_i | e**(-ik.r) | phi_j > R_a = np.array([a/2,a/2,a/2]) rr = gd.get_grid_point_coordinates() for dim in range(3): rr[dim] -= R_a[dim] k_G = np.array([[11.,0.2,0.1],[10., 0., 10.]]) nkpt = k_G.shape[0] d0 = np.zeros((nkpt,m,m), dtype=complex)
class DF(CHI): """This class defines dielectric function related physical quantities.""" def __init__(self, calc=None, nbands=None, w=None, q=None, eshift=None, ecut=10., density_cut=None, G_plus_q=False, eta=0.2, rpad=None, vcut=None, ftol=1e-7, txt=None, xc='ALDA', print_xc_scf=False, hilbert_trans=True, time_ordered=False, optical_limit=False, comm=None, kcommsize=None): CHI.__init__(self, calc=calc, nbands=nbands, w=w, q=q, eshift=eshift, ecut=ecut, density_cut=density_cut, G_plus_q=G_plus_q, eta=eta, rpad=rpad, vcut=vcut, ftol=ftol, txt=txt, xc=xc, hilbert_trans=hilbert_trans, time_ordered=time_ordered, optical_limit=optical_limit, comm=comm, kcommsize=kcommsize) self.df_flag = False self.print_bootstrap = print_xc_scf self.df1_w = None # NLF RPA self.df2_w = None # LF RPA self.df3_w = None # NLF ALDA self.df4_w = None # LF ALDA def get_dielectric_matrix(self, xc='RPA', overwritechi0=False, symmetric=True, chi0_wGG=None, calc=None, vcut=None, dir=None): if self.chi0_wGG is None and chi0_wGG is None: self.initialize() self.calculate() elif self.chi0_wGG is None and chi0_wGG is not None: #Read from file and reinitialize self.xc = xc from gpaw.response.parallel import par_read self.chi0_wGG = par_read(chi0_wGG, 'chi0_wGG') self.nvalbands = self.nbands #self.parallel_init() # parallelization not yet implemented self.Nw_local = self.Nw # parallelization not yet implemented if self.calc is None: from gpaw import GPAW self.calc = GPAW(calc,txt=None) if self.xc == 'ALDA' or self.xc == 'ALDA_X': from gpaw.response.kernel import calculate_Kxc from gpaw.grid_descriptor import GridDescriptor from gpaw.mpi import world, rank, size, serial_comm self.pbc = self.calc.atoms.pbc self.gd = GridDescriptor(self.calc.wfs.gd.N_c*self.rpad, self.acell_cv, pbc_c=True, comm=serial_comm) R_av = self.calc.atoms.positions / Bohr nt_sg = self.calc.density.nt_sG if (self.rpad > 1).any() or (self.pbc - True).any(): nt_sG = self.gd.zeros(self.nspins) #nt_sG = np.zeros([self.nspins, self.nG[0], self.nG[1], self.nG[2]]) for s in range(self.nspins): nt_G = self.pad(nt_sg[s]) nt_sG[s] = nt_G else: nt_sG = nt_sg self.Kxc_sGG = calculate_Kxc(self.gd, nt_sG, self.npw, self.Gvec_Gc, self.gd.N_c, self.vol, self.bcell_cv, R_av, self.calc.wfs.setups, self.calc.density.D_asp, functional=self.xc, density_cut=self.density_cut) if overwritechi0: dm_wGG = self.chi0_wGG else: dm_wGG = np.zeros_like(self.chi0_wGG) if dir is None: q_c = self.q_c else: q_c = np.diag((1,1,1))[dir] * self.qopt self.chi0_wGG[:,0,:] = self.chi00G_wGv[:,:,dir] self.chi0_wGG[:,:,0] = self.chi0G0_wGv[:,:,dir] from gpaw.response.kernel import calculate_Kc, CoulombKernel kernel = CoulombKernel(vcut=self.vcut, pbc=self.calc.atoms.pbc, cell=self.acell_cv) self.Kc_GG = kernel.calculate_Kc(q_c, self.Gvec_Gc, self.bcell_cv, symmetric=symmetric) #self.Kc_GG = calculate_Kc(q_c, # self.Gvec_Gc, # self.acell_cv, # self.bcell_cv, # self.pbc, # self.vcut, # symmetric=symmetric) tmp_GG = np.eye(self.npw, self.npw) if xc == 'RPA': self.printtxt('Use RPA.') for iw in range(self.Nw_local): dm_wGG[iw] = tmp_GG - self.Kc_GG * self.chi0_wGG[iw] elif xc == 'ALDA': self.printtxt('Use ALDA kernel.') # E_LDA = 1 - v_c chi0 (1-fxc chi0)^-1 # http://prb.aps.org/pdf/PRB/v33/i10/p7017_1 eq. 4 A_wGG = self.chi0_wGG.copy() for iw in range(self.Nw_local): A_wGG[iw] = np.dot(self.chi0_wGG[iw], np.linalg.inv(tmp_GG - np.dot(self.Kxc_sGG[0], self.chi0_wGG[iw]))) for iw in range(self.Nw_local): dm_wGG[iw] = tmp_GG - self.Kc_GG * A_wGG[iw] return dm_wGG def get_inverse_dielectric_matrix(self, xc='RPA'): dm_wGG = self.get_dielectric_matrix(xc=xc) dminv_wGG = np.zeros_like(dm_wGG) for iw in range(self.Nw_local): dminv_wGG[iw] = np.linalg.inv(dm_wGG[iw]) return dminv_wGG def get_chi(self, xc='RPA'): """Solve Dyson's equation.""" if self.chi0_wGG is None: self.initialize() self.calculate() else: pass # read from file and re-initializing .... need to be implemented kernel_GG = np.zeros((self.npw, self.npw), dtype=complex) chi_wGG = np.zeros_like(self.chi0_wGG) # Coulomb kernel for iG in range(self.npw): qG = np.dot(self.q_c + self.Gvec_Gc[iG], self.bcell_cv) kernel_GG[iG,iG] = 4 * pi / np.dot(qG, qG) if xc == 'ALDA': kernel_GG += self.Kxc_sGG[0] for iw in range(self.Nw_local): tmp_GG = np.eye(self.npw, self.npw) - np.dot(self.chi0_wGG[iw], kernel_GG) chi_wGG[iw] = np.dot(np.linalg.inv(tmp_GG) , self.chi0_wGG[iw]) return chi_wGG def get_dielectric_function(self, xc='RPA', dir=None): """Calculate the dielectric function. Returns df1_w and df2_w. Parameters: df1_w: ndarray Dielectric function without local field correction. df2_w: ndarray Dielectric function with local field correction. """ if not self.optical_limit: assert dir is None if self.df_flag is False: dm_wGG = self.get_dielectric_matrix(xc=xc, dir=dir) Nw_local = dm_wGG.shape[0] dfNLF_w = np.zeros(Nw_local, dtype = complex) dfLFC_w = np.zeros(Nw_local, dtype = complex) df1_w = np.zeros(self.Nw, dtype = complex) df2_w = np.zeros(self.Nw, dtype = complex) for iw in range(Nw_local): tmp_GG = dm_wGG[iw] dfLFC_w[iw] = 1. / np.linalg.inv(tmp_GG)[0, 0] dfNLF_w[iw] = tmp_GG[0, 0] self.wcomm.all_gather(dfNLF_w, df1_w) self.wcomm.all_gather(dfLFC_w, df2_w) if xc == 'RPA': self.df1_w = df1_w self.df2_w = df2_w elif xc=='ALDA' or xc=='ALDA_X': self.df3_w = df1_w self.df4_w = df2_w if xc == 'RPA': return self.df1_w, self.df2_w elif xc == 'ALDA' or xc=='ALDA_X': return self.df3_w, self.df4_w def get_surface_response_function(self, z0=0., filename='surf_EELS'): """Calculate surface response function.""" if self.chi0_wGG is None: self.initialize() self.calculate() g_w2 = np.zeros((self.Nw,2), dtype=complex) assert self.acell_cv[0, 2] == 0. and self.acell_cv[1, 2] == 0. Nz = self.gd.N_c[2] # number of points in z direction tmp = np.zeros(Nz, dtype=int) nGz = 0 # number of G_z for i in range(self.npw): if self.Gvec_Gc[i, 0] == 0 and self.Gvec_Gc[i, 1] == 0: tmp[nGz] = self.Gvec_Gc[i, 2] nGz += 1 assert (np.abs(self.Gvec_Gc[:nGz, :2]) < 1e-10).all() for id, xc in enumerate(['RPA', 'ALDA']): chi_wGG = self.get_chi(xc=xc) # The first nGz are all Gx=0 and Gy=0 component chi_wgg_LFC = chi_wGG[:, :nGz, :nGz] del chi_wGG chi_wzz_LFC = np.zeros((self.Nw_local, Nz, Nz), dtype=complex) # Fourier transform of chi_wgg to chi_wzz Gz_g = tmp[:nGz] * self.bcell_cv[2,2] z_z = np.linspace(0, self.acell_cv[2,2]-self.gd.h_cv[2,2], Nz) phase1_zg = np.exp(1j * np.outer(z_z, Gz_g)) phase2_gz = np.exp(-1j * np.outer(Gz_g, z_z)) for iw in range(self.Nw_local): chi_wzz_LFC[iw] = np.dot(np.dot(phase1_zg, chi_wgg_LFC[iw]), phase2_gz) chi_wzz_LFC /= self.acell_cv[2,2] # Get surface response function z_z -= z0 / Bohr q_v = np.dot(self.q_c, self.bcell_cv) qq = sqrt(np.inner(q_v, q_v)) phase1_1z = np.array([np.exp(qq*z_z)]) phase2_z1 = np.exp(qq*z_z) tmp_w = np.zeros(self.Nw_local, dtype=complex) for iw in range(self.Nw_local): tmp_w[iw] = np.dot(np.dot(phase1_1z, chi_wzz_LFC[iw]), phase2_z1)[0] tmp_w *= -2 * pi / qq * self.gd.h_cv[2,2]**2 g_w = np.zeros(self.Nw, dtype=complex) self.wcomm.all_gather(tmp_w, g_w) g_w2[:, id] = g_w if rank == 0: f = open(filename,'w') for iw in range(self.Nw): energy = iw * self.dw * Hartree print >> f, energy, np.imag(g_w2[iw, 0]), np.imag(g_w2[iw, 1]) f.close() # Wait for I/O to finish self.comm.barrier() def check_sum_rule(self, df1_w=None, df2_w=None): """Check f-sum rule.""" if df1_w is None: df1_w = self.df1_w df2_w = self.df2_w N1 = N2 = 0 for iw in range(self.Nw): w = iw * self.dw N1 += np.imag(df1_w[iw]) * w N2 += np.imag(df2_w[iw]) * w N1 *= self.dw * self.vol / (2 * pi**2) N2 *= self.dw * self.vol / (2 * pi**2) self.printtxt('') self.printtxt('Sum rule for ABS:') nv = self.nvalence self.printtxt('Without local field: N1 = %f, %f %% error' %(N1, (N1 - nv) / nv * 100) ) self.printtxt('Include local field: N2 = %f, %f %% error' %(N2, (N2 - nv) / nv * 100) ) N1 = N2 = 0 for iw in range(self.Nw): w = iw * self.dw N1 -= np.imag(1/df1_w[iw]) * w N2 -= np.imag(1/df2_w[iw]) * w N1 *= self.dw * self.vol / (2 * pi**2) N2 *= self.dw * self.vol / (2 * pi**2) self.printtxt('') self.printtxt('Sum rule for EELS:') nv = self.nvalence self.printtxt('Without local field: N1 = %f, %f %% error' %(N1, (N1 - nv) / nv * 100) ) self.printtxt('Include local field: N2 = %f, %f %% error' %(N2, (N2 - nv) / nv * 100) ) def get_macroscopic_dielectric_constant(self, xc='RPA'): """Calculate macroscopic dielectric constant. Returns eM1 and eM2 Macroscopic dielectric constant is defined as the real part of dielectric function at w=0. Parameters: eM1: float Dielectric constant without local field correction. (RPA, ALDA) eM2: float Dielectric constant with local field correction. """ assert self.optical_limit self.printtxt('') self.printtxt('%s Macroscopic Dielectric Constant:' % xc) dirstr = ['x', 'y', 'z'] for dir in range(3): eM = np.zeros(2) df1, df2 = self.get_dielectric_function(xc=xc, dir=dir) eps0 = np.real(df1[0]) eps = np.real(df2[0]) self.printtxt(' %s direction' %(dirstr[dir])) self.printtxt(' Without local field: %f' % eps0 ) self.printtxt(' Include local field: %f' % eps ) return eps0, eps def get_absorption_spectrum(self, filename='Absorption.dat'): """Calculate optical absorption spectrum. By default, generate a file 'Absorption.dat'. Optical absorption spectrum is obtained from the imaginary part of dielectric function. """ assert self.optical_limit for dir in range(3): df1, df2 = self.get_dielectric_function(xc='RPA', dir=dir) if self.xc == 'ALDA': df3, df4 = self.get_dielectric_function(xc='ALDA', dir=dir) if self.xc is 'ALDA_X': df3, df4 = self.get_dielectric_function(xc='ALDA_X', dir=dir) Nw = df1.shape[0] if self.xc == 'Bootstrap': # bootstrap doesnt support all direction spectra yet from gpaw.response.fxc import Bootstrap Kc_GG = np.zeros((self.npw, self.npw)) q_c = np.diag((1, 1, 1))[dir] * self.qopt for iG in range(self.npw): qG = np.dot(q_c + self.Gvec_Gc[iG], self.bcell_cv) Kc_GG[iG,iG] = 4 * pi / np.dot(qG, qG) from gpaw.mpi import world assert self.wcomm.size == world.size df3 = Bootstrap(self.chi0_wGG, Nw, Kc_GG, self.printtxt, self.print_bootstrap, self.wcomm) if rank == 0: f = open('%s.%s' % (filename, 'xyz'[dir]), 'w') #f = open(filename+'.%s'%(dirstr[dir]),'w') # ???? for iw in range(Nw): energy = iw * self.dw * Hartree if self.xc == 'RPA': print >> f, energy, np.real(df1[iw]), np.imag(df1[iw]), \ np.real(df2[iw]), np.imag(df2[iw]) elif self.xc == 'ALDA': print >> f, energy, np.real(df1[iw]), np.imag(df1[iw]), \ np.real(df2[iw]), np.imag(df2[iw]), \ np.real(df3[iw]), np.imag(df3[iw]), \ np.real(df4[iw]), np.imag(df4[iw]) elif self.xc == 'Bootstrap': print >> f, energy, np.real(df1[iw]), np.imag(df1[iw]), \ np.real(df2[iw]), np.imag(df2[iw]), \ np.real(df3[iw]), np.imag(df3[iw]) f.close() # Wait for I/O to finish self.comm.barrier() def get_EELS_spectrum(self, filename='EELS.dat'): """Calculate EELS spectrum. By default, generate a file 'EELS.dat'. EELS spectrum is obtained from the imaginary part of the inverse of dielectric function. """ # calculate RPA dielectric function df1, df2 = self.get_dielectric_function(xc='RPA') if self.xc == 'ALDA': df3, df4 = self.get_dielectric_function(xc='ALDA') Nw = df1.shape[0] if rank == 0: f = open(filename,'w') for iw in range(self.Nw): energy = iw * self.dw * Hartree if self.xc == 'RPA': print >> f, energy, -np.imag(1./df1[iw]), -np.imag(1./df2[iw]) elif self.xc == 'ALDA': print >> f, energy, -np.imag(1./df1[iw]), -np.imag(1./df2[iw]), \ -np.imag(1./df3[iw]), -np.imag(1./df4[iw]) f.close() # Wait for I/O to finish self.comm.barrier() def get_jdos(self, f_skn, e_skn, kd, kq, dw, Nw, sigma): """Calculate Joint density of states""" JDOS_w = np.zeros(Nw) nbands = f_skn[0].shape[1] for k in range(kd.nbzkpts): print k ibzkpt1 = kd.bz2ibz_k[k] ibzkpt2 = kd.bz2ibz_k[kq[k]] for n in range(nbands): for m in range(nbands): focc = f_skn[0][ibzkpt1, n] - f_skn[0][ibzkpt2, m] w0 = e_skn[0][ibzkpt2, m] - e_skn[0][ibzkpt1, n] if focc > 0 and w0 >= 0: w0_id = int(w0 / dw) if w0_id + 1 < Nw: alpha = (w0_id + 1 - w0/dw) / dw JDOS_w[w0_id] += focc * alpha alpha = (w0/dw-w0_id) / dw JDOS_w[w0_id+1] += focc * alpha w = np.arange(Nw) * dw * Hartree return w, JDOS_w def calculate_induced_density(self, q, w): """ Evaluate induced density for a certain q and w. Parameters: q: ndarray Momentum tranfer at reduced coordinate. w: scalar Energy (eV). """ if type(w) is int: iw = w w = self.wlist[iw] / Hartree elif type(w) is float: w /= Hartree iw = int(np.round(w / self.dw)) else: raise ValueError('Frequency not correct !') self.printtxt('Calculating Induced density at q, w (iw)') self.printtxt('(%f, %f, %f), %f(%d)' %(q[0], q[1], q[2], w*Hartree, iw)) # delta_G0 delta_G = np.zeros(self.npw) delta_G[0] = 1. # coef is (q+G)**2 / 4pi coef_G = np.zeros(self.npw) for iG in range(self.npw): qG = np.dot(q + self.Gvec_Gc[iG], self.bcell_cv) coef_G[iG] = np.dot(qG, qG) coef_G /= 4 * pi # obtain chi_G0(q,w) dm_wGG = self.get_RPA_dielectric_matrix() tmp_GG = dm_wGG[iw] del dm_wGG chi_G = (np.linalg.inv(tmp_GG)[:, 0] - delta_G) * coef_G gd = self.gd r = gd.get_grid_point_coordinates() # calculate dn(r,q,w) drho_R = gd.zeros(dtype=complex) for iG in range(self.npw): qG = np.dot(q + self.Gvec_Gc[iG], self.bcell_cv) qGr_R = np.inner(qG, r.T).T drho_R += chi_G[iG] * np.exp(1j * qGr_R) # phase = sum exp(iq.R_i) return drho_R def get_induced_density_z(self, q, w): """Get induced density on z axis (summation over xy-plane). """ drho_R = self.calculate_induced_density(q, w) drho_z = np.zeros(self.gd.N_c[2],dtype=complex) # dxdy = np.cross(self.h_c[0], self.h_c[1]) for iz in range(self.gd.N_c[2]): drho_z[iz] = drho_R[:,:,iz].sum() return drho_z def get_eigenmodes(self,filename = None, chi0 = None, calc = None, dm = None, xc = 'RPA', sum = None, vcut = None, checkphase = False, return_full = False): """ Calculate the plasmonic eigenmodes as eigenvectors of the dielectric matrix. Parameters: filename: pckl file output from response calculation. chi0: gpw file chi0_wGG from response calculation. calc: gpaw calculator instance ground state calculator used in response calculation. Wavefunctions only needed if chi0 is calculated from scratch dm: gpw file dielectric matrix from response calculation xc: str 'RPA'or 'ALDA' XC- Kernel sum: str '2D': sum in the x and y directions '1D': To be implemented vcut: str '0D','1D' or '2D' Cut the Coulomb potential checkphase: Bool if True, the eigenfunctions id rotated in the complex plane, to be made as real as posible return_full: Bool if True, the eigenvectors in reciprocal space is also returned. """ self.read(filename) self.pbc = [1,1,1] #self.calc.atoms.pbc = [1,1,1] npw = self.npw self.w_w = np.linspace(0, self.dw * (self.Nw - 1)*Hartree, self.Nw) self.vcut = vcut dm_wGG = self.get_dielectric_matrix(xc=xc, symmetric=False, chi0_wGG=chi0, calc=calc, vcut=vcut) q = self.q_c # get grid on which the eigenmodes are calculated #gd = self.calc.wfs.gd #r = gd.get_grid_point_coordinates() #rrr = r*Bohr from gpaw.utilities.gpts import get_number_of_grid_points from gpaw.grid_descriptor import GridDescriptor grid_size = [1,1,1] h=0.2 cell_cv = self.acell_cv*np.diag(grid_size) mode = 'fd' realspace = True h /= Bohr N_c = get_number_of_grid_points(cell_cv, h, mode, realspace) gd = GridDescriptor(N_c, cell_cv, self.pbc) #gd = self.calc.wfs.gd r = gd.get_grid_point_coordinates() rrr = r*Bohr eig_0 = np.array([], dtype = complex) eig_left = np.array([], dtype = complex) eig_right = np.array([], dtype = complex) vec_modes = np.zeros([1, self.npw], dtype = complex) vec_modes_dual = np.zeros([1, self.npw], dtype = complex) vec_modes_density = np.zeros([1, self.npw], dtype = complex) vec_modes_norm = np.zeros([1, self.npw], dtype = complex) eig_all = np.zeros([1, self.npw], dtype = complex) eig_dummy = np.zeros([1, self.npw], dtype = complex) v_dummy = np.zeros([1, self.npw], dtype = complex) vec_dummy = np.zeros([1, self.npw], dtype = complex) vec_dummy2 = np.zeros([1, self.npw], dtype = complex) w_0 = np.array([]) w_left = np.array([]) w_right = np.array([]) if sum == '2D': v_ind = np.zeros([1, r.shape[-1]], dtype = complex) n_ind = np.zeros([1, r.shape[-1]], dtype = complex) elif sum == '1D': self.printtxt('1D sum not implemented') return else: v_ind = np.zeros([1, r.shape[1], r.shape[2], r.shape[3]], dtype = complex) n_ind = np.zeros([1, r.shape[1], r.shape[2], r.shape[3]], dtype = complex) eps_GG_plus = dm_wGG[0] eig_plus, vec_plus = np.linalg.eig(eps_GG_plus) # find eigenvalues and eigenvectors vec_plus_dual = np.linalg.inv(vec_plus) # loop over frequencies, where the eigenvalues for the 2D matrix in G,G' are found. for i in np.array(range(self.Nw-1))+1: eps_GG = eps_GG_plus eig, vec = eig_plus,vec_plus vec_dual = vec_plus_dual eps_GG_plus = dm_wGG[i] # epsilon_GG'(omega + d-omega) eig_plus, vec_plus = np.linalg.eig(eps_GG_plus) vec_plus_dual = np.linalg.inv(vec_plus) eig_dummy[0,:] = eig eig_all = np.append(eig_all, eig_dummy, axis=0) # append all eigenvalues to array # loop to check find the eigenvalues that crosses zero from negative to positive values: for k in range(self.npw): for m in range(self.npw): if eig[k]< 0 and 0 < eig_plus[m]: # check it's the same mode - Overlap between eigenvectors should be large: if abs(np.inner(vec[:,k], vec_plus_dual[m,:])) > 0.95: self.printtxt('crossing found at w = %1.1f eV'%self.w_w[i-1]) eig_left = np.append(eig_left, eig[k]) eig_right = np.append(eig_right, eig_plus[m]) vec_dummy[0, :] = vec[:,k] vec_modes = np.append(vec_modes, vec_dummy, axis = 0) vec_dummy[0, :] = vec_dual[k, :].T vec_modes_dual = np.append(vec_modes_dual, vec_dummy, axis = 0) w1 = self.w_w[i-1] w2 = self.w_w[i] a = np.real((eig_plus[m]-eig[k]) / (w2-w1)) w0 = np.real(-eig[k]) / a + w1 eig0 = a*(w0-w1)+eig[k] w_0 = np.append(w_0,w0) w_left = np.append(w_left, w1) eig_0 = np.append(eig_0,eig0) n_dummy = np.zeros([1, r.shape[1], r.shape[2], r.shape[3]], dtype = complex) v_dummy = np.zeros([1, r.shape[1], r.shape[2], r.shape[3]], dtype = complex) vec_n = np.zeros([self.npw]) for iG in range(self.npw): # Fourier transform qG = np.dot((q + self.Gvec_Gc[iG]), self.bcell_cv) coef_G = np.dot(qG, qG) / (4 * pi) qGr_R = np.inner(qG, r.T).T v_dummy += vec[iG, k] * np.exp(1j * qGr_R) n_dummy += vec[iG, k] * np.exp(1j * qGr_R) * coef_G if checkphase: # rotate eigenvectors in complex plane integral = np.zeros([81]) phases = np.linspace(0,2,81) for ip in range(81): v_int = v_dummy * np.exp(1j * pi * phases[ip]) integral[ip] = abs(np.imag(v_int)).sum() phase = phases[np.argsort(integral)][0] v_dummy *= np.exp(1j * pi * phase) n_dummy *= np.exp(1j * pi * phase) if sum == '2D': i_xyz = 3 v_dummy_z = np.zeros([1,v_dummy.shape[i_xyz]], dtype = complex) n_dummy_z = np.zeros([1,v_dummy.shape[i_xyz]], dtype = complex) v_dummy_z[0,:] = np.sum(np.sum(v_dummy, axis = 1), axis = 1)[0,:] n_dummy_z[0,:] = np.sum(np.sum(n_dummy, axis = 1), axis = 1)[0,:] v_ind = np.append(v_ind, v_dummy_z, axis=0) n_ind = np.append(n_ind, n_dummy_z, axis=0) elif sum == '1D': self.printtxt('1D sum not implemented') else : v_ind = np.append(v_ind, v_dummy, axis=0) n_ind = np.append(n_ind, n_dummy, axis=0) """ returns: grid points, frequency grid, all eigenvalues, mode energies, left point energies, mode eigenvalues, eigenvalues of left and right-side points, (mode eigenvectors, mode dual eigenvectors,) induced potential in real space, induced density in real space """ if return_full: return rrr, self.w_w, eig_all[1:], w_0, eig_0, w_left, eig_left, \ eig_right, vec_modes[1:], vec_modes_dual[1:], v_ind[1:], n_ind[1:] else: return rrr, self.w_w, eig_all[1:], w_0, eig_0, w_left, eig_left, \ eig_right, v_ind[1:], n_ind[1:] def project_chi_to_LCAO_pair_orbital(self, orb_MG): nLCAO = orb_MG.shape[0] N = np.zeros((self.Nw, nLCAO, nLCAO), dtype=complex) kcoulinv_GG = np.zeros((self.npw, self.npw)) for iG in range(self.npw): qG = np.dot(self.q_c + self.Gvec_Gc[iG], self.bcell_cv) kcoulinv_GG[iG, iG] = np.dot(qG, qG) kcoulinv_GG /= 4.*pi dm_wGG = self.get_RPA_dielectric_matrix() for mu in range(nLCAO): for nu in range(nLCAO): pairorb_R = orb_MG[mu] * orb_MG[nu] if not (pairorb_R * pairorb_R.conj() < 1e-10).all(): tmp_G = np.fft.fftn(pairorb_R) * self.vol / self.nG0 pairorb_G = np.zeros(self.npw, dtype=complex) for iG in range(self.npw): index = self.Gindex[iG] pairorb_G[iG] = tmp_G[index[0], index[1], index[2]] for iw in range(self.Nw): chi_GG = (dm_wGG[iw] - np.eye(self.npw)) * kcoulinv_GG N[iw, mu, nu] = (np.outer(pairorb_G.conj(), pairorb_G) * chi_GG).sum() # N[iw, mu, nu] = np.inner(pairorb_G.conj(),np.inner(pairorb_G, chi_GG)) return N def write(self, filename, all=False): """Dump essential data""" data = {'nbands': self.nbands, 'acell': self.acell_cv, #* Bohr, 'bcell': self.bcell_cv, #/ Bohr, 'h_cv' : self.gd.h_cv, #* Bohr, 'nG' : self.gd.N_c, 'nG0' : self.nG0, 'vol' : self.vol, #* Bohr**3, 'BZvol': self.BZvol, #/ Bohr**3, 'nkpt' : self.kd.nbzkpts, 'ecut' : self.ecut, #* Hartree, 'npw' : self.npw, 'eta' : self.eta, #* Hartree, 'ftol' : self.ftol, 'Nw' : self.Nw, 'NwS' : self.NwS, 'dw' : self.dw, # * Hartree, 'q_red': self.q_c, 'q_car': self.qq_v, # / Bohr, 'qmod' : np.dot(self.qq_v, self.qq_v), # / Bohr 'vcut' : self.vcut, 'pbc' : self.pbc, 'nvalence' : self.nvalence, 'hilbert_trans' : self.hilbert_trans, 'optical_limit' : self.optical_limit, 'e_skn' : self.e_skn, # * Hartree, 'f_skn' : self.f_skn, 'bzk_kc' : self.kd.bzk_kc, 'ibzk_kc' : self.kd.ibzk_kc, 'kq_k' : self.kq_k, 'Gvec_Gc' : self.Gvec_Gc, 'dfNLFRPA_w' : self.df1_w, 'dfLFCRPA_w' : self.df2_w, 'dfNLFALDA_w' : self.df3_w, 'dfLFCALDA_w' : self.df4_w, 'df_flag' : True} if all: from gpaw.response.parallel import par_write par_write('chi0' + filename,'chi0_wGG',self.wcomm,self.chi0_wGG) if rank == 0: pickle.dump(data, open(filename, 'w'), -1) self.comm.barrier() def read(self, filename): """Read data from pickle file""" data = pickle.load(open(filename)) self.nbands = data['nbands'] self.acell_cv = data['acell'] self.bcell_cv = data['bcell'] self.nG0 = data['nG0'] self.vol = data['vol'] self.BZvol = data['BZvol'] self.ecut = data['ecut'] self.npw = data['npw'] self.eta = data['eta'] self.ftol = data['ftol'] self.Nw = data['Nw'] self.NwS = data['NwS'] self.dw = data['dw'] self.q_c = data['q_red'] self.qq_v = data['q_car'] self.qmod = data['qmod'] #self.vcut = data['vcut'] #self.pbc = data['pbc'] self.hilbert_trans = data['hilbert_trans'] self.optical_limit = data['optical_limit'] self.e_skn = data['e_skn'] self.f_skn = data['f_skn'] self.nvalence= data['nvalence'] self.kq_k = data['kq_k'] self.Gvec_Gc = data['Gvec_Gc'] self.df1_w = data['dfNLFRPA_w'] self.df2_w = data['dfLFCRPA_w'] self.df3_w = data['dfNLFALDA_w'] self.df4_w = data['dfLFCALDA_w'] self.df_flag = data['df_flag'] self.printtxt('Read succesfully !')
from __future__ import print_function from math import sqrt, pi import numpy as np from gpaw.setup import create_setup from gpaw.grid_descriptor import GridDescriptor from gpaw.localized_functions import create_localized_functions from gpaw.xc import XC n = 60 #40 /8 * 10 a = 10.0 gd = GridDescriptor((n, n, n), (a, a, a)) c_LL = np.identity(9, float) a_Lg = gd.zeros(9) nspins = 2 xc = XC('LDA') for soft in [False]: s = create_setup('Cu', xc, lmax=2) ghat_l = s.ghat_l ghat_Lg = create_localized_functions(ghat_l, gd, (0.54321, 0.5432, 0.543)) a_Lg[:] = 0.0 ghat_Lg.add(a_Lg, c_LL) for l in range(3): for m in range(2 * l + 1): L = l**2 + m a_g = a_Lg[L] Q0 = gd.integrate(a_g) / sqrt(4 * pi) Q1_m = -gd.calculate_dipole_moment(a_g) / sqrt(4 * pi / 3) print(Q0) if l == 0: Q0 -= 1.0 Q1_m[:] = 0.0
from __future__ import print_function import numpy as np from gpaw.lfc import LocalizedFunctionsCollection as LFC from gpaw.grid_descriptor import GridDescriptor from gpaw.spline import Spline gd = GridDescriptor([20, 16, 16], [(4, 2, 0), (0, 4, 0), (0, 0, 4)]) spos_ac = np.array([[0.252, 0.15, 0.35], [0.503, 0.5, 0.5]]) s = Spline(l=0, rmax=2.0, f_g=np.array([1, 0.9, 0.1, 0.0])) spline_aj = [[s], [s]] c = LFC(gd, spline_aj) c.set_positions(spos_ac) c_ai = c.dict(zero=True) if 1 in c_ai: c_ai[1][0] = 2.0 psi = gd.zeros() c.add(psi, c_ai) d_avv = dict([(a, np.zeros((3, 3))) for a in c.my_atom_indices]) c.second_derivative(psi, d_avv) if 0 in d_avv: print(d_avv[0]) eps = 0.000001 d_aiv = c.dict(derivative=True) pos_av = np.dot(spos_ac, gd.cell_cv) for v in range(3): pos_av[0, v] += eps c.set_positions(np.dot(pos_av, gd.icell_cv.T)) c.derivative(psi, d_aiv) if 0 in d_aiv:
from gpaw.spline import Spline a = 4.0 gd = GridDescriptor(N_c=[16, 20, 20], cell_cv=[a, a + 1, a + 2], pbc_c=(0, 1, 1)) spos_ac = np.array([[0.25, 0.15, 0.35], [0.5, 0.5, 0.5]]) kpts_kc = None s = Spline(l=0, rmax=2.0, f_g=np.array([1, 0.9, 0.1, 0.0])) p = Spline(l=1, rmax=2.0, f_g=np.array([1, 0.9, 0.1, 0.0])) spline_aj = [[s], [s, p]] c = LFC(gd, spline_aj, cut=True, forces=True) c.set_positions(spos_ac) C_ani = c.dict(3, zero=True) if 1 in C_ani: C_ani[1][:, 1:] = np.eye(3) psi = gd.zeros(3) c.add(psi, C_ani) c.integrate(psi, C_ani) if 1 in C_ani: d = C_ani[1][:, 1:].diagonal() assert d.ptp() < 4e-6 C_ani[1][:, 1:] -= np.diag(d) assert abs(C_ani[1]).max() < 5e-17 d_aniv = c.dict(3, derivative=True) c.derivative(psi, d_aniv) if 1 in d_aniv: for v in range(3): assert abs(d_aniv[1][v - 1, 0, v] + 0.2144) < 5e-5 d_aniv[1][v - 1, 0, v] = 0 assert abs(d_aniv[1]).max() < 3e-16 eps = 0.0001
# Copyright (C) 2003 CAMP # Please see the accompanying LICENSE file for further information. from gpaw.grid_descriptor import GridDescriptor from gpaw.transformers import Transformer import time n = 6 gda = GridDescriptor((n,n,n)) gdb = gda.refine() gdc = gdb.refine() a = gda.zeros() b = gdb.zeros() c = gdc.zeros() inter = Transformer(gdb, gdc, 2).apply restr = Transformer(gdb, gda, 2).apply t = time.clock() for i in range(8*300): inter(b, c) print time.clock() - t t = time.clock() for i in range(8*3000): restr(b, a) print time.clock() - t
def dummy_kpt_test(): l = 0 rcut = 6. a = 5. k_kc = [(.5, .5, .5)]#[(0., 0., 0.), (0.5, 0.5, 0.5)] kcount = len(k_kc) dtype = complex r = np.arange(0., rcut, .01) spos_ac_ref = [(0., 0., 0.)]#, (.2, .2, .2)] spos_ac = [(0., 0., 0.), (.2, .2, .2)] ngaussians = 4 realgaussindex = (ngaussians - 1) / 2 rchars = np.linspace(1., rcut, ngaussians) splines = [] gaussians = [QuasiGaussian(1./rch**2., rcut) for rch in rchars] for g in gaussians: norm = get_norm(r, g(r), l) g.renormalize(norm) spline = Spline(l, r[-1], g(r)) splines.append(spline) refgauss = gaussians[realgaussindex] refspline = splines[realgaussindex] gd = GridDescriptor((60, 60, 60), (a,a,a), (1,1,1)) reflf_a = [create_localized_functions([refspline], gd, spos_c, dtype=dtype) for spos_c in spos_ac_ref] for reflf in reflf_a: reflf.set_phase_factors(k_kc) kpt_u = [KPoint([], gd, 1., 0, k, k, k_c, dtype) for k, k_c in enumerate(k_kc)] for kpt in kpt_u: kpt.allocate(1) kpt.f_n[0] = 1. psit_nG = gd.zeros(1, dtype=dtype) coef_xi = np.identity(1, dtype=dtype) integral = np.zeros((1, 1), dtype=dtype) for reflf in reflf_a: reflf.add(psit_nG, coef_xi, k=kpt.k) reflf.integrate(psit_nG, integral, k=kpt.k) kpt.psit_nG = psit_nG print 'ref norm', integral print 'calculating overlaps' os_kmii, oS_kmii = overlaps(l, gd, splines, kpt_u, spos_ac=spos_ac_ref) print 'done' lf_a = [create_localized_functions(splines, gd, spos_c, dtype=dtype) for spos_c in spos_ac] for lf in lf_a: lf.set_phase_factors(k_kc) s_kii = np.zeros((kcount, ngaussians, ngaussians), dtype=dtype) S_kii = np.zeros((kcount, ngaussians, ngaussians), dtype=dtype) for kpt in kpt_u: k = kpt.k all_integrals = np.zeros((1, ngaussians), dtype=dtype) tempgrids = gd.zeros(ngaussians, dtype=dtype) tempcoef_xi = np.identity(ngaussians, dtype=dtype) for lf in lf_a: lf.integrate(kpt.psit_nG, all_integrals, k=k) lf.add(tempgrids, tempcoef_xi, k=k) lf.integrate(tempgrids, s_kii[k], k=k) print 'all <phi|psi>' print all_integrals conj_integrals = np.conj(all_integrals) for i in range(ngaussians): for j in range(ngaussians): S_kii[k, i, j] = conj_integrals[0, i] * all_integrals[0, j] print 'handmade s_kmii' print s_kii print 'handmade S_ii' print S_kii s_kmii = s_kii.reshape(kcount, 1, ngaussians, ngaussians) S_kmii = S_kii.reshape(kcount, 1, ngaussians, ngaussians) print 'matrices from overlap function' print 's_kmii' print os_kmii print 'S_kmii' print oS_kmii optimizer = CoefficientOptimizer(s_kmii, S_kmii, ngaussians) coefficients = optimizer.find_coefficients() optimizer2 = CoefficientOptimizer(os_kmii, oS_kmii, ngaussians) coefficients2 = optimizer2.find_coefficients() print 'coefs' print coefficients print 'overlaps() coefs' print coefficients2 print 'badness' print optimizer.evaluate(coefficients) exactsolution = [0.] * ngaussians exactsolution[realgaussindex] = 1. print 'badness of exact solution' print optimizer.evaluate(exactsolution) orbital = LinearCombination(coefficients, gaussians) orbital2 = LinearCombination(coefficients2, gaussians) norm = get_norm(r, orbital(r), l) norm2 = get_norm(r, orbital2(r), l) orbital.renormalize(norm) orbital2.renormalize(norm2) import pylab pylab.plot(r, refgauss(r), label='ref') pylab.plot(r, orbital(r), label='opt') pylab.plot(r, orbital2(r), '--', label='auto') pylab.legend() pylab.show()
from math import sqrt, pi import numpy as np from gpaw.setup import create_setup from gpaw.grid_descriptor import GridDescriptor from gpaw.localized_functions import create_localized_functions from gpaw.xc import XC n = 60#40 /8 * 10 a = 10.0 gd = GridDescriptor((n, n, n), (a, a, a)) c_LL = np.identity(9, float) a_Lg = gd.zeros(9) nspins = 2 xc = XC('LDA') for soft in [False]: s = create_setup('Cu', xc, lmax=2) ghat_l = s.ghat_l ghat_Lg = create_localized_functions(ghat_l, gd, (0.54321, 0.5432, 0.543)) a_Lg[:] = 0.0 ghat_Lg.add(a_Lg, c_LL) for l in range(3): for m in range(2 * l + 1): L = l**2 + m a_g = a_Lg[L] Q0 = gd.integrate(a_g) / sqrt(4 * pi) Q1_m = -gd.calculate_dipole_moment(a_g) / sqrt(4 * pi / 3) print Q0 if l == 0: Q0 -= 1.0 Q1_m[:] = 0.0 elif l == 1:
]])] for name, D, cell in cells: if name == 'Jelver': # Strange one! continue print('------------------') print(name, D) print(cell[0]) print(cell[1]) print(cell[2]) for n in range(1, 6): N = 2 * n + 2 gd = GridDescriptor((N, N, N), cell) b_g = gd.zeros() r_gv = gd.get_grid_point_coordinates().transpose((1, 2, 3, 0)) c_v = gd.cell_cv.sum(0) / 2 r_gv -= c_v lap = Laplace(gd, n=n) grad_v = [Gradient(gd, v, n=n) for v in range(3)] assert lap.npoints == D * 2 * n + 1 for m in range(0, 2 * n + 1): for ix in range(m + 1): for iy in range(m - ix + 1): iz = m - ix - iy a_g = (r_gv**(ix, iy, iz)).prod(3) if ix + iy + iz == 2 and max(ix, iy, iz) == 2: r = 2.0 else: r = 0.0
class UTDomainParallelSetup(TestCase): """ Setup a simple domain parallel calculation.""" # Number of bands nbands = 1 # Spin-paired nspins = 1 # Mean spacing and number of grid points per axis h = 0.2 / Bohr # Generic lattice constant for unit cell a = 5.0 / Bohr # Type of boundary conditions employed boundaries = None # Type of unit cell employed celltype = None def setUp(self): for virtvar in ['boundaries', 'celltype']: assert getattr(self,virtvar) is not None, 'Virtual "%s"!' % virtvar # Basic unit cell information: pbc_c = {'zero' : (False,False,False), \ 'periodic': (True,True,True), \ 'mixed' : (True, False, True)}[self.boundaries] a, b = self.a, 2**0.5*self.a cell_cv = {'general' : np.array([[0,a,a],[a/2,0,a/2],[a/2,a/2,0]]), 'rotated' : np.array([[0,0,b],[b/2,0,0],[0,b/2,0]]), 'inverted' : np.array([[0,0,b],[0,b/2,0],[b/2,0,0]]), 'orthogonal': np.diag([b, b/2, b/2])}[self.celltype] cell_cv = np.array([(4-3*pbc)*c_v for pbc,c_v in zip(pbc_c, cell_cv)]) # Decide how many kpoints to sample from the 1st Brillouin Zone kpts_c = np.ceil((10/Bohr)/np.sum(cell_cv**2,axis=1)**0.5).astype(int) kpts_c = tuple(kpts_c*pbc_c + 1-pbc_c) bzk_kc = kpts2ndarray(kpts_c) self.gamma = len(bzk_kc) == 1 and not bzk_kc[0].any() #p = InputParameters() #Z_a = self.atoms.get_atomic_numbers() #xcfunc = XC(p.xc) #setups = Setups(Z_a, p.setups, p.basis, p.lmax, xcfunc) #symmetry, weight_k, self.ibzk_kc = reduce_kpoints(self.atoms, bzk_kc, # setups, p.usesymm) self.ibzk_kc = bzk_kc.copy() # don't use symmetry reduction of kpoints self.nibzkpts = len(self.ibzk_kc) self.ibzk_kv = kpoint_convert(cell_cv, skpts_kc=self.ibzk_kc) # Parse parallelization parameters and create suitable communicators. #parsize, parsize_bands = create_parsize_minbands(self.nbands, world.size) parsize, parsize_bands = world.size//gcd(world.size, self.nibzkpts), 1 assert self.nbands % np.prod(parsize_bands) == 0 domain_comm, kpt_comm, band_comm = distribute_cpus(parsize, parsize_bands, self.nspins, self.nibzkpts) # Set up band descriptor: self.bd = BandDescriptor(self.nbands, band_comm) # Set up grid descriptor: N_c = np.round(np.sum(cell_cv**2, axis=1)**0.5 / self.h) N_c += 4-N_c % 4 # makes domain decomposition easier self.gd = GridDescriptor(N_c, cell_cv, pbc_c, domain_comm, parsize) self.assertEqual(self.gamma, np.all(~self.gd.pbc_c)) # What to do about kpoints? self.kpt_comm = kpt_comm if debug and world.rank == 0: comm_sizes = tuple([comm.size for comm in [world, self.bd.comm, \ self.gd.comm, self.kpt_comm]]) print '%d world, %d band, %d domain, %d kpt' % comm_sizes def tearDown(self): del self.ibzk_kc, self.ibzk_kv, self.bd, self.gd, self.kpt_comm # ================================= def verify_comm_sizes(self): if world.size == 1: return comm_sizes = tuple([comm.size for comm in [world, self.bd.comm, \ self.gd.comm, self.kpt_comm]]) self._parinfo = '%d world, %d band, %d domain, %d kpt' % comm_sizes self.assertEqual(self.nbands % self.bd.comm.size, 0) self.assertEqual((self.nspins*self.nibzkpts) % self.kpt_comm.size, 0) def verify_grid_volume(self): gdvol = np.prod(self.gd.get_size_of_global_array())*self.gd.dv self.assertAlmostEqual(self.gd.integrate(1+self.gd.zeros()), gdvol, 10) def verify_grid_point(self): # Volume integral of cartesian coordinates of all available grid points gdvol = np.prod(self.gd.get_size_of_global_array())*self.gd.dv cmr_v = self.gd.integrate(self.gd.get_grid_point_coordinates()) / gdvol # Theoretical center of cell based on all available grid data cm0_v = np.dot((0.5*(self.gd.get_size_of_global_array()-1.0) \ + 1.0-self.gd.pbc_c) / self.gd.N_c, self.gd.cell_cv) self.assertAlmostEqual(np.abs(cmr_v-cm0_v).max(), 0, 10) def verify_non_pbc_spacing(self): atoms = create_random_atoms(self.gd, 1000, 'NH3', self.a/2) pos_ac = atoms.get_positions() cellvol = np.linalg.det(self.gd.cell_cv) if debug: print 'cell volume:', np.abs(cellvol)*Bohr**3, 'Ang^3', cellvol>0 and '(right handed)' or '(left handed)' # Loop over non-periodic axes and check minimum distance requirement for c in np.argwhere(~self.gd.pbc_c).ravel(): a_v = self.gd.cell_cv[(c+1)%3] b_v = self.gd.cell_cv[(c+2)%3] c_v = np.cross(a_v, b_v) for d in range(2): # Inwards unit normal vector of d'th cell face of c'th axis # and point intersected by this plane (d=0,1 / bottom,top). n_v = np.sign(cellvol) * (1-2*d) * c_v / np.linalg.norm(c_v) if debug: print {0:'x',1:'y',2:'z'}[c]+'-'+{0:'bottom',1:'top'}[d]+':', n_v, 'Bohr' if debug: print 'gd.xxxiucell_cv[%d]~' % c, self.gd.xxxiucell_cv[c] / np.linalg.norm(self.gd.xxxiucell_cv[c]), 'Bohr' origin_v = np.dot(d * np.eye(3)[c], self.gd.cell_cv) d_a = np.dot(pos_ac/Bohr - origin_v[np.newaxis,:], n_v) if debug: print 'a:', self.a/2*Bohr, 'min:', np.min(d_a)*Bohr, 'max:', np.max(d_a)*Bohr self.assertAlmostEqual(d_a.min(), self.a/2, 0) #XXX digits!
from __future__ import print_function import numpy as np from gpaw.grid_descriptor import GridDescriptor from gpaw.xc.libvdwxc import vdw_df, vdw_df2, vdw_df_cx, \ vdw_optPBE, vdw_optB88, vdw_C09, vdw_beef, \ libvdwxc_has_mpi, libvdwxc_has_pfft # This test verifies that the results returned by the van der Waals # functionals implemented in libvdwxc do not change. N_c = np.array([23, 10, 6]) gd = GridDescriptor(N_c, N_c * 0.2, pbc_c=(1, 0, 1)) n_sg = gd.zeros(1) nG_sg = gd.collect(n_sg) if gd.comm.rank == 0: gen = np.random.RandomState(0) nG_sg[:] = gen.rand(*nG_sg.shape) gd.distribute(nG_sg, n_sg) for mode in ['serial', 'mpi', 'pfft']: if mode == 'serial' and gd.comm.size > 1: continue if mode == 'mpi' and not libvdwxc_has_mpi(): continue if mode == 'pfft' and not libvdwxc_has_pfft(): continue def test(vdwxcclass, Eref=np.nan, nvref=np.nan): xc = vdwxcclass(mode=mode) xc._initialize(gd)
from gpaw.fd_operators import Gradient import numpy as np from gpaw.grid_descriptor import GridDescriptor from gpaw.mpi import world if world.size > 4: # Grid is so small that domain decomposition cannot exceed 4 domains assert world.size % 4 == 0 group, other = divmod(world.rank, 4) ranks = np.arange(4 * group, 4 * (group + 1)) domain_comm = world.new_communicator(ranks) else: domain_comm = world gd = GridDescriptor((8, 1, 1), (8.0, 1.0, 1.0), comm=domain_comm) a = gd.zeros() dadx = gd.zeros() a[:, 0, 0] = np.arange(gd.beg_c[0], gd.end_c[0]) gradx = Gradient(gd, v=0) print a.itemsize, a.dtype, a.shape print dadx.itemsize, dadx.dtype, dadx.shape gradx.apply(a, dadx) # a = [ 0. 1. 2. 3. 4. 5. 6. 7.] # # da # -- = [-2.5 1. 1. 1. 1. 1. 1. -2.5] # dx dadx = gd.collect(dadx, broadcast=True) assert dadx[3, 0, 0] == 1.0 and np.sum(dadx[:, 0, 0]) == 0.0
def dummy_kpt_test(): l = 0 rcut = 6. a = 5. k_kc = [(.5, .5, .5)] #[(0., 0., 0.), (0.5, 0.5, 0.5)] kcount = len(k_kc) dtype = complex r = np.arange(0., rcut, .01) spos_ac_ref = [(0., 0., 0.)] #, (.2, .2, .2)] spos_ac = [(0., 0., 0.), (.2, .2, .2)] ngaussians = 4 realgaussindex = (ngaussians - 1) / 2 rchars = np.linspace(1., rcut, ngaussians) splines = [] gaussians = [QuasiGaussian(1. / rch**2., rcut) for rch in rchars] for g in gaussians: norm = get_norm(r, g(r), l) g.renormalize(norm) spline = Spline(l, r[-1], g(r)) splines.append(spline) refgauss = gaussians[realgaussindex] refspline = splines[realgaussindex] gd = GridDescriptor((60, 60, 60), (a, a, a), (1, 1, 1)) reflf_a = [ create_localized_functions([refspline], gd, spos_c, dtype=dtype) for spos_c in spos_ac_ref ] for reflf in reflf_a: reflf.set_phase_factors(k_kc) kpt_u = [ KPoint([], gd, 1., 0, k, k, k_c, dtype) for k, k_c in enumerate(k_kc) ] for kpt in kpt_u: kpt.allocate(1) kpt.f_n[0] = 1. psit_nG = gd.zeros(1, dtype=dtype) coef_xi = np.identity(1, dtype=dtype) integral = np.zeros((1, 1), dtype=dtype) for reflf in reflf_a: reflf.add(psit_nG, coef_xi, k=kpt.k) reflf.integrate(psit_nG, integral, k=kpt.k) kpt.psit_nG = psit_nG print 'ref norm', integral print 'calculating overlaps' os_kmii, oS_kmii = overlaps(l, gd, splines, kpt_u, spos_ac=spos_ac_ref) print 'done' lf_a = [ create_localized_functions(splines, gd, spos_c, dtype=dtype) for spos_c in spos_ac ] for lf in lf_a: lf.set_phase_factors(k_kc) s_kii = np.zeros((kcount, ngaussians, ngaussians), dtype=dtype) S_kii = np.zeros((kcount, ngaussians, ngaussians), dtype=dtype) for kpt in kpt_u: k = kpt.k all_integrals = np.zeros((1, ngaussians), dtype=dtype) tempgrids = gd.zeros(ngaussians, dtype=dtype) tempcoef_xi = np.identity(ngaussians, dtype=dtype) for lf in lf_a: lf.integrate(kpt.psit_nG, all_integrals, k=k) lf.add(tempgrids, tempcoef_xi, k=k) lf.integrate(tempgrids, s_kii[k], k=k) print 'all <phi|psi>' print all_integrals conj_integrals = np.conj(all_integrals) for i in range(ngaussians): for j in range(ngaussians): S_kii[k, i, j] = conj_integrals[0, i] * all_integrals[0, j] print 'handmade s_kmii' print s_kii print 'handmade S_ii' print S_kii s_kmii = s_kii.reshape(kcount, 1, ngaussians, ngaussians) S_kmii = S_kii.reshape(kcount, 1, ngaussians, ngaussians) print 'matrices from overlap function' print 's_kmii' print os_kmii print 'S_kmii' print oS_kmii optimizer = CoefficientOptimizer(s_kmii, S_kmii, ngaussians) coefficients = optimizer.find_coefficients() optimizer2 = CoefficientOptimizer(os_kmii, oS_kmii, ngaussians) coefficients2 = optimizer2.find_coefficients() print 'coefs' print coefficients print 'overlaps() coefs' print coefficients2 print 'badness' print optimizer.evaluate(coefficients) exactsolution = [0.] * ngaussians exactsolution[realgaussindex] = 1. print 'badness of exact solution' print optimizer.evaluate(exactsolution) orbital = LinearCombination(coefficients, gaussians) orbital2 = LinearCombination(coefficients2, gaussians) norm = get_norm(r, orbital(r), l) norm2 = get_norm(r, orbital2(r), l) orbital.renormalize(norm) orbital2.renormalize(norm2) import pylab pylab.plot(r, refgauss(r), label='ref') pylab.plot(r, orbital(r), label='opt') pylab.plot(r, orbital2(r), '--', label='auto') pylab.legend() pylab.show()
from gpaw.transformers import Transformer import numpy.random as ra from gpaw.grid_descriptor import GridDescriptor p = 0 n = 20 gd1 = GridDescriptor((n, n, n), (8.0, 8.0, 8.0), pbc_c=p) a1 = gd1.zeros() ra.seed(8) a1[:] = ra.random(a1.shape) gd2 = gd1.refine() a2 = gd2.zeros() i = Transformer(gd1, gd2).apply i(a1, a2) assert abs(gd1.integrate(a1) - gd2.integrate(a2)) < 1e-10 r = Transformer(gd2, gd1).apply a2[0] = 0.0 a2[:, 0] = 0.0 a2[:, :, 0] = 0.0 a2[-1] = 0.0 a2[:, -1] = 0.0 a2[:, :, -1] = 0.0 r(a2, a1) assert abs(gd1.integrate(a1) - gd2.integrate(a2)) < 1e-10
def playground(): np.set_printoptions(linewidth=176) #N_c = [4, 7, 9] N_c = [4, 4, 2] pbc_c = (1, 1, 1) # 210 distribute_dir = 1 reduce_dir = 0 parsize_c = (2, 2, 2) parsize2_c = list(parsize_c) parsize2_c[reduce_dir] = 1 parsize2_c[distribute_dir] *= parsize_c[reduce_dir] assert np.prod(parsize2_c) == np.prod(parsize_c) gd = GridDescriptor(N_c=N_c, pbc_c=pbc_c, cell_cv=0.2 * np.array(N_c), parsize_c=parsize_c) gd2 = get_compatible_grid_descriptor(gd, distribute_dir, reduce_dir) src = gd.zeros(dtype=complex) src[:] = gd.comm.rank src_global = gd.collect(src) if gd.comm.rank == 0: ind = np.indices(src_global.shape) src_global += 1j * (ind[0] / 10. + ind[1] / 100. + ind[2] / 1000.) #src_global[1] += 0.5j print('GLOBAL ARRAY', src_global.shape) print(src_global.squeeze()) gd.distribute(src_global, src) goal = gd2.zeros(dtype=float) goal[:] = gd.comm.rank # get_members()[gd2.comm.rank] goal_global = gd2.collect(goal) if gd.comm.rank == 0: print('GOAL GLOBAL') print(goal_global.squeeze()) gd.comm.barrier() #return recvbuf = redistribute(gd, gd2, src, distribute_dir, reduce_dir, operation='forth') recvbuf_master = gd2.collect(recvbuf) if gd2.comm.rank == 0: print('RECV') print(recvbuf_master) err = src_global - recvbuf_master print('MAXERR', np.abs(err).max()) hopefully_orig = redistribute(gd, gd2, recvbuf, distribute_dir, reduce_dir, operation='back') tmp = gd.collect(hopefully_orig) if gd.comm.rank == 0: print('FINALLY') print(tmp) err2 = src_global - tmp print('MAXERR', np.abs(err2).max())
from time import time from gpaw.grid_descriptor import GridDescriptor from gpaw.fd_operators import Laplace import gpaw.mpi as mpi n = 96 h = 0.1 L = n * h gd = GridDescriptor((n, n, n), [L, L, L]) # Allocate arrays: a = gd.zeros(100) + 1.2 b = gd.empty(100) o = Laplace(gd, 2).apply t0 = time() for r in range(10): o(a, b) if mpi.rank == 0: print time() - t0, a.shape
from gpaw.fftw import FFTPlan print(FFTPlan) for l in range(3): print(l) s = Spline(l, rc, 2 * x**1.5 / np.pi * np.exp(-x * r**2)) lfc1 = LFC(gd, [[s]], kd, dtype=complex) lfc2 = PWLFC([[s]], pd) c_axi = {0: np.zeros((1, 2 * l + 1), complex)} c_axi[0][0, 0] = 1.9 - 4.5j c_axiv = {0: np.zeros((1, 2 * l + 1, 3), complex)} b1 = gd.zeros(1, dtype=complex) b2 = pd.zeros(1, dtype=complex) for lfc, b in [(lfc1, b1), (lfc2, b2)]: lfc.set_positions(spos_ac) lfc.add(b, c_axi, 0) b2 = pd.ifft(b2[0]) * eikr equal(abs(b2 - b1[0]).max(), 0, 0.001) b1 = eikr[None] b2 = pd.fft(b1[0] * 0 + 1).reshape((1, -1)) results = [] results2 = [] for lfc, b in [(lfc1, b1), (lfc2, b2)]:
from gpaw.fd_operators import Gradient import numpy as np from gpaw.grid_descriptor import GridDescriptor from gpaw.mpi import world if world.size > 4: # Grid is so small that domain decomposition cannot exceed 4 domains assert world.size % 4 == 0 group, other = divmod(world.rank, 4) ranks = np.arange(4*group, 4*(group+1)) domain_comm = world.new_communicator(ranks) else: domain_comm = world gd = GridDescriptor((8, 1, 1), (8.0, 1.0, 1.0), comm=domain_comm) a = gd.zeros() dadx = gd.zeros() a[:, 0, 0] = np.arange(gd.beg_c[0], gd.end_c[0]) gradx = Gradient(gd, v=0) print a.itemsize, a.dtype, a.shape print dadx.itemsize, dadx.dtype, dadx.shape gradx.apply(a, dadx) # a = [ 0. 1. 2. 3. 4. 5. 6. 7.] # # da # -- = [-2.5 1. 1. 1. 1. 1. 1. -2.5] # dx dadx = gd.collect(dadx, broadcast=True) assert dadx[3, 0, 0] == 1.0 and np.sum(dadx[:, 0, 0]) == 0.0
from gpaw.response.math_func import two_phi_planewave_integrals # Initialize s, p, d (9 in total) wave and put them on grid rc = 2.0 a = 2.5 * rc n = 64 lmax = 2 b = 8.0 m = (lmax + 1)**2 gd = GridDescriptor([n, n, n], [a, a, a]) r = np.linspace(0, rc, 200) g = np.exp(-(r / rc * b)**2) splines = [Spline(l=l, rmax=rc, f_g=g) for l in range(lmax + 1)] c = LFC(gd, [splines]) c.set_positions([(0.5, 0.5, 0.5)]) psi = gd.zeros(m) d0 = c.dict(m) if 0 in d0: d0[0] = np.identity(m) c.add(psi, d0) # Calculate on 3d-grid < phi_i | e**(-ik.r) | phi_j > R_a = np.array([a / 2, a / 2, a / 2]) rr = gd.get_grid_point_coordinates() for dim in range(3): rr[dim] -= R_a[dim] k_G = np.array([[11., 0.2, 0.1], [10., 0., 10.]]) nkpt = k_G.shape[0] d0 = np.zeros((nkpt, m, m), dtype=complex)
if size == 1: for name, D, cell in cells: if name == 'Jelver': # Strange one! continue print('------------------') print(name, D) print(cell[0]) print(cell[1]) print(cell[2]) for n in range(1, 6): N = 2 * n + 2 gd = GridDescriptor((N, N, N), cell) b_g = gd.zeros() r_gv = gd.get_grid_point_coordinates().transpose((1, 2, 3, 0)) c_v = gd.cell_cv.sum(0) / 2 r_gv -= c_v lap = Laplace(gd, n=n) grad_v = [Gradient(gd, v, n=n) for v in range(3)] assert lap.npoints == D * 2 * n + 1 for m in range(0, 2 * n + 1): for ix in range(m + 1): for iy in range(m - ix + 1): iz = m - ix - iy a_g = (r_gv**(ix, iy, iz)).prod(3) if ix + iy + iz == 2 and max(ix, iy, iz) == 2: r = 2.0 else: r = 0.0
class DF(CHI): """This class defines dielectric function related physical quantities.""" def __init__(self, calc=None, nbands=None, w=None, q=None, eshift=None, ecut=10., density_cut=None, G_plus_q=False, eta=0.2, rpad=None, vcut=None, ftol=1e-7, txt=None, xc='ALDA', print_xc_scf=False, hilbert_trans=True, time_ordered=False, optical_limit=False, comm=None, kcommsize=None): CHI.__init__(self, calc=calc, nbands=nbands, w=w, q=q, eshift=eshift, ecut=ecut, density_cut=density_cut, G_plus_q=G_plus_q, eta=eta, rpad=rpad, vcut=vcut, ftol=ftol, txt=txt, xc=xc, hilbert_trans=hilbert_trans, time_ordered=time_ordered, optical_limit=optical_limit, comm=comm, kcommsize=kcommsize) self.df_flag = False self.print_bootstrap = print_xc_scf self.df1_w = None # NLF RPA self.df2_w = None # LF RPA self.df3_w = None # NLF ALDA self.df4_w = None # LF ALDA def get_dielectric_matrix(self, xc='RPA', overwritechi0=False, symmetric=True, chi0_wGG=None, calc=None, vcut=None, dir=None): if self.chi0_wGG is None and chi0_wGG is None: self.initialize() self.calculate() elif self.chi0_wGG is None and chi0_wGG is not None: #Read from file and reinitialize self.xc = xc from gpaw.response.parallel import par_read self.chi0_wGG = par_read(chi0_wGG, 'chi0_wGG') self.nvalbands = self.nbands #self.parallel_init() # parallelization not yet implemented self.Nw_local = self.Nw # parallelization not yet implemented if self.calc is None: from gpaw import GPAW self.calc = GPAW(calc, txt=None) if self.xc == 'ALDA' or self.xc == 'ALDA_X': from gpaw.response.kernel import calculate_Kxc from gpaw.grid_descriptor import GridDescriptor from gpaw.mpi import world, rank, size, serial_comm self.pbc = self.calc.atoms.pbc self.gd = GridDescriptor(self.calc.wfs.gd.N_c * self.rpad, self.acell_cv, pbc_c=True, comm=serial_comm) R_av = self.calc.atoms.positions / Bohr nt_sg = self.calc.density.nt_sG if (self.rpad > 1).any() or (self.pbc - True).any(): nt_sG = self.gd.zeros(self.nspins) #nt_sG = np.zeros([self.nspins, self.nG[0], self.nG[1], self.nG[2]]) for s in range(self.nspins): nt_G = self.pad(nt_sg[s]) nt_sG[s] = nt_G else: nt_sG = nt_sg self.Kxc_sGG = calculate_Kxc(self.gd, nt_sG, self.npw, self.Gvec_Gc, self.gd.N_c, self.vol, self.bcell_cv, R_av, self.calc.wfs.setups, self.calc.density.D_asp, functional=self.xc, density_cut=self.density_cut) if overwritechi0: dm_wGG = self.chi0_wGG else: dm_wGG = np.zeros_like(self.chi0_wGG) if dir is None: q_c = self.q_c else: q_c = np.diag((1, 1, 1))[dir] * self.qopt self.chi0_wGG[:, 0, :] = self.chi00G_wGv[:, :, dir] self.chi0_wGG[:, :, 0] = self.chi0G0_wGv[:, :, dir] from gpaw.response.kernel import calculate_Kc, CoulombKernel kernel = CoulombKernel(vcut=self.vcut, pbc=self.calc.atoms.pbc, cell=self.acell_cv) self.Kc_GG = kernel.calculate_Kc(q_c, self.Gvec_Gc, self.bcell_cv, symmetric=symmetric) #self.Kc_GG = calculate_Kc(q_c, # self.Gvec_Gc, # self.acell_cv, # self.bcell_cv, # self.pbc, # self.vcut, # symmetric=symmetric) tmp_GG = np.eye(self.npw, self.npw) if xc == 'RPA': self.printtxt('Use RPA.') for iw in range(self.Nw_local): dm_wGG[iw] = tmp_GG - self.Kc_GG * self.chi0_wGG[iw] elif xc == 'ALDA': self.printtxt('Use ALDA kernel.') # E_LDA = 1 - v_c chi0 (1-fxc chi0)^-1 # http://prb.aps.org/pdf/PRB/v33/i10/p7017_1 eq. 4 A_wGG = self.chi0_wGG.copy() for iw in range(self.Nw_local): A_wGG[iw] = np.dot( self.chi0_wGG[iw], np.linalg.inv(tmp_GG - np.dot(self.Kxc_sGG[0], self.chi0_wGG[iw]))) for iw in range(self.Nw_local): dm_wGG[iw] = tmp_GG - self.Kc_GG * A_wGG[iw] return dm_wGG def get_inverse_dielectric_matrix(self, xc='RPA'): dm_wGG = self.get_dielectric_matrix(xc=xc) dminv_wGG = np.zeros_like(dm_wGG) for iw in range(self.Nw_local): dminv_wGG[iw] = np.linalg.inv(dm_wGG[iw]) return dminv_wGG def get_chi(self, xc='RPA'): """Solve Dyson's equation.""" if self.chi0_wGG is None: self.initialize() self.calculate() else: pass # read from file and re-initializing .... need to be implemented kernel_GG = np.zeros((self.npw, self.npw), dtype=complex) chi_wGG = np.zeros_like(self.chi0_wGG) # Coulomb kernel for iG in range(self.npw): qG = np.dot(self.q_c + self.Gvec_Gc[iG], self.bcell_cv) kernel_GG[iG, iG] = 4 * pi / np.dot(qG, qG) if xc == 'ALDA': kernel_GG += self.Kxc_sGG[0] for iw in range(self.Nw_local): tmp_GG = np.eye(self.npw, self.npw) - np.dot( self.chi0_wGG[iw], kernel_GG) chi_wGG[iw] = np.dot(np.linalg.inv(tmp_GG), self.chi0_wGG[iw]) return chi_wGG def get_dielectric_function(self, xc='RPA', dir=None): """Calculate the dielectric function. Returns df1_w and df2_w. Parameters: df1_w: ndarray Dielectric function without local field correction. df2_w: ndarray Dielectric function with local field correction. """ if not self.optical_limit: assert dir is None if self.df_flag is False: dm_wGG = self.get_dielectric_matrix(xc=xc, dir=dir) Nw_local = dm_wGG.shape[0] dfNLF_w = np.zeros(Nw_local, dtype=complex) dfLFC_w = np.zeros(Nw_local, dtype=complex) df1_w = np.zeros(self.Nw, dtype=complex) df2_w = np.zeros(self.Nw, dtype=complex) for iw in range(Nw_local): tmp_GG = dm_wGG[iw] dfLFC_w[iw] = 1. / np.linalg.inv(tmp_GG)[0, 0] dfNLF_w[iw] = tmp_GG[0, 0] self.wcomm.all_gather(dfNLF_w, df1_w) self.wcomm.all_gather(dfLFC_w, df2_w) if xc == 'RPA': self.df1_w = df1_w self.df2_w = df2_w elif xc == 'ALDA' or xc == 'ALDA_X': self.df3_w = df1_w self.df4_w = df2_w if xc == 'RPA': return self.df1_w, self.df2_w elif xc == 'ALDA' or xc == 'ALDA_X': return self.df3_w, self.df4_w def get_surface_response_function(self, z0=0., filename='surf_EELS'): """Calculate surface response function.""" if self.chi0_wGG is None: self.initialize() self.calculate() g_w2 = np.zeros((self.Nw, 2), dtype=complex) assert self.acell_cv[0, 2] == 0. and self.acell_cv[1, 2] == 0. Nz = self.gd.N_c[2] # number of points in z direction tmp = np.zeros(Nz, dtype=int) nGz = 0 # number of G_z for i in range(self.npw): if self.Gvec_Gc[i, 0] == 0 and self.Gvec_Gc[i, 1] == 0: tmp[nGz] = self.Gvec_Gc[i, 2] nGz += 1 assert (np.abs(self.Gvec_Gc[:nGz, :2]) < 1e-10).all() for id, xc in enumerate(['RPA', 'ALDA']): chi_wGG = self.get_chi(xc=xc) # The first nGz are all Gx=0 and Gy=0 component chi_wgg_LFC = chi_wGG[:, :nGz, :nGz] del chi_wGG chi_wzz_LFC = np.zeros((self.Nw_local, Nz, Nz), dtype=complex) # Fourier transform of chi_wgg to chi_wzz Gz_g = tmp[:nGz] * self.bcell_cv[2, 2] z_z = np.linspace(0, self.acell_cv[2, 2] - self.gd.h_cv[2, 2], Nz) phase1_zg = np.exp(1j * np.outer(z_z, Gz_g)) phase2_gz = np.exp(-1j * np.outer(Gz_g, z_z)) for iw in range(self.Nw_local): chi_wzz_LFC[iw] = np.dot(np.dot(phase1_zg, chi_wgg_LFC[iw]), phase2_gz) chi_wzz_LFC /= self.acell_cv[2, 2] # Get surface response function z_z -= z0 / Bohr q_v = np.dot(self.q_c, self.bcell_cv) qq = sqrt(np.inner(q_v, q_v)) phase1_1z = np.array([np.exp(qq * z_z)]) phase2_z1 = np.exp(qq * z_z) tmp_w = np.zeros(self.Nw_local, dtype=complex) for iw in range(self.Nw_local): tmp_w[iw] = np.dot(np.dot(phase1_1z, chi_wzz_LFC[iw]), phase2_z1)[0] tmp_w *= -2 * pi / qq * self.gd.h_cv[2, 2]**2 g_w = np.zeros(self.Nw, dtype=complex) self.wcomm.all_gather(tmp_w, g_w) g_w2[:, id] = g_w if rank == 0: f = open(filename, 'w') for iw in range(self.Nw): energy = iw * self.dw * Hartree print(energy, np.imag(g_w2[iw, 0]), np.imag(g_w2[iw, 1]), file=f) f.close() # Wait for I/O to finish self.comm.barrier() def check_sum_rule(self, df1_w=None, df2_w=None): """Check f-sum rule.""" if df1_w is None: df1_w = self.df1_w df2_w = self.df2_w N1 = N2 = 0 for iw in range(self.Nw): w = iw * self.dw N1 += np.imag(df1_w[iw]) * w N2 += np.imag(df2_w[iw]) * w N1 *= self.dw * self.vol / (2 * pi**2) N2 *= self.dw * self.vol / (2 * pi**2) self.printtxt('') self.printtxt('Sum rule for ABS:') nv = self.nvalence self.printtxt('Without local field: N1 = %f, %f %% error' % (N1, (N1 - nv) / nv * 100)) self.printtxt('Include local field: N2 = %f, %f %% error' % (N2, (N2 - nv) / nv * 100)) N1 = N2 = 0 for iw in range(self.Nw): w = iw * self.dw N1 -= np.imag(1 / df1_w[iw]) * w N2 -= np.imag(1 / df2_w[iw]) * w N1 *= self.dw * self.vol / (2 * pi**2) N2 *= self.dw * self.vol / (2 * pi**2) self.printtxt('') self.printtxt('Sum rule for EELS:') nv = self.nvalence self.printtxt('Without local field: N1 = %f, %f %% error' % (N1, (N1 - nv) / nv * 100)) self.printtxt('Include local field: N2 = %f, %f %% error' % (N2, (N2 - nv) / nv * 100)) def get_macroscopic_dielectric_constant(self, xc='RPA'): """Calculate macroscopic dielectric constant. Returns eM1 and eM2 Macroscopic dielectric constant is defined as the real part of dielectric function at w=0. Parameters: eM1: float Dielectric constant without local field correction. (RPA, ALDA) eM2: float Dielectric constant with local field correction. """ assert self.optical_limit self.printtxt('') self.printtxt('%s Macroscopic Dielectric Constant:' % xc) dirstr = ['x', 'y', 'z'] for dir in range(3): eM = np.zeros(2) df1, df2 = self.get_dielectric_function(xc=xc, dir=dir) eps0 = np.real(df1[0]) eps = np.real(df2[0]) self.printtxt(' %s direction' % (dirstr[dir])) self.printtxt(' Without local field: %f' % eps0) self.printtxt(' Include local field: %f' % eps) return eps0, eps def get_absorption_spectrum(self, filename='Absorption.dat'): """Calculate optical absorption spectrum. By default, generate a file 'Absorption.dat'. Optical absorption spectrum is obtained from the imaginary part of dielectric function. """ assert self.optical_limit for dir in range(3): df1, df2 = self.get_dielectric_function(xc='RPA', dir=dir) if self.xc == 'ALDA': df3, df4 = self.get_dielectric_function(xc='ALDA', dir=dir) if self.xc == 'ALDA_X': df3, df4 = self.get_dielectric_function(xc='ALDA_X', dir=dir) Nw = df1.shape[0] if self.xc == 'Bootstrap': # bootstrap doesnt support all direction spectra yet from gpaw.response.fxc import Bootstrap Kc_GG = np.zeros((self.npw, self.npw)) q_c = np.diag((1, 1, 1))[dir] * self.qopt for iG in range(self.npw): qG = np.dot(q_c + self.Gvec_Gc[iG], self.bcell_cv) Kc_GG[iG, iG] = 4 * pi / np.dot(qG, qG) from gpaw.mpi import world assert self.wcomm.size == world.size df3 = Bootstrap(self.chi0_wGG, Nw, Kc_GG, self.printtxt, self.print_bootstrap, self.wcomm) if rank == 0: f = open('%s.%s' % (filename, 'xyz'[dir]), 'w') #f = open(filename+'.%s'%(dirstr[dir]),'w') # ???? for iw in range(Nw): energy = iw * self.dw * Hartree if self.xc == 'RPA': print(energy, np.real(df1[iw]), np.imag(df1[iw]), \ np.real(df2[iw]), np.imag(df2[iw]), file=f) elif self.xc == 'ALDA': print(energy, np.real(df1[iw]), np.imag(df1[iw]), \ np.real(df2[iw]), np.imag(df2[iw]), \ np.real(df3[iw]), np.imag(df3[iw]), \ np.real(df4[iw]), np.imag(df4[iw]), file=f) elif self.xc == 'Bootstrap': print(energy, np.real(df1[iw]), np.imag(df1[iw]), \ np.real(df2[iw]), np.imag(df2[iw]), \ np.real(df3[iw]), np.imag(df3[iw]), file=f) f.close() # Wait for I/O to finish self.comm.barrier() def get_EELS_spectrum(self, filename='EELS.dat'): """Calculate EELS spectrum. By default, generate a file 'EELS.dat'. EELS spectrum is obtained from the imaginary part of the inverse of dielectric function. """ # calculate RPA dielectric function df1, df2 = self.get_dielectric_function(xc='RPA') if self.xc == 'ALDA': df3, df4 = self.get_dielectric_function(xc='ALDA') Nw = df1.shape[0] if rank == 0: f = open(filename, 'w') for iw in range(self.Nw): energy = iw * self.dw * Hartree if self.xc == 'RPA': print(energy, -np.imag(1. / df1[iw]), -np.imag(1. / df2[iw]), file=f) elif self.xc == 'ALDA': print(energy, -np.imag(1./df1[iw]), -np.imag(1./df2[iw]), \ -np.imag(1./df3[iw]), -np.imag(1./df4[iw]), file=f) f.close() # Wait for I/O to finish self.comm.barrier() def get_jdos(self, f_skn, e_skn, kd, kq, dw, Nw, sigma): """Calculate Joint density of states""" JDOS_w = np.zeros(Nw) nbands = f_skn[0].shape[1] for k in range(kd.nbzkpts): print(k) ibzkpt1 = kd.bz2ibz_k[k] ibzkpt2 = kd.bz2ibz_k[kq[k]] for n in range(nbands): for m in range(nbands): focc = f_skn[0][ibzkpt1, n] - f_skn[0][ibzkpt2, m] w0 = e_skn[0][ibzkpt2, m] - e_skn[0][ibzkpt1, n] if focc > 0 and w0 >= 0: w0_id = int(w0 / dw) if w0_id + 1 < Nw: alpha = (w0_id + 1 - w0 / dw) / dw JDOS_w[w0_id] += focc * alpha alpha = (w0 / dw - w0_id) / dw JDOS_w[w0_id + 1] += focc * alpha w = np.arange(Nw) * dw * Hartree return w, JDOS_w def calculate_induced_density(self, q, w): """ Evaluate induced density for a certain q and w. Parameters: q: ndarray Momentum tranfer at reduced coordinate. w: scalar Energy (eV). """ if type(w) is int: iw = w w = self.wlist[iw] / Hartree elif type(w) is float: w /= Hartree iw = int(np.round(w / self.dw)) else: raise ValueError('Frequency not correct !') self.printtxt('Calculating Induced density at q, w (iw)') self.printtxt('(%f, %f, %f), %f(%d)' % (q[0], q[1], q[2], w * Hartree, iw)) # delta_G0 delta_G = np.zeros(self.npw) delta_G[0] = 1. # coef is (q+G)**2 / 4pi coef_G = np.zeros(self.npw) for iG in range(self.npw): qG = np.dot(q + self.Gvec_Gc[iG], self.bcell_cv) coef_G[iG] = np.dot(qG, qG) coef_G /= 4 * pi # obtain chi_G0(q,w) dm_wGG = self.get_RPA_dielectric_matrix() tmp_GG = dm_wGG[iw] del dm_wGG chi_G = (np.linalg.inv(tmp_GG)[:, 0] - delta_G) * coef_G gd = self.gd r = gd.get_grid_point_coordinates() # calculate dn(r,q,w) drho_R = gd.zeros(dtype=complex) for iG in range(self.npw): qG = np.dot(q + self.Gvec_Gc[iG], self.bcell_cv) qGr_R = np.inner(qG, r.T).T drho_R += chi_G[iG] * np.exp(1j * qGr_R) # phase = sum exp(iq.R_i) return drho_R def get_induced_density_z(self, q, w): """Get induced density on z axis (summation over xy-plane). """ drho_R = self.calculate_induced_density(q, w) drho_z = np.zeros(self.gd.N_c[2], dtype=complex) # dxdy = np.cross(self.h_c[0], self.h_c[1]) for iz in range(self.gd.N_c[2]): drho_z[iz] = drho_R[:, :, iz].sum() return drho_z def get_eigenmodes(self, filename=None, chi0=None, calc=None, dm=None, xc='RPA', sum=None, vcut=None, checkphase=False, return_full=False): """ Calculate the plasmonic eigenmodes as eigenvectors of the dielectric matrix. Parameters: filename: pckl file output from response calculation. chi0: gpw file chi0_wGG from response calculation. calc: gpaw calculator instance ground state calculator used in response calculation. Wavefunctions only needed if chi0 is calculated from scratch dm: gpw file dielectric matrix from response calculation xc: str 'RPA'or 'ALDA' XC- Kernel sum: str '2D': sum in the x and y directions '1D': To be implemented vcut: str '0D','1D' or '2D' Cut the Coulomb potential checkphase: Bool if True, the eigenfunctions id rotated in the complex plane, to be made as real as posible return_full: Bool if True, the eigenvectors in reciprocal space is also returned. """ self.read(filename) self.pbc = [1, 1, 1] #self.calc.atoms.pbc = [1,1,1] npw = self.npw self.w_w = np.linspace(0, self.dw * (self.Nw - 1) * Hartree, self.Nw) self.vcut = vcut dm_wGG = self.get_dielectric_matrix(xc=xc, symmetric=False, chi0_wGG=chi0, calc=calc, vcut=vcut) q = self.q_c # get grid on which the eigenmodes are calculated #gd = self.calc.wfs.gd #r = gd.get_grid_point_coordinates() #rrr = r*Bohr from gpaw.utilities.gpts import get_number_of_grid_points from gpaw.grid_descriptor import GridDescriptor grid_size = [1, 1, 1] h = 0.2 cell_cv = self.acell_cv * np.diag(grid_size) mode = 'fd' realspace = True h /= Bohr N_c = get_number_of_grid_points(cell_cv, h, mode, realspace) gd = GridDescriptor(N_c, cell_cv, self.pbc) #gd = self.calc.wfs.gd r = gd.get_grid_point_coordinates() rrr = r * Bohr eig_0 = np.array([], dtype=complex) eig_left = np.array([], dtype=complex) eig_right = np.array([], dtype=complex) vec_modes = np.zeros([1, self.npw], dtype=complex) vec_modes_dual = np.zeros([1, self.npw], dtype=complex) vec_modes_density = np.zeros([1, self.npw], dtype=complex) vec_modes_norm = np.zeros([1, self.npw], dtype=complex) eig_all = np.zeros([1, self.npw], dtype=complex) eig_dummy = np.zeros([1, self.npw], dtype=complex) v_dummy = np.zeros([1, self.npw], dtype=complex) vec_dummy = np.zeros([1, self.npw], dtype=complex) vec_dummy2 = np.zeros([1, self.npw], dtype=complex) w_0 = np.array([]) w_left = np.array([]) w_right = np.array([]) if sum == '2D': v_ind = np.zeros([1, r.shape[-1]], dtype=complex) n_ind = np.zeros([1, r.shape[-1]], dtype=complex) elif sum == '1D': self.printtxt('1D sum not implemented') return else: v_ind = np.zeros([1, r.shape[1], r.shape[2], r.shape[3]], dtype=complex) n_ind = np.zeros([1, r.shape[1], r.shape[2], r.shape[3]], dtype=complex) eps_GG_plus = dm_wGG[0] eig_plus, vec_plus = np.linalg.eig( eps_GG_plus) # find eigenvalues and eigenvectors vec_plus_dual = np.linalg.inv(vec_plus) # loop over frequencies, where the eigenvalues for the 2D matrix in G,G' are found. for i in np.array(range(self.Nw - 1)) + 1: eps_GG = eps_GG_plus eig, vec = eig_plus, vec_plus vec_dual = vec_plus_dual eps_GG_plus = dm_wGG[i] # epsilon_GG'(omega + d-omega) eig_plus, vec_plus = np.linalg.eig(eps_GG_plus) vec_plus_dual = np.linalg.inv(vec_plus) eig_dummy[0, :] = eig eig_all = np.append(eig_all, eig_dummy, axis=0) # append all eigenvalues to array # loop to check find the eigenvalues that crosses zero from negative to positive values: for k in range(self.npw): for m in range(self.npw): if eig[k] < 0 and 0 < eig_plus[m]: # check it's the same mode - Overlap between eigenvectors should be large: if abs(np.inner(vec[:, k], vec_plus_dual[m, :])) > 0.95: self.printtxt('crossing found at w = %1.1f eV' % self.w_w[i - 1]) eig_left = np.append(eig_left, eig[k]) eig_right = np.append(eig_right, eig_plus[m]) vec_dummy[0, :] = vec[:, k] vec_modes = np.append(vec_modes, vec_dummy, axis=0) vec_dummy[0, :] = vec_dual[k, :].T vec_modes_dual = np.append(vec_modes_dual, vec_dummy, axis=0) w1 = self.w_w[i - 1] w2 = self.w_w[i] a = np.real((eig_plus[m] - eig[k]) / (w2 - w1)) w0 = np.real(-eig[k]) / a + w1 eig0 = a * (w0 - w1) + eig[k] w_0 = np.append(w_0, w0) w_left = np.append(w_left, w1) eig_0 = np.append(eig_0, eig0) n_dummy = np.zeros( [1, r.shape[1], r.shape[2], r.shape[3]], dtype=complex) v_dummy = np.zeros( [1, r.shape[1], r.shape[2], r.shape[3]], dtype=complex) vec_n = np.zeros([self.npw]) for iG in range(self.npw): # Fourier transform qG = np.dot((q + self.Gvec_Gc[iG]), self.bcell_cv) coef_G = np.dot(qG, qG) / (4 * pi) qGr_R = np.inner(qG, r.T).T v_dummy += vec[iG, k] * np.exp(1j * qGr_R) n_dummy += vec[iG, k] * np.exp( 1j * qGr_R) * coef_G if checkphase: # rotate eigenvectors in complex plane integral = np.zeros([81]) phases = np.linspace(0, 2, 81) for ip in range(81): v_int = v_dummy * np.exp( 1j * pi * phases[ip]) integral[ip] = abs(np.imag(v_int)).sum() phase = phases[np.argsort(integral)][0] v_dummy *= np.exp(1j * pi * phase) n_dummy *= np.exp(1j * pi * phase) if sum == '2D': i_xyz = 3 v_dummy_z = np.zeros([1, v_dummy.shape[i_xyz]], dtype=complex) n_dummy_z = np.zeros([1, v_dummy.shape[i_xyz]], dtype=complex) v_dummy_z[0, :] = np.sum(np.sum(v_dummy, axis=1), axis=1)[0, :] n_dummy_z[0, :] = np.sum(np.sum(n_dummy, axis=1), axis=1)[0, :] v_ind = np.append(v_ind, v_dummy_z, axis=0) n_ind = np.append(n_ind, n_dummy_z, axis=0) elif sum == '1D': self.printtxt('1D sum not implemented') else: v_ind = np.append(v_ind, v_dummy, axis=0) n_ind = np.append(n_ind, n_dummy, axis=0) """ returns: grid points, frequency grid, all eigenvalues, mode energies, left point energies, mode eigenvalues, eigenvalues of left and right-side points, (mode eigenvectors, mode dual eigenvectors,) induced potential in real space, induced density in real space """ if return_full: return rrr, self.w_w, eig_all[1:], w_0, eig_0, w_left, eig_left, \ eig_right, vec_modes[1:], vec_modes_dual[1:], v_ind[1:], n_ind[1:] else: return rrr, self.w_w, eig_all[1:], w_0, eig_0, w_left, eig_left, \ eig_right, v_ind[1:], n_ind[1:] def project_chi_to_LCAO_pair_orbital(self, orb_MG): nLCAO = orb_MG.shape[0] N = np.zeros((self.Nw, nLCAO, nLCAO), dtype=complex) kcoulinv_GG = np.zeros((self.npw, self.npw)) for iG in range(self.npw): qG = np.dot(self.q_c + self.Gvec_Gc[iG], self.bcell_cv) kcoulinv_GG[iG, iG] = np.dot(qG, qG) kcoulinv_GG /= 4. * pi dm_wGG = self.get_RPA_dielectric_matrix() for mu in range(nLCAO): for nu in range(nLCAO): pairorb_R = orb_MG[mu] * orb_MG[nu] if not (pairorb_R * pairorb_R.conj() < 1e-10).all(): tmp_G = np.fft.fftn(pairorb_R) * self.vol / self.nG0 pairorb_G = np.zeros(self.npw, dtype=complex) for iG in range(self.npw): index = self.Gindex[iG] pairorb_G[iG] = tmp_G[index[0], index[1], index[2]] for iw in range(self.Nw): chi_GG = (dm_wGG[iw] - np.eye(self.npw)) * kcoulinv_GG N[iw, mu, nu] = (np.outer(pairorb_G.conj(), pairorb_G) * chi_GG).sum() # N[iw, mu, nu] = np.inner(pairorb_G.conj(),np.inner(pairorb_G, chi_GG)) return N def write(self, filename, all=False): """Dump essential data""" data = { 'nbands': self.nbands, 'acell': self.acell_cv, #* Bohr, 'bcell': self.bcell_cv, #/ Bohr, 'h_cv': self.gd.h_cv, #* Bohr, 'nG': self.gd.N_c, 'nG0': self.nG0, 'vol': self.vol, #* Bohr**3, 'BZvol': self.BZvol, #/ Bohr**3, 'nkpt': self.kd.nbzkpts, 'ecut': self.ecut, #* Hartree, 'npw': self.npw, 'eta': self.eta, #* Hartree, 'ftol': self.ftol, 'Nw': self.Nw, 'NwS': self.NwS, 'dw': self.dw, # * Hartree, 'q_red': self.q_c, 'q_car': self.qq_v, # / Bohr, 'qmod': np.dot(self.qq_v, self.qq_v), # / Bohr 'vcut': self.vcut, 'pbc': self.pbc, 'nvalence': self.nvalence, 'hilbert_trans': self.hilbert_trans, 'optical_limit': self.optical_limit, 'e_skn': self.e_skn, # * Hartree, 'f_skn': self.f_skn, 'bzk_kc': self.kd.bzk_kc, 'ibzk_kc': self.kd.ibzk_kc, 'kq_k': self.kq_k, 'Gvec_Gc': self.Gvec_Gc, 'dfNLFRPA_w': self.df1_w, 'dfLFCRPA_w': self.df2_w, 'dfNLFALDA_w': self.df3_w, 'dfLFCALDA_w': self.df4_w, 'df_flag': True } if all: from gpaw.response.parallel import par_write par_write('chi0' + filename, 'chi0_wGG', self.wcomm, self.chi0_wGG) if rank == 0: pickle.dump(data, open(filename, 'w'), -1) self.comm.barrier() def read(self, filename): """Read data from pickle file""" data = pickle.load(open(filename)) self.nbands = data['nbands'] self.acell_cv = data['acell'] self.bcell_cv = data['bcell'] self.nG0 = data['nG0'] self.vol = data['vol'] self.BZvol = data['BZvol'] self.ecut = data['ecut'] self.npw = data['npw'] self.eta = data['eta'] self.ftol = data['ftol'] self.Nw = data['Nw'] self.NwS = data['NwS'] self.dw = data['dw'] self.q_c = data['q_red'] self.qq_v = data['q_car'] self.qmod = data['qmod'] #self.vcut = data['vcut'] #self.pbc = data['pbc'] self.hilbert_trans = data['hilbert_trans'] self.optical_limit = data['optical_limit'] self.e_skn = data['e_skn'] self.f_skn = data['f_skn'] self.nvalence = data['nvalence'] self.kq_k = data['kq_k'] self.Gvec_Gc = data['Gvec_Gc'] self.df1_w = data['dfNLFRPA_w'] self.df2_w = data['dfLFCRPA_w'] self.df3_w = data['dfNLFALDA_w'] self.df4_w = data['dfLFCALDA_w'] self.df_flag = data['df_flag'] self.printtxt('Read succesfully !')
print(" %s'th moment = %2.6f" % (L, m)) equal(m, (L == 0) / sqrt(4 * pi), 1.5e-3) # Check that it is removed correctly v = gauss.remove_moment(nH, 0) m = gauss.get_moment(nH, 0) print("\nZero'th moment of compensated Hydrogen density =", m) equal(m, 0.0, 1e-7) # /-------------------------------------------------\ # | Check if Gaussian potentials are made correctly | # \-------------------------------------------------/ # Array for storing the potential pot = gd.zeros(dtype=float, global_array=False) for L in range(7): # Angular index of gaussian # Get analytic functions ng = gauss.get_gauss(L) vg = gauss.get_gauss_pot(L) # Solve potential numerically niter = solve(pot, ng, charge=None, zero_initial_phi=True) # Determine residual residual = norm(pot - vg) residual = gd.integrate((pot - vg) ** 2) ** 0.5 # print result print("L=%s, processor %s of %s: %s" % (L, gd.comm.rank + 1, gd.comm.size, residual))
class UTDomainParallelSetup(TestCase): """ Setup a simple domain parallel calculation.""" # Number of bands nbands = 1 # Spin-paired nspins = 1 # Mean spacing and number of grid points per axis h = 0.2 / Bohr # Generic lattice constant for unit cell a = 5.0 / Bohr # Type of boundary conditions employed boundaries = None # Type of unit cell employed celltype = None def setUp(self): for virtvar in ['boundaries', 'celltype']: assert getattr(self,virtvar) is not None, 'Virtual "%s"!' % virtvar # Basic unit cell information: pbc_c = {'zero' : (False,False,False), \ 'periodic': (True,True,True), \ 'mixed' : (True, False, True)}[self.boundaries] a, b = self.a, 2**0.5*self.a cell_cv = {'general' : np.array([[0,a,a],[a/2,0,a/2],[a/2,a/2,0]]), 'rotated' : np.array([[0,0,b],[b/2,0,0],[0,b/2,0]]), 'inverted' : np.array([[0,0,b],[0,b/2,0],[b/2,0,0]]), 'orthogonal': np.diag([b, b/2, b/2])}[self.celltype] cell_cv = np.array([(4-3*pbc)*c_v for pbc,c_v in zip(pbc_c, cell_cv)]) # Decide how many kpoints to sample from the 1st Brillouin Zone kpts_c = np.ceil((10/Bohr)/np.sum(cell_cv**2,axis=1)**0.5).astype(int) kpts_c = tuple(kpts_c*pbc_c + 1-pbc_c) bzk_kc = kpts2ndarray(kpts_c) self.gamma = len(bzk_kc) == 1 and not bzk_kc[0].any() #p = InputParameters() #Z_a = self.atoms.get_atomic_numbers() #xcfunc = XC(p.xc) #setups = Setups(Z_a, p.setups, p.basis, p.lmax, xcfunc) #symmetry, weight_k, self.ibzk_kc = reduce_kpoints(self.atoms, bzk_kc, # setups, p.usesymm) self.ibzk_kc = bzk_kc.copy() # don't use symmetry reduction of kpoints self.nibzkpts = len(self.ibzk_kc) self.ibzk_kv = kpoint_convert(cell_cv, skpts_kc=self.ibzk_kc) # Parse parallelization parameters and create suitable communicators. #parsize_domain, parsize_bands = create_parsize_minbands(self.nbands, world.size) parsize_domain, parsize_bands = world.size//gcd(world.size, self.nibzkpts), 1 assert self.nbands % np.prod(parsize_bands) == 0 domain_comm, kpt_comm, band_comm = distribute_cpus(parsize_domain, parsize_bands, self.nspins, self.nibzkpts) # Set up band descriptor: self.bd = BandDescriptor(self.nbands, band_comm) # Set up grid descriptor: N_c = np.round(np.sum(cell_cv**2, axis=1)**0.5 / self.h) N_c += 4-N_c % 4 # makes domain decomposition easier self.gd = GridDescriptor(N_c, cell_cv, pbc_c, domain_comm, parsize_domain) self.assertEqual(self.gamma, np.all(~self.gd.pbc_c)) # What to do about kpoints? self.kpt_comm = kpt_comm if debug and world.rank == 0: comm_sizes = tuple([comm.size for comm in [world, self.bd.comm, \ self.gd.comm, self.kpt_comm]]) print '%d world, %d band, %d domain, %d kpt' % comm_sizes def tearDown(self): del self.ibzk_kc, self.ibzk_kv, self.bd, self.gd, self.kpt_comm # ================================= def verify_comm_sizes(self): if world.size == 1: return comm_sizes = tuple([comm.size for comm in [world, self.bd.comm, \ self.gd.comm, self.kpt_comm]]) self._parinfo = '%d world, %d band, %d domain, %d kpt' % comm_sizes self.assertEqual(self.nbands % self.bd.comm.size, 0) self.assertEqual((self.nspins*self.nibzkpts) % self.kpt_comm.size, 0) def verify_grid_volume(self): gdvol = np.prod(self.gd.get_size_of_global_array())*self.gd.dv self.assertAlmostEqual(self.gd.integrate(1+self.gd.zeros()), gdvol, 10) def verify_grid_point(self): # Volume integral of cartesian coordinates of all available grid points gdvol = np.prod(self.gd.get_size_of_global_array())*self.gd.dv cmr_v = self.gd.integrate(self.gd.get_grid_point_coordinates()) / gdvol # Theoretical center of cell based on all available grid data cm0_v = np.dot((0.5*(self.gd.get_size_of_global_array()-1.0) \ + 1.0-self.gd.pbc_c) / self.gd.N_c, self.gd.cell_cv) self.assertAlmostEqual(np.abs(cmr_v-cm0_v).max(), 0, 10) def verify_non_pbc_spacing(self): atoms = create_random_atoms(self.gd, 1000, 'NH3', self.a/2) pos_ac = atoms.get_positions() cellvol = np.linalg.det(self.gd.cell_cv) if debug: print 'cell volume:', np.abs(cellvol)*Bohr**3, 'Ang^3', cellvol>0 and '(right handed)' or '(left handed)' # Loop over non-periodic axes and check minimum distance requirement for c in np.argwhere(~self.gd.pbc_c).ravel(): a_v = self.gd.cell_cv[(c+1)%3] b_v = self.gd.cell_cv[(c+2)%3] c_v = np.cross(a_v, b_v) for d in range(2): # Inwards unit normal vector of d'th cell face of c'th axis # and point intersected by this plane (d=0,1 / bottom,top). n_v = np.sign(cellvol) * (1-2*d) * c_v / np.linalg.norm(c_v) if debug: print {0:'x',1:'y',2:'z'}[c]+'-'+{0:'bottom',1:'top'}[d]+':', n_v, 'Bohr' if debug: print 'gd.xxxiucell_cv[%d]~' % c, self.gd.xxxiucell_cv[c] / np.linalg.norm(self.gd.xxxiucell_cv[c]), 'Bohr' origin_v = np.dot(d * np.eye(3)[c], self.gd.cell_cv) d_a = np.dot(pos_ac/Bohr - origin_v[np.newaxis,:], n_v) if debug: print 'a:', self.a/2*Bohr, 'min:', np.min(d_a)*Bohr, 'max:', np.max(d_a)*Bohr self.assertAlmostEqual(d_a.min(), self.a/2, 0) #XXX digits!
m = gauss.get_moment(nH, L) print(' %s\'th moment = %2.6f' % (L, m)) equal(m, (L == 0) / sqrt(4 * pi), 1.5e-3) # Check that it is removed correctly v = gauss.remove_moment(nH, 0) m = gauss.get_moment(nH, 0) print('\nZero\'th moment of compensated Hydrogen density =', m) equal(m, 0., 1e-7) # /-------------------------------------------------\ # | Check if Gaussian potentials are made correctly | # \-------------------------------------------------/ # Array for storing the potential pot = gd.zeros(dtype=float, global_array=False) for L in range(7): # Angular index of gaussian # Get analytic functions ng = gauss.get_gauss(L) vg = gauss.get_gauss_pot(L) # Solve potential numerically niter = solve(pot, ng, charge=None, zero_initial_phi=True) # Determine residual residual = norm(pot - vg) residual = gd.integrate((pot - vg)**2)**0.5 # print result print('L=%s, processor %s of %s: %s' % (L, gd.comm.rank + 1, gd.comm.size, residual))
def test(cellno, cellname, cell_cv, idiv, pbc, nn): N_c = h2gpts(0.12, cell_cv, idiv=idiv) if idiv == 1: N_c += 1 - N_c % 2 # We want especially to test uneven grids gd = GridDescriptor(N_c, cell_cv, pbc_c=pbc) rho_g = gd.zeros() phi_g = gd.zeros() rho_g[:] = -0.3 + rng.rand(*rho_g.shape) # Neutralize charge: charge = gd.integrate(rho_g) magic = gd.get_size_of_global_array().prod() rho_g -= charge / gd.dv / magic charge = gd.integrate(rho_g) assert abs(charge) < 1e-12 # Check use_cholesky=True/False ? from gpaw.poisson import FDPoissonSolver ps = FastPoissonSolver(nn=nn) #print('setgrid') # Will raise BadAxesError for some pbc/cell combinations ps.set_grid_descriptor(gd) ps.solve(phi_g, rho_g) laplace = Laplace(gd, scale=-1.0 / (4.0 * np.pi), n=nn) def get_residual_err(phi_g): rhotest_g = gd.zeros() laplace.apply(phi_g, rhotest_g) residual = np.abs(rhotest_g - rho_g) # Residual is not accurate at end of non-periodic directions # except for nn=1 (since effectively we use the right stencil # only for nn=1 at the boundary). # # To do this check correctly, the Laplacian should have lower # nn at the boundaries. Therefore we do not test the residual # at these ends, only in between, by zeroing the bad ones: if nn > 1: exclude_points = nn - 1 for c in range(3): if nn > 1 and not pbc[c]: # get view ehere axis c refers becomes zeroth dimension: X = residual.transpose(c, (c + 1) % 3, (c + 2) % 3) if gd.beg_c[c] == 1: X[:exclude_points] = 0.0 if gd.end_c[c] == gd.N_c[c]: X[-exclude_points:] = 0.0 return residual.max() maxerr = get_residual_err(phi_g) pbcstring = '{}{}{}'.format(*pbc) if 0: ps2 = FDPoissonSolver(relax='J', nn=nn, eps=1e-18) ps2.set_grid_descriptor(gd) phi2_g = gd.zeros() ps2.solve(phi2_g, rho_g) phimaxerr = np.abs(phi2_g - phi_g).max() maxerr2 = get_residual_err(phi2_g) msg = ('{:2d} {:8s} pbc={} err={:8.5e} err[J]={:8.5e} ' 'err[phi]={:8.5e} nn={:1d}' .format(cellno, cellname, pbcstring, maxerr, maxerr2, phimaxerr, nn)) state = 'ok' if maxerr < tolerance else 'FAIL' msg = ('{:2d} {:8s} grid={} pbc={} err[fast]={:8.5e} nn={:1d} {}' .format(cellno, cellname, N_c, pbcstring, maxerr, nn, state)) if world.rank == 0: print(msg) return maxerr
# Copyright (C) 2003 CAMP # Please see the accompanying LICENSE file for further information. from __future__ import print_function from gpaw.grid_descriptor import GridDescriptor from gpaw.transformers import Transformer import time n = 6 gda = GridDescriptor((n, n, n)) gdb = gda.refine() gdc = gdb.refine() a = gda.zeros() b = gdb.zeros() c = gdc.zeros() inter = Transformer(gdb, gdc, 2).apply restr = Transformer(gdb, gda, 2).apply t = time.clock() for i in range(8 * 300): inter(b, c) print(time.clock() - t) t = time.clock() for i in range(8 * 3000): restr(b, a) print(time.clock() - t)
from gpaw.fftw import FFTPlan print(FFTPlan) for l in range(3): print(l) s = Spline(l, rc, 2 * x**1.5 / np.pi * np.exp(-x * r**2)) lfc1 = LFC(gd, [[s]], kd, dtype=complex) lfc2 = PWLFC([[s]], pd) c_axi = {0: np.zeros((1, 2 * l + 1), complex)} c_axi[0][0, 0] = 1.9 - 4.5j c_axiv = {0: np.zeros((1, 2 * l + 1, 3), complex)} b1 = gd.zeros(1, dtype=complex) b2 = pd.zeros(1, dtype=complex) for lfc, b in [(lfc1, b1), (lfc2, b2)]: lfc.set_positions(spos_ac) lfc.add(b, c_axi, 0) b2 = pd.ifft(b2[0]) * eikr equal(abs(b2-b1[0]).max(), 0, 0.001) b1 = eikr[None] b2 = pd.fft(b1[0] * 0 + 1).reshape((1, -1)) results = [] results2 = [] for lfc, b in [(lfc1, b1), (lfc2, b2)]:
print('%.10e vs %.10e at %.10e is %s' % (x, y, tol, res)) else: from gpaw.test import equal # Model grid N = 16 N_c = np.array((1, 1, 3)) * N cell_c = N_c / float(N) gd = GridDescriptor(N_c, cell_c, False) # Construct model density coord_vg = gd.get_grid_point_coordinates() x_g = coord_vg[0, :] y_g = coord_vg[1, :] z_g = coord_vg[2, :] rho_g = gd.zeros() for z0 in [1, 2]: rho_g += 10 * (z_g - z0) * \ np.exp(-20 * np.sum((coord_vg.T - np.array([.5, .5, z0])).T**2, axis=0)) if do_plot: big_rho_g = gd.collect(rho_g) if gd.comm.rank == 0: import matplotlib.pyplot as plt fig, ax_ij = plt.subplots(3, 4, figsize=(20, 10)) ax_i = ax_ij.ravel() ploti = 0 Ng_c = gd.get_size_of_global_array() plt.sca(ax_i[ploti]) ploti += 1
import numpy as np from gpaw.lfc import LocalizedFunctionsCollection as LFC from gpaw.grid_descriptor import GridDescriptor from gpaw.spline import Spline gd = GridDescriptor([20, 16, 16], [(4, 2, 0), (0, 4, 0), (0, 0, 4)]) spos_ac = np.array([[0.252, 0.15, 0.35], [0.503, 0.5, 0.5]]) s = Spline(l=0, rmax=2.0, f_g=np.array([1, 0.9, 0.1, 0.0])) spline_aj = [[s], [s]] c = LFC(gd, spline_aj) c.set_positions(spos_ac) c_ai = c.dict(zero=True) if 1 in c_ai: c_ai[1][0] = 2.0 psi = gd.zeros() c.add(psi, c_ai) d_avv = dict([(a, np.zeros((3, 3))) for a in c.my_atom_indices]) c.second_derivative(psi, d_avv) if 0 in d_avv: print d_avv[0] eps = 0.000001 d_aiv = c.dict(derivative=True) pos_av = np.dot(spos_ac, gd.cell_cv) for v in range(3): pos_av[0, v] += eps c.set_positions(np.dot(pos_av, gd.icell_cv.T)) c.derivative(psi, d_aiv) if 0 in d_aiv: d0_v = d_aiv[0][0].copy()