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()
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 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 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 __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 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 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 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 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 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 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 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 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 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 __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 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 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 __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 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 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 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 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 get_electrostatic_potential(self, ae=True, rcgauss=0.02): """Interpolate electrostatic potential. Return value in eV. ae: bool Add PAW correction to get the all-electron potential. rcgauss: float Width of gaussian (in Angstrom) used to represent the nuclear charge. """ gd = self.calc.hamiltonian.finegd v_r = self.calc.get_electrostatic_potential() / Ha 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 * Ha
def setUp(self): for virtvar in ['equipartition']: assert getattr(self,virtvar) is not None, 'Virtual "%s"!' % virtvar kpts = {'even' : (12,1,2), \ 'prime': (23,1,1)}[self.equipartition] #primes = [i for i in xrange(50,1,-1) if ~np.any(i%np.arange(2,i)==0)] bzk_kc = kpts2ndarray(kpts) assert p.usesymm == None self.nibzkpts = len(bzk_kc) #parsize, parsize_bands = create_parsize_minbands(self.nbands, world.size) parsize, parsize_bands = 1, 1 #XXX 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, p.parallel['stridebands']) # Set up grid descriptor: res, ngpts = shapeopt(300, 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 randomized gas-like atomic configuration self.atoms = create_random_atoms(self.gd) # Create setups Z_a = self.atoms.get_atomic_numbers() self.setups = Setups(Z_a, p.setups, p.basis, p.lmax, xc) self.natoms = len(self.setups) # Set up kpoint descriptor: self.kd = KPointDescriptor(bzk_kc, self.nspins) self.kd.set_symmetry(self.atoms, self.setups, p.usesymm) self.kd.set_communicator(kpt_comm)
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