def load(self, method): """Make sure all necessary attributes have been initialized""" assert method in ('real', 'recip_gauss', 'recip_ewald'),\ str(method) + ' is an invalid method name,\n' +\ 'use either real, recip_gauss, or recip_ewald' if method.startswith('recip'): if self.gd.comm.size > 1: raise RuntimeError("Cannot do parallel FFT, use method='real'") if not hasattr(self, 'k2'): self.k2, self.N3 = construct_reciprocal(self.gd) if method.endswith('ewald') and not hasattr(self, 'ewald'): # cutoff radius assert self.gd.orthogonal rc = 0.5 * np.average(self.gd.cell_cv.diagonal()) # ewald potential: 1 - cos(k rc) self.ewald = (np.ones(self.gd.n_c) - np.cos(np.sqrt(self.k2) * rc)) # lim k -> 0 ewald / k2 self.ewald[0, 0, 0] = 0.5 * rc**2 elif method.endswith('gauss') and not hasattr(self, 'ng'): gauss = Gaussian(self.gd) self.ng = gauss.get_gauss(0) / sqrt(4 * pi) self.vg = gauss.get_gauss_pot(0) / sqrt(4 * pi) else: # method == 'real' if not hasattr(self, 'solve'): if self.poisson is not None: self.solve = self.poisson.solve else: solver = PoissonSolver(nn=2) solver.set_grid_descriptor(self.gd) solver.initialize(load_gauss=True) self.solve = solver.solve
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 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 _init(self): if self._initialized: return gd = self.grids[-1] k2_Q, N3 = construct_reciprocal(gd) self.poisson_factor_Q = 4.0 * np.pi / k2_Q self._initialized = True
def initialize(self, gd, load_gauss=False): # XXX this won't work now, but supposedly this class will be deprecated # in favour of FFTPoissonSolver, no? self.gd = gd if self.gd.comm.size > 1: raise RuntimeError('Cannot do parallel FFT.') self.k2, self.N3 = construct_reciprocal(self.gd) if load_gauss: gauss = Gaussian(self.gd) self.rho_gauss = gauss.get_gauss(0) self.phi_gauss = gauss.get_gauss_pot(0)
def set_q(self, q_c): """Set q-vector in case of Bloch-type charge distribution. Parameters ---------- q_c: ndarray q-vector in scaled coordinates of the reciprocal lattice vectors. """ if self.gd.comm.rank == 0: self.k2_Q, self.N3 = construct_reciprocal(self.gd, q_c=q_c)
def set_q(self, q_c): """Set q-vector in case of Bloch-type charge distribution. Parameters ---------- q_c: ndarray q-vector in scaled coordinates of the reciprocal lattice vectors. """ if self.gd.comm.rank == 0: if self.gd.comm.size > 1: raise RuntimeError( "This solver is obsolete:" + "domain decomposition support has been removed") self.k2_Q, self.N3 = construct_reciprocal(self.gd, q_c=q_c)
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] = 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 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 initialize(self): if self.gd.comm.rank == 0: self.k2_Q, self.N3 = construct_reciprocal(self.gd)
def initialize(self): """Construct reciprocal grid.""" if self.gd.comm.rank == 0: self.k2_Q, self.N3 = construct_reciprocal(self.gd)
def initialize(self): gd = self.transp_yz_1_x.gd2 k2_Q, N3 = construct_reciprocal(gd, distributed=True) self.poisson_factor_Q = 4.0 * np.pi / k2_Q
def initialize_metric(self, gd): self.gd = gd k2_Q, N3 = construct_reciprocal(self.gd) self.metric = ReciprocalMetric(self.weight, k2_Q) self.mR_G = gd.empty(dtype=complex)