def __init__(self, cell_cv, nk_c, txt=sys.stdout): self.nk_c = nk_c bigcell_cv = cell_cv * nk_c[:, np.newaxis] L_c = (np.linalg.inv(bigcell_cv)**2).sum(0)**-0.5 rc = 0.5 * L_c.min() print('Inner radius for %dx%dx%d Wigner-Seitz cell: %.3f Ang' % (tuple(nk_c) + (rc * Bohr, )), file=txt) self.a = 5 / rc print('Range-separation parameter: %.3f Ang^-1' % (self.a / Bohr), file=txt) # nr_c = [get_efficient_fft_size(2 * int(L * self.a * 1.5)) nr_c = [get_efficient_fft_size(2 * int(L * self.a * 3.0)) for L in L_c] print('FFT size for calculating truncated Coulomb: %dx%dx%d' % tuple(nr_c), file=txt) self.gd = GridDescriptor(nr_c, bigcell_cv, comm=mpi.serial_comm) v_R = self.gd.empty() v_i = v_R.ravel() pos_iv = self.gd.get_grid_point_coordinates().reshape((3, -1)).T corner_jv = np.dot(np.indices((2, 2, 2)).reshape((3, 8)).T, bigcell_cv) for i, pos_v in enumerate(pos_iv): r = ((pos_v - corner_jv)**2).sum(axis=1).min()**0.5 if r == 0: v_i[i] = 2 * self.a / pi**0.5 else: v_i[i] = erf(self.a * r) / r self.K_Q = np.fft.fftn(v_R) * self.gd.dv
def initialize_clgd(self): N_c = get_number_of_grid_points(self.cl.cell, self.cl.spacing) self.cl.spacing = np.diag(self.cl.cell) / N_c self.cl.gd = GridDescriptor(N_c, self.cl.cell, False, self.cl.dcomm, self.cl.dparsize) self.cl.gd_global = GridDescriptor(N_c, self.cl.cell, False, serial_comm, None) self.cl.extrapolated_qm_phi = self.cl.gd.empty()
class WignerSeitzTruncatedCoulomb: def __init__(self, cell_cv, nk_c, txt=sys.stdout): self.nk_c = nk_c bigcell_cv = cell_cv * nk_c[:, np.newaxis] L_c = (np.linalg.inv(bigcell_cv)**2).sum(0)**-0.5 rc = 0.5 * L_c.min() prnt('Inner radius for %dx%dx%d Wigner-Seitz cell: %.3f Ang' % (tuple(nk_c) + (rc * Bohr, )), file=txt) self.a = 5 / rc prnt('Range-separation parameter: %.3f Ang^-1' % (self.a / Bohr), file=txt) # nr_c = [get_efficient_fft_size(2 * int(L * self.a * 1.5)) nr_c = [get_efficient_fft_size(2 * int(L * self.a * 3.0)) for L in L_c] prnt('FFT size for calculating truncated Coulomb: %dx%dx%d' % tuple(nr_c), file=txt) self.gd = GridDescriptor(nr_c, bigcell_cv, comm=mpi.serial_comm) v_R = self.gd.empty() v_i = v_R.ravel() pos_iv = self.gd.get_grid_point_coordinates().reshape((3, -1)).T corner_jv = np.dot(np.indices((2, 2, 2)).reshape((3, 8)).T, bigcell_cv) for i, pos_v in enumerate(pos_iv): r = ((pos_v - corner_jv)**2).sum(axis=1).min()**0.5 if r == 0: v_i[i] = 2 * self.a / pi**0.5 else: v_i[i] = erf(self.a * r) / r self.K_Q = np.fft.fftn(v_R) * self.gd.dv def get_potential(self, pd): q_c = pd.kd.bzk_kc[0] shift_c = (q_c * self.nk_c).round().astype(int) max_c = self.gd.N_c // 2 K_G = pd.zeros() N_c = pd.gd.N_c for G, Q in enumerate(pd.Q_qG[0]): Q_c = (np.unravel_index(Q, N_c) + N_c // 2) % N_c - N_c // 2 Q_c = Q_c * self.nk_c + shift_c if (abs(Q_c) < max_c).all(): K_G[G] = self.K_Q[tuple(Q_c)] G2_G = pd.G2_qG[0] a = self.a if pd.kd.gamma: K_G[0] += pi / a**2 else: K_G[0] += 4 * pi * (1 - np.exp(-G2_G[0] / (4 * a**2))) / G2_G[0] K_G[1:] += 4 * pi * (1 - np.exp(-G2_G[1:] / (4 * a**2))) / G2_G[1:] assert pd.dtype == complex return K_G
class WignerSeitzTruncatedCoulomb: def __init__(self, cell_cv, nk_c, txt=sys.stdout): self.nk_c = nk_c bigcell_cv = cell_cv * nk_c[:, np.newaxis] L_c = (np.linalg.inv(bigcell_cv)**2).sum(0)**-0.5 rc = 0.5 * L_c.min() prnt('Inner radius for %dx%dx%d Wigner-Seitz cell: %.3f Ang' % (tuple(nk_c) + (rc * Bohr,)), file=txt) self.a = 5 / rc prnt('Range-separation parameter: %.3f Ang^-1' % (self.a / Bohr), file=txt) # nr_c = [get_efficient_fft_size(2 * int(L * self.a * 1.5)) nr_c = [get_efficient_fft_size(2 * int(L * self.a * 3.0)) for L in L_c] prnt('FFT size for calculating truncated Coulomb: %dx%dx%d' % tuple(nr_c), file=txt) self.gd = GridDescriptor(nr_c, bigcell_cv, comm=mpi.serial_comm) v_R = self.gd.empty() v_i = v_R.ravel() pos_iv = self.gd.get_grid_point_coordinates().reshape((3, -1)).T corner_jv = np.dot(np.indices((2, 2, 2)).reshape((3, 8)).T, bigcell_cv) for i, pos_v in enumerate(pos_iv): r = ((pos_v - corner_jv)**2).sum(axis=1).min()**0.5 if r == 0: v_i[i] = 2 * self.a / pi**0.5 else: v_i[i] = erf(self.a * r) / r self.K_Q = np.fft.fftn(v_R) * self.gd.dv def get_potential(self, pd): q_c = pd.kd.bzk_kc[0] shift_c = (q_c * self.nk_c).round().astype(int) max_c = self.gd.N_c // 2 K_G = pd.zeros() N_c = pd.gd.N_c for G, Q in enumerate(pd.Q_qG[0]): Q_c = (np.unravel_index(Q, N_c) + N_c // 2) % N_c - N_c // 2 Q_c = Q_c * self.nk_c + shift_c if (abs(Q_c) < max_c).all(): K_G[G] = self.K_Q[tuple(Q_c)] G2_G = pd.G2_qG[0] a = self.a if pd.kd.gamma: K_G[0] += pi / a**2 else: K_G[0] += 4 * pi * (1 - np.exp(-G2_G[0] / (4 * a**2))) / G2_G[0] K_G[1:] += 4 * pi * (1 - np.exp(-G2_G[1:] / (4 * a**2))) / G2_G[1:] assert pd.dtype == complex return K_G
def setUp(self): for virtvar in ['boundaries']: assert getattr(self, virtvar) is not None, 'Virtual "%s"!' % virtvar # Basic unit cell information: res, N_c = shapeopt(100, self.G**3, 3, 0.2) #N_c = 4*np.round(np.array(N_c)/4) # makes domain decomposition easier cell_cv = self.h * np.diag(N_c) pbc_c = {'zero' : (False,False,False), \ 'periodic': (True,True,True), \ 'mixed' : (True, False, True)}[self.boundaries] # Create randomized gas-like atomic configuration on interim grid tmpgd = GridDescriptor(N_c, cell_cv, pbc_c) self.atoms = create_random_atoms(tmpgd) # Create setups Z_a = self.atoms.get_atomic_numbers() assert 1 == self.nspins self.setups = Setups(Z_a, p.setups, p.basis, p.lmax, xc) self.natoms = len(self.setups) # 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) self.bzk_kc = kpts2ndarray(kpts_c) # Set up k-point descriptor self.kd = KPointDescriptor(self.bzk_kc, self.nspins) self.kd.set_symmetry(self.atoms, self.setups, p.usesymm) # Set the dtype if self.kd.gamma: self.dtype = float else: self.dtype = complex # Create communicators parsize, parsize_bands = self.get_parsizes() assert self.nbands % np.prod(parsize_bands) == 0 domain_comm, kpt_comm, band_comm = distribute_cpus( parsize, parsize_bands, self.nspins, self.kd.nibzkpts) self.kd.set_communicator(kpt_comm) # Set up band descriptor: self.bd = BandDescriptor(self.nbands, band_comm) # Set up grid descriptor: self.gd = GridDescriptor(N_c, cell_cv, pbc_c, domain_comm, parsize) # Set up kpoint/spin descriptor (to be removed): self.kd_old = KPointDescriptorOld(self.nspins, self.kd.nibzkpts, kpt_comm, self.kd.gamma, self.dtype)
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 __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 extend_grid(gd, N_cd): N_cd = np.array(N_cd) N_c = gd.N_c + N_cd.sum(axis=1) cell_cv = gd.h_cv * N_c move_c = gd.get_grid_spacings() * N_cd[:,0] egd = GridDescriptor(N_c, cell_cv, gd.pbc_c, gd.comm) egd.extend_N_cd = N_cd return egd, cell_cv*Bohr, move_c*Bohr
def extend_grid(gd, N_cd): N_cd = np.array(N_cd) N_c = gd.N_c + N_cd.sum(axis=1) cell_cv = gd.h_cv * N_c move_c = gd.get_grid_spacings() * N_cd[:, 0] egd = GridDescriptor(N_c, cell_cv, gd.pbc_c, gd.comm) egd.extend_N_cd = N_cd return egd, cell_cv * Bohr, move_c * Bohr
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 initialize_more_things(self): if self.alphas: from gpaw.mpi import SerialCommunicator scale_c1 = (self.shape / (1.0 * self.gd.N_c))[:, np.newaxis] gdfft = GridDescriptor(self.shape, self.gd.cell_cv * scale_c1, True, comm=SerialCommunicator()) k_k = construct_reciprocal(gdfft)[0][:, :, :self.shape[2] // 2 + 1]**0.5 k_k[0, 0, 0] = 0.0 self.dj_k = k_k / (2 * pi / self.rcut) self.j_k = self.dj_k.astype(int) self.dj_k -= self.j_k self.dj_k *= 2 * pi / self.rcut if self.verbose: print('VDW: density array size:', self.gd.get_size_of_global_array()) print('VDW: zero-padded array size:', self.shape) print(('VDW: maximum kinetic energy: %.3f Hartree' % (0.5 * k_k.max()**2))) assert self.j_k.max() < self.Nr // 2, ('Use larger Nr than %i.' % self.Nr) else: self.dj_k = None self.j_k = None
def read_3D(self, file, filetype=None): """Read the density from a 3D file""" if filetype is None: # estimate file type from name ending filetype = file.split('.')[-1] filetype.lower() if filetype == 'plt': data, cell = read_plt(file) pbc_c = [True, True, True] N_c = np.array(data.shape) for c in range(3): if N_c[c] % 2 == 1: pbc_c[c] = False N_c[c] += 1 self.gd = GridDescriptor(N_c, cell.diagonal() / Bohr, pbc_c) self.offset_c = [int(not a) for a in self.gd.pbc_c] else: raise NotImplementedError('unknown file type "' + filetype + '"') self.file = file self.ldos = np.array(data * Bohr**3, np.float)
def __init__(self, cell_cv, nk_c, txt=sys.stdout): self.nk_c = nk_c bigcell_cv = cell_cv * nk_c[:, np.newaxis] L_c = (np.linalg.inv(bigcell_cv)**2).sum(0)**-0.5 rc = 0.5 * L_c.min() prnt('Inner radius for %dx%dx%d Wigner-Seitz cell: %.3f Ang' % (tuple(nk_c) + (rc * Bohr,)), file=txt) self.a = 5 / rc prnt('Range-separation parameter: %.3f Ang^-1' % (self.a / Bohr), file=txt) # nr_c = [get_efficient_fft_size(2 * int(L * self.a * 1.5)) nr_c = [get_efficient_fft_size(2 * int(L * self.a * 3.0)) for L in L_c] prnt('FFT size for calculating truncated Coulomb: %dx%dx%d' % tuple(nr_c), file=txt) self.gd = GridDescriptor(nr_c, bigcell_cv, comm=mpi.serial_comm) v_R = self.gd.empty() v_i = v_R.ravel() pos_iv = self.gd.get_grid_point_coordinates().reshape((3, -1)).T corner_jv = np.dot(np.indices((2, 2, 2)).reshape((3, 8)).T, bigcell_cv) for i, pos_v in enumerate(pos_iv): r = ((pos_v - corner_jv)**2).sum(axis=1).min()**0.5 if r == 0: v_i[i] = 2 * self.a / pi**0.5 else: v_i[i] = erf(self.a * r) / r self.K_Q = np.fft.fftn(v_R) * self.gd.dv
def setUp(self): for virtvar in ['boundaries']: assert getattr(self,virtvar) is not None, 'Virtual "%s"!' % virtvar parsize_domain, parsize_bands = create_parsize_minbands(self.nbands, world.size) assert self.nbands % np.prod(parsize_bands) == 0 comms = distribute_cpus(parsize_domain, parsize_bands, self.nspins, self.nibzkpts) domain_comm, kpt_comm, band_comm, block_comm = \ [comms[name] for name in 'dkbK'] self.block_comm = block_comm # Set up band descriptor: self.bd = BandDescriptor(self.nbands, band_comm) # Set up grid descriptor: res, ngpts = shapeopt(300, self.G**3, 3, 0.2) cell_c = self.h * np.array(ngpts) pbc_c = {'zero' : False, \ 'periodic': True, \ 'mixed' : (True, False, True)}[self.boundaries] self.gd = GridDescriptor(ngpts, cell_c, pbc_c, domain_comm, parsize_domain) # What to do about kpoints? self.kpt_comm = kpt_comm
def test_coulomb(N=2**6, a=20): Nc = (N, N, N) # Number of grid point gd = GridDescriptor(Nc, (a, a, a), True) # grid-descriptor object xyz, r2 = coordinates( gd) # matrix with the square of the radial coordinate r = np.sqrt(r2) # matrix with the values of the radial coordinate nH = np.exp(-2 * r) / pi # density of the hydrogen atom C = Coulomb(gd) # coulomb calculator if world.size > 1: C.load('real') t0 = time.time() print('Processor %s of %s: %s Ha in %s sec' % (gd.comm.rank + 1, gd.comm.size, -0.5 * C.coulomb(nH, method='real'), time.time() - t0)) return else: C.load('recip_ewald') C.load('recip_gauss') C.load('real') test = {} t0 = time.time() test['dual density'] = (-0.5 * C.coulomb(nH, nH.copy()), time.time() - t0) for method in ('real', 'recip_gauss', 'recip_ewald'): t0 = time.time() test[method] = (-0.5 * C.coulomb(nH, method=method), time.time() - t0) return test
def setUp(self): for virtvar in ['dtype', 'parstride_bands']: assert getattr(self, virtvar) is not None, 'Virtual "%s"!' % virtvar parsize, parsize_bands = create_parsize_maxbands( self.nbands, world.size) 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, self.parstride_bands) # Set up grid descriptor: res, ngpts = shapeopt(100, self.G**3, 3, 0.2) cell_c = self.h * np.array(ngpts) pbc_c = (True, False, True) self.gd = GridDescriptor(ngpts, cell_c, pbc_c, domain_comm, parsize) # Create Kohn-Sham layouts for these band and grid descriptors: self.ksl = self.create_kohn_sham_layouts() # What to do about kpoints? self.kpt_comm = kpt_comm
def set_grid_descriptor(self, gd): if (self.gd is not None and (self.gd.N_c == gd.N_c).all() and (self.gd.pbc_c == gd.pbc_c).all() and (self.gd.cell_cv == gd.cell_cv).all()): return VDWFunctional.set_grid_descriptor(self, gd) if self.size is None: self.shape = gd.N_c.copy() for c, n in enumerate(self.shape): if not gd.pbc_c[c]: self.shape[c] = int(2**ceil(log(n) / log(2))) else: self.shape = np.array(self.size) scale_c1 = (self.shape / (1.0 * gd.N_c))[:, np.newaxis] gdfft = GridDescriptor(self.shape, gd.cell_cv * scale_c1, True) k_k = construct_reciprocal(gdfft)[0][:, :, :self.shape[2] // 2 + 1]**0.5 k_k[0, 0, 0] = 0.0 self.dj_k = k_k / (2 * pi / self.rcut) self.j_k = self.dj_k.astype(int) self.dj_k -= self.j_k self.dj_k *= 2 * pi / self.rcut assert self.j_k.max() < self.Nr // 2, 'Use larger Nr.' if self.verbose: print 'VDW: density array size:', gd.get_size_of_global_array() print 'VDW: zero-padded array size:', self.shape print('VDW: maximum kinetic energy: %.3f Hartree' % (0.5 * k_k.max()**2))
def get_combined_data(self, qmdata=None, cldata=None, spacing=None): if qmdata is None: qmdata = self.density.rhot_g if cldata is None: cldata = self.classical_material.charge_density if spacing is None: spacing = self.cl.gd.h_cv[0, 0] spacing_au = spacing / Bohr # from Angstroms to a.u. # Collect data from different processes cln = self.cl.gd.collect(cldata) qmn = self.qm.gd.collect(qmdata) clgd = GridDescriptor(self.cl.gd.N_c, self.cl.cell, False, serial_comm, None) if world.rank == 0: cln *= self.classical_material.sign # refine classical part while clgd.h_cv[0, 0] > spacing_au * 1.50: # 45: cln = Transformer(clgd, clgd.refine()).apply(cln) clgd = clgd.refine() # refine quantum part qmgd = GridDescriptor(self.qm.gd.N_c, self.qm.cell, False, serial_comm, None) while qmgd.h_cv[0, 0] < clgd.h_cv[0, 0] * 0.95: qmn = Transformer(qmgd, qmgd.coarsen()).apply(qmn) qmgd = qmgd.coarsen() assert np.all(qmgd.h_cv == clgd.h_cv ), " Spacings %.8f (qm) and %.8f (cl) Angstroms" % ( qmgd.h_cv[0][0] * Bohr, clgd.h_cv[0][0] * Bohr) # now find the corners r_gv_cl = clgd.get_grid_point_coordinates().transpose((1, 2, 3, 0)) cind = self.qm.corner1 / np.diag(clgd.h_cv) - 1 n = qmn.shape # print 'Corner points: ', self.qm.corner1*Bohr, ' - ', self.qm.corner2*Bohr # print 'Calculated points: ', r_gv_cl[tuple(cind)]*Bohr, ' - ', r_gv_cl[tuple(cind+n+1)]*Bohr cln[cind[0] + 1:cind[0] + n[0] + 1, cind[1] + 1:cind[1] + n[1] + 1, cind[2] + 1:cind[2] + n[2] + 1] += qmn world.barrier() return cln, clgd
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 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 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 get_combined_data(self, qmdata=None, cldata=None, spacing=None): if qmdata is None: qmdata = self.density.rhot_g if cldata is None: cldata = self.classical_material.charge_density if spacing is None: spacing = self.cl.gd.h_cv[0, 0] spacing_au = spacing / Bohr # from Angstroms to a.u. # Collect data from different processes cln = self.cl.gd.collect(cldata) qmn = self.qm.gd.collect(qmdata) clgd = GridDescriptor(self.cl.gd.N_c, self.cl.cell, False, serial_comm, None) if world.rank == 0: cln *= self.classical_material.sign # refine classical part while clgd.h_cv[0, 0] > spacing_au * 1.50: # 45: cln = Transformer(clgd, clgd.refine()).apply(cln) clgd = clgd.refine() # refine quantum part qmgd = GridDescriptor(self.qm.gd.N_c, self.qm.cell, False, serial_comm, None) while qmgd.h_cv[0, 0] < clgd.h_cv[0, 0] * 0.95: qmn = Transformer(qmgd, qmgd.coarsen()).apply(qmn) qmgd = qmgd.coarsen() assert np.all(qmgd.h_cv == clgd.h_cv), " Spacings %.8f (qm) and %.8f (cl) Angstroms" % (qmgd.h_cv[0][0] * Bohr, clgd.h_cv[0][0] * Bohr) # now find the corners r_gv_cl = clgd.get_grid_point_coordinates().transpose((1, 2, 3, 0)) cind = self.qm.corner1 / np.diag(clgd.h_cv) - 1 n = qmn.shape # print 'Corner points: ', self.qm.corner1*Bohr, ' - ', self.qm.corner2*Bohr # print 'Calculated points: ', r_gv_cl[tuple(cind)]*Bohr, ' - ', r_gv_cl[tuple(cind+n+1)]*Bohr cln[cind[0] + 1:cind[0] + n[0] + 1, cind[1] + 1:cind[1] + n[1] + 1, cind[2] + 1:cind[2] + n[2] + 1] += qmn world.barrier() return cln, clgd
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 solve_mesh(self, X, Y, Z, pot, dens0, permitivity): gd = GridDescriptor([X.shape[0] + 1, X.shape[1] + 1, X.shape[2] + 1], cell_cv=[ X[0, -1, 0] - X[0, 0, 0], Y[-1, 0, 0] - Y[0, 0, 0], Z[0, 0, -1] - Z[0, 0, 0] ], pbc_c=False) self.set_grid_descriptor(gd) self.solve(pot, dens0, permitivity)
def interpolate_weight(calc, weight, h=0.05, n=2): '''interpolates cdft weight function, gd is the fine grid ''' gd = calc.density.finegd weight = gd.collect(weight, broadcast=True) weight = gd.zero_pad(weight) w = np.zeros_like(weight) gd1 = GridDescriptor(gd.N_c, gd.cell_cv, comm=serial_comm) gd1.distribute(weight, w) N_c = h2gpts(h / Bohr, gd.cell_cv) N_c = np.array([get_efficient_fft_size(N, n) for N in N_c]) gd2 = GridDescriptor(N_c, gd.cell_cv, comm=serial_comm) interpolator = Interpolator(gd1, gd2) W = interpolator.interpolate(w) return W
def go(comm, ngpts, repeat, narrays, out, prec): N_c = np.array((ngpts, ngpts, ngpts)) a = 10.0 gd = GridDescriptor(N_c, (a, a, a), comm=comm)) gdcoarse = gd.coarsen() gdfine = gd.refine() kin1 = Laplace(gd, -0.5, 1).apply laplace = Laplace(gd, -0.5, 2) kin2 = laplace.apply restrict = Transformer(gd, gdcoarse, 1).apply interpolate = Transformer(gd, gdfine, 1).apply precondition = Preconditioner(gd, laplace, np_float) a1 = gd.empty(narrays) a1[:] = 1.0 a2 = gd.empty(narrays) c = gdcoarse.empty(narrays) f = gdfine.empty(narrays) T = [0, 0, 0, 0, 0] for i in range(repeat): comm.barrier() kin1(a1, a2) comm.barrier() t0a = time() kin1(a1, a2) t0b = time() comm.barrier() t1a = time() kin2(a1, a2) t1b = time() comm.barrier() t2a = time() for A, C in zip(a1,c): restrict(A, C) t2b = time() comm.barrier() t3a = time() for A, F in zip(a1,f): interpolate(A, F) t3b = time() comm.barrier() if prec: t4a = time() for A in a1: precondition(A, None, None, None) t4b = time() comm.barrier() T[0] += t0b - t0a T[1] += t1b - t1a T[2] += t2b - t2a T[3] += t3b - t3a if prec: T[4] += t4b - t4a if mpi.rank == 0: out.write(' %2d %2d %2d' % tuple(gd.parsize_c)) out.write(' %12.6f %12.6f %12.6f %12.6f %12.6f\n' % tuple([t / repeat / narrays for t in T])) out.flush()
def __init__(self, calc, h=0.05, n=2): """Create transformation object. calc: GPAW calculator object The calcalator that has the wave functions. h: float Desired grid-spacing in Angstrom. n: int Force number of points to be a mulitiple of n. """ self.calc = calc gd = calc.wfs.gd gd1 = GridDescriptor(gd.N_c, gd.cell_cv, comm=serial_comm) # Descriptor for the final grid: N_c = h2gpts(h / Bohr, gd.cell_cv) N_c = np.array([get_efficient_fft_size(N, n) for N in N_c]) gd2 = self.gd = GridDescriptor(N_c, gd.cell_cv, comm=serial_comm) self.interpolator = Interpolator(gd1, gd2, self.calc.wfs.dtype) self.dphi = None # PAW correction (will be initialized when needed)
def __init__(self, cell_cv, nk_c, txt=None): txt = txt or sys.stdout self.nk_c = nk_c bigcell_cv = cell_cv * nk_c[:, np.newaxis] L_c = (np.linalg.inv(bigcell_cv)**2).sum(0)**-0.5 rc = 0.5 * L_c.min() print('Inner radius for %dx%dx%d Wigner-Seitz cell: %.3f Ang' % (tuple(nk_c) + (rc * Bohr,)), file=txt) self.a = 5 / rc print('Range-separation parameter: %.3f Ang^-1' % (self.a / Bohr), file=txt) nr_c = [get_efficient_fft_size(2 * int(L * self.a * 3.0)) for L in L_c] print('FFT size for calculating truncated Coulomb: %dx%dx%d' % tuple(nr_c), file=txt) self.gd = GridDescriptor(nr_c, bigcell_cv, comm=mpi.serial_comm) v_ijk = self.gd.empty() pos_ijkv = self.gd.get_grid_point_coordinates().transpose((1, 2, 3, 0)) corner_xv = np.dot(np.indices((2, 2, 2)).reshape((3, 8)).T, bigcell_cv) # Ignore division by zero (in 0,0,0 corner): with seterr(invalid='ignore'): # Loop over first dimension to avoid too large ndarrays. for pos_jkv, v_jk in zip(pos_ijkv, v_ijk): # Distances to the 8 corners: d_jkxv = pos_jkv[:, :, np.newaxis] - corner_xv r_jk = (d_jkxv**2).sum(axis=3).min(2)**0.5 v_jk[:] = erf(self.a * r_jk) / r_jk # Fix 0/0 corner value: v_ijk[0, 0, 0] = 2 * self.a / pi**0.5 self.K_Q = np.fft.fftn(v_ijk) * self.gd.dv
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 extended_grid_descriptor(gd, extend_N_cd=None, N_c=None, extcomm=None): """Create grid descriptor for extended grid. Provide only either extend_N_cd or N_c. Parameters: extend_N_cd: ndarray, int Number of extra grid points per axis (c) and direction (d, left or right) N_c: ndarray, int Number of grid points in extended grid extcomm: Communicator for the extended grid, defaults to gd.comm """ if extcomm is None: extcomm = gd.comm if extend_N_cd is None: assert N_c is not None, 'give only extend_N_cd or N_c' N_c = np.array(N_c, dtype=np.int) extend_N_cd = np.tile((N_c - gd.N_c) // 2, (2, 1)).T else: # extend_N_cd is not None: assert N_c is None, 'give only extend_N_cd or N_c' extend_N_cd = np.array(extend_N_cd, dtype=np.int) N_c = gd.N_c + extend_N_cd.sum(axis=1) cell_cv = gd.h_cv * N_c move_c = gd.get_grid_spacings() * extend_N_cd[:, 0] egd = GridDescriptor(N_c, cell_cv, gd.pbc_c, extcomm) egd.extend_N_cd = extend_N_cd return egd, cell_cv * Bohr, move_c * Bohr
def rigorous_testing(): from itertools import product, permutations, cycle from gpaw.mpi import world gridpointcounts = [1, 2, 10, 21] cpucounts = np.arange(1, world.size + 1) pbc = cycle(product([0, 1], [0, 1], [0, 1])) # This yields all possible parallelizations! for parsize_c in product(cpucounts, cpucounts, cpucounts): if np.prod(parsize_c) != world.size: continue # All possible grid point counts for N_c in product(gridpointcounts, gridpointcounts, gridpointcounts): # We simply can't be bothered to also do all possible # combinations with PBCs. Trying every possible set of # boundary conditions at least ones should be quite fine # enough. pbc_c = next(pbc) for dirs in permutations([0, 1, 2]): independent_dir, distribute_dir, reduce_dir = dirs parsize2_c = list(parsize_c) parsize2_c[reduce_dir] = 1 parsize2_c[distribute_dir] *= parsize_c[reduce_dir] parsize2_c = tuple(parsize2_c) assert np.prod(parsize2_c) == np.prod(parsize_c) try: 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) #gd2 = gd.new_descriptor(parsize_c=parsize2_c) except ValueError: # Skip illegal distributions continue if gd.comm.rank == 1: #print(gd, gd2) print( 'N_c=%s[%s] redist %s -> %s [ind=%d dist=%d red=%d]' % (N_c, pbc_c, parsize_c, parsize2_c, independent_dir, distribute_dir, reduce_dir)) gd.comm.barrier() test(N_c, gd, gd2, reduce_dir, distribute_dir, verbose=False)
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 apply_t(self): """Apply kinetic energy operator and return new object.""" p = 2 # padding newsize_c = self.size_c + 2 * p gd = GridDescriptor(N_c=newsize_c + 1, cell_cv=self.gd.h_c * (newsize_c + 1), pbc_c=False, comm=mpi.serial_comm) T = Laplace(gd, scale =1/2., n=p) f_ig = np.zeros((len(self.f_iG),) + tuple(newsize_c)) f_ig[:, p:-p, p:-p, p:-p] = self.f_iG Tf_iG = np.empty_like(f_ig) T.apply(f_ig, Tf_iG) return LocalizedFunctions(self.gd, Tf_iG, self.corner_c - p, self.index)
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 get_electrostatic_potential(self, ae=True, rcgauss=0.02): ham = self.calc.hamiltonian if ham.vHt_g is None: self.calc.restore_state() gd = ham.finegd v_r = gd.zero_pad(ham.vHt_g) gd1 = GridDescriptor(gd.N_c, gd.cell_cv, comm=serial_comm) interpolator = Interpolator(gd1, self.gd) v_R = interpolator.interpolate(v_r) if ae: alpha = 1 / (rcgauss / Bohr)**2 self.add_potential_correction(v_R, alpha) return v_R * Hartree
def set_grid_descriptor(self, gd): if self.size is None: self.shape = gd.N_c.copy() for c, n in enumerate(self.shape): if not gd.pbc_c[c]: # self.shape[c] = get_efficient_fft_size(n) self.shape[c] = int(2**ceil(log(n) / log(2))) else: self.shape = np.array(self.size) for c, n in enumerate(self.shape): if gd.pbc_c[c]: assert n == gd.N_c[c] else: assert n >= gd.N_c[c] if self.alphas: scale_c1 = (self.shape / (1.0 * gd.N_c))[:, np.newaxis] gdfft = GridDescriptor(self.shape, gd.cell_cv * scale_c1, True) k_k = construct_reciprocal(gdfft)[0][:, :, :self.shape[2] // 2 + 1]**0.5 k_k[0, 0, 0] = 0.0 self.dj_k = k_k / (2 * pi / self.rcut) self.j_k = self.dj_k.astype(int) self.dj_k -= self.j_k self.dj_k *= 2 * pi / self.rcut if self.verbose: print('VDW: density array size:', gd.get_size_of_global_array()) print('VDW: zero-padded array size:', self.shape) print(('VDW: maximum kinetic energy: %.3f Hartree' % (0.5 * k_k.max()**2))) assert self.j_k.max( ) < self.Nr // 2, 'Use larger Nr than %i.' % self.Nr else: self.dj_k = None self.j_k = None
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)
from time import time from gpaw.transformers import Transformer from gpaw.grid_descriptor import GridDescriptor from gpaw.mpi import world ngpts = 80 N_c = (ngpts, ngpts, ngpts) a = 10.0 gd = GridDescriptor(N_c, (a, a, a)) gdfine = gd.refine() interpolate = Transformer(gd, gdfine, 3).apply a1 = gd.empty() a1[:] = 1.0 f = gdfine.empty() ta = time() r = 600 for i in range(r): interpolate(a1, f) tb = time() n = 8 * (1 + 2 + 4) * ngpts**3 print '%.3f GFlops' % (r * n / (tb - ta) * 1e-9) """ python: 0.330 GFlops mpirun -np 2 gpaw-python: 0.500 GFlops gpaw-python + OMP: 0.432 GFlops """
n[-1, i] -= 0.000002 Em = xc.calculate_spherical(rgd, n, v) x2 = (Ep - Em) / 0.000002 print(name, nspins, E, x, x2, x - x2) equal(x, x2, 1e-9) n[-1, i] += 0.000001 if nspins == 1: ns = rgd.empty(2) ns[:] = n / 2 Es = xc.calculate_spherical(rgd, ns, 0 * ns) equal(E, Es, 1e-13) N = 20 a = 1.0 gd = GridDescriptor((N, N, N), (a, a, a)) for name in ['LDA', 'PBE']: xc = XC(name) for nspins in [1, 2]: n = gd.empty(nspins) n.fill(0.03) z = np.arange(gd.beg_c[2], gd.end_c[2]) * a / N n[:] += 0.01 * np.sin(2 * pi * z / a) if nspins == 2: n[1] += 0.01 * np.cos(2 * pi * z / a) n /= nspins v = 0.0 * n E = xc.calculate(gd, n, v)
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
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 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
assert np.prod(D) * B == world.size, 'D=%s, B=%d, W=%d' % (D,B,world.size) # Set up communicators: comms = distribute_cpus(parsize_domain=D, parsize_bands=B, nspins=1, nibzkpts=1) domain_comm, kpt_comm, band_comm, block_comm = \ [comms[name] for name in ['d', 'k', 'b', 'K']] assert kpt_comm.size == 1 if world.rank == 0: print('MPI: %d domains, %d band groups' % (domain_comm.size, band_comm.size)) # Set up band and grid descriptors: bd = BandDescriptor(N, band_comm, False) gd = GridDescriptor((G, G, G), (a, a, a), True, domain_comm, parsize=D) ksl = BandLayouts(gd, bd, block_comm, float) # Random wave functions: psit_mG = gd.empty(M) for m in range(M): np.random.seed(world.rank * M + m) psit_mG[m] = np.random.uniform(-0.5, 0.5, tuple(gd.n_c)) if world.rank == 0: print('Size of wave function array:', psit_mG.shape) P_ani = {0: psit_mG[:, :2, 0, 0].copy(), 1: psit_mG[:, -1, -1, -3:].copy()} kin = Laplace(gd, -0.5, 2).apply vt_G = gd.empty() vt_G.fill(0.567)
from time import time import numpy as np from gpaw.mpi import world, size, rank from gpaw.utilities.blas import gemm from gpaw.mic.micblas import gemm as mic_gemm import pymic import sys device = pymic.devices[0] stream = device.get_default_stream() gpts = int(sys.argv[1]) nbands = int(sys.argv[2]) repeats = 10 gd = GridDescriptor([gpts, gpts, gpts], comm=world, parsize=size) a = gd.empty(nbands) b = gd.empty(nbands) np.random.seed(10) a[:] = np.random.random(a.shape) b[:] = np.random.random(b.shape) c = np.zeros((nbands, nbands)) # warm-up for i in range(3): gd.integrate(a, b, hermitian=False, _transposed_result=c) gemm(1.0, a, c, 0.0, b) # equal(np.sum(c), 3600.89536641, 1e-6) t0 = time()
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)
import numpy as np from gpaw.lfc import LocalizedFunctionsCollection as LFC 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
from gpaw.grid_descriptor import GridDescriptor from gpaw.fd_operators import Laplace from gpaw.test import equal import numpy as np import time import timeit import os import pyMIC as mic offload_enabled = os.environ.get("GPAW_OFFLOAD"); device = mic.devices[0] gpts = 64 gd = GridDescriptor([gpts, gpts, gpts]) a = gd.empty() # source b = gd.empty() # result np.random.seed(10) a[:] = np.random.random(a.shape) b[:] = np.zeros(b.shape) op = Laplace(gd, 1.0, 3) if offload_enabled: offl_a = device.bind(a) offl_b = device.bind(b) print "--------------------------------------------------------------"
from gpaw.utilities.gauss import Gaussian from gpaw.grid_descriptor import GridDescriptor from gpaw.test import equal from gpaw.mpi import world from gpaw.poisson import PoissonSolver def norm(a): return np.sqrt(np.sum(a.ravel() ** 2)) / len(a.ravel()) # Initialize classes a = 20 # Size of cell N = 48 # Number of grid points Nc = (N, N, N) # Number of grid points along each axis gd = GridDescriptor(Nc, (a, a, a), 0) # Grid-descriptor object solver = PoissonSolver(nn=3) # Numerical poisson solver solver.set_grid_descriptor(gd) solver.initialize() solve = solver.solve xyz, r2 = coordinates(gd) # Matrix with the square of the radial coordinate print(r2.shape) r = np.sqrt(r2) # Matrix with the values of the radial coordinate nH = np.exp(-2 * r) / pi # Density of the hydrogen atom gauss = Gaussian(gd) # An instance of Gaussian # /------------------------------------------------\ # | Check if Gaussian densities are made correctly | # \------------------------------------------------/ for gL in range(2, 9): g = gauss.get_gauss(gL) # a gaussian of gL'th order
from math import pi from gpaw.grid_descriptor import GridDescriptor from gpaw.xc import XC from gpaw.xc.noncollinear import NonCollinearLDAKernel, NonCollinearFunctional import numpy as np from gpaw.test import equal N = 20 a = 1.0 gd = GridDescriptor((N, N, N), (a, a, a)) for xc in [XC('LDA'), XC('PBE')]: n = gd.empty(2) n.fill(0.03) z = np.arange(gd.beg_c[2], gd.end_c[2]) * a / N n[:] += 0.01 * np.sin(2 * pi * z / a) n[1] += 0.02 + 0.01 * np.cos(2 * pi * z / a) n /= 2 v = 0.0 * n E = xc.calculate(gd, n, v) here = (gd.beg_c[0] <= 1 < gd.end_c[0] and gd.beg_c[1] <= 2 < gd.end_c[1] and gd.beg_c[2] <= 3 < gd.end_c[2]) if here: x = v[-1, 1, 2, 3] * gd.dv n[-1, 1, 2, 3] += 0.000001 Ep = xc.calculate(gd, n, v) if here: n[-1, 1, 2, 3] -= 0.000002
def abstract_boundary(self): # Abtract the effective potential, hartree potential, and average density #out from the electrode calculation. map = {'-': '0', '+': '1'} data = self.tio.read_data(filename='Lead_' + map[self.direction], option='Lead') nn = data['fine_N_c'][2] ns = data['nspins'] N_c = data['N_c'] cell_cv = data['cell_cv'] pbc_c = data['pbc_c'] #parsize_c = data['parsize_c'] if type(parsize_domain) is int: parsize_c = None assert parsize_domain == self.domain_comm.size else: parsize_c = parsize_domain if parsize_c is None: parsize_c = decompose_domain(N_c, self.domain_comm.size) parsize_c = np.array(parsize_c) d1 = N_c[0] // 2 d2 = N_c[1] // 2 vHt_g = data['vHt_g'] vt_sg = data['vt_sg'] nt_sg = data['nt_sg'] rhot_g = data['rhot_g'] vt_sG = data['vt_sG'] nt_sG = data['nt_sG'] self.D_asp = data['D_asp'] self.dH_asp = data['dH_asp'] gd = GridDescriptor(N_c, cell_cv, pbc_c, self.domain_comm, parsize_c) finegd = gd.refine() self.boundary_vHt_g = None self.boundary_vHt_g1 = None self.boundary_vt_sg_line = None self.boundary_nt_sg = None self.boundary_rhot_g_line = None self.boundary_vt_sG = None self.boundary_nt_sG = None if self.tio.domain_comm.rank == 0: self.boundary_vHt_g = self.slice(nn, vHt_g) self.boundary_nt_sg = self.slice(nn, nt_sg) if self.direction == '-': other_direction= '+' else: other_direction= '-' h = self.h_cz / 2.0 b_vHt_g0 = self.boundary_vHt_g.copy() b_vHt_g1 = self.boundary_vHt_g.copy() self.boundary_vHt_g = interpolate_array(b_vHt_g0, finegd, h, self.direction) self.boundary_vHt_g1 = interpolate_array(b_vHt_g1, finegd, h, other_direction) vt_sg = interpolate_array(vt_sg, finegd, h, self.direction) self.boundary_vt_sg_line = aa1d(vt_sg) self.boundary_nt_sg = interpolate_array(self.boundary_nt_sg, finegd, h, self.direction) rhot_g = interpolate_array(rhot_g, finegd, h, self.direction) self.boundary_rhot_g_line = aa1d(rhot_g) nn /= 2 h *= 2 self.boundary_vt_sG = self.slice(nn, vt_sG) self.boundary_nt_sG = self.slice(nn, nt_sG) self.boundary_vt_sG = interpolate_array(self.boundary_vt_sG, gd, h, self.direction) self.boundary_nt_sG = interpolate_array(self.boundary_nt_sG, gd, h, self.direction)
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:
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:]
h = 0.2 # grid spacing a = h * G # side length of box M = N // B # number of bands per block assert M * B == N D = world.size // B # number of domains assert D * B == world.size # Set up communicators: r = world.rank // D * D domain_comm = world.new_communicator(np.arange(r, r + D)) band_comm = world.new_communicator(np.arange(world.rank % D, world.size, D)) # Set up grid descriptor: gd = GridDescriptor((G, G, G), (a, a, a), True, domain_comm, parsize) # Random wave functions: np.random.seed(world.rank) psit_mG = np.random.uniform(-0.5, 0.5, size=(M,) + tuple(gd.n_c)) if world.rank == 0: print 'Size of wave function array:', psit_mG.shape # Send and receive buffers: send_mG = gd.empty(M) recv_mG = gd.empty(M) def run(): S_nn = overlap(psit_mG, send_mG, recv_mG) t1 = time()
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
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