def update_at_weights(self): if log.do_medium: log('Computing Becke weights.') # The list of radii is constructed to be as close as possible to # the original values used by Becke. radii = [] for number in self.numbers: if number == 1: radius = 0.35*angstrom # exception defined in Becke's paper else: radius = periodic[number].becke_radius if radius is None: # for cases not covered by Brag-Slater radius = periodic[number].cov_radius radii.append(radius) radii = np.array(radii) # Actual work pb = log.progress(self.natom) for index in xrange(self.natom): grid = self.get_grid(index) at_weights = self.cache.load('at_weights', index, alloc=grid.shape)[0] at_weights[:] = 1 becke_helper_atom(grid.points, at_weights, radii, self.coordinates, index, self._k) pb()
def update_centers(self, system): if self.subgrids is None: raise RuntimeError('It is only possible to update the centers of a molecular grid when the subgrids are kept.') if len(self.subgrids) != system.natom: raise ValueError('The number of grid centers and the number of atoms does not match.') if (self.numbers != system.numbers).any() or (self.pseudo_numbers != system.pseudo_numbers).any(): raise ValueError('The elements of the grid and the system do not match.') offset = 0 # More recent covalent radii are used than in the original work of Becke. self.centers[:] = system.coordinates cov_radii = np.array([periodic[n].cov_radius for n in self.numbers]) for i in xrange(system.natom): atgrid = self.subgrids[i] atsize = atgrid.size atgrid.update_center(self.centers[i]) self.weights[offset:offset+atsize] = atgrid.weights becke_helper_atom( self.points[offset:offset+atsize], self.weights[offset:offset+atsize], cov_radii, self.centers, i, self._k) offset += atgrid.size
def __init__(self, centers, numbers, pseudo_numbers=None, agspec='medium', k=3, random_rotate=True, mode='discard'): ''' **Arguments:** centers An array (N, 3) with centers for the atom-centered grids. numbers An array (N,) with atomic numbers. **Optional arguments:** pseudo_numbers An array (N,) with effective core charges. When not given, this defaults to ``numbers``. agspec A specifications of the atomic grid. This can either be an instance of the AtomicGridSpec object, or the first argument of its constructor. k The order of the switching function in Becke's weighting scheme. random_rotate Flag to control random rotation of spherical grids. mode Select one of the following options regarding atomic subgrids: * ``'discard'`` (the default) means that all information about subgrids gets discarded. * ``'keep'`` means that a list of subgrids is kept, including the integration weights of the local grids. * ``'only'`` means that only the subgrids are constructed and that the computation of the molecular integration weights (based on the Becke partitioning) is skipped. ''' natom, centers, numbers, pseudo_numbers = typecheck_geo(centers, numbers, pseudo_numbers) self._centers = centers self._numbers = numbers self._pseudo_numbers = pseudo_numbers # check if the mode argument is valid if mode not in ['discard', 'keep', 'only']: raise ValueError('The mode argument must be \'discard\', \'keep\' or \'only\'.') # transform agspec into a usable format if not isinstance(agspec, AtomicGridSpec): agspec = AtomicGridSpec(agspec) self._agspec = agspec # assign attributes self._k = k self._random_rotate = random_rotate self._mode = mode # allocate memory for the grid size = sum(agspec.get_size(self.numbers[i], self.pseudo_numbers[i]) for i in xrange(natom)) points = np.zeros((size, 3), float) weights = np.zeros(size, float) self._becke_weights = np.ones(size, float) # construct the atomic grids if mode != 'discard': atgrids = [] else: atgrids = None offset = 0 if mode != 'only': # More recent covalent radii are used than in the original work of Becke. # No covalent radius is defined for elements heavier than Curium and a # default value of 3.0 Bohr is used for heavier elements. cov_radii = np.array([(periodic[n].cov_radius or 3.0) for n in self.numbers]) # The actual work: if log.do_medium: log('Preparing Becke-Lebedev molecular integration grid.') pb = log.progress(natom) for i in xrange(natom): atsize = agspec.get_size(self.numbers[i], self.pseudo_numbers[i]) atgrid = AtomicGrid( self.numbers[i], self.pseudo_numbers[i], self.centers[i], agspec, random_rotate, points[offset:offset+atsize]) if mode != 'only': atbecke_weights = self._becke_weights[offset:offset+atsize] becke_helper_atom(points[offset:offset+atsize], atbecke_weights, cov_radii, self.centers, i, self._k) weights[offset:offset+atsize] = atgrid.weights*atbecke_weights if mode != 'discard': atgrids.append(atgrid) offset += atsize pb() # finish IntGrid.__init__(self, points, weights, atgrids) # Some screen info self._log_init()
def __init__(self, centers, numbers, pseudo_numbers=None, agspec='medium', k=3, random_rotate=True, mode='discard'): ''' **Arguments:** centers An array (N, 3) with centers for the atom-centered grids. numbers An array (N,) with atomic numbers. **Optional arguments:** pseudo_numbers An array (N,) with effective core charges. When not given, this defaults to ``numbers``. agspec A specifications of the atomic grid. This can either be an instance of the AtomicGridSpec object, or the first argument of its constructor. k The order of the switching function in Becke's weighting scheme. random_rotate Flag to control random rotation of spherical grids. mode Select one of the following options regarding atomic subgrids: * ``'discard'`` (the default) means that all information about subgrids gets discarded. * ``'keep'`` means that a list of subgrids is kept, including the integration weights of the local grids. * ``'only'`` means that only the subgrids are constructed and that the computation of the molecular integration weights (based on the Becke partitioning) is skipped. ''' natom, centers, numbers, pseudo_numbers = typecheck_geo( centers, numbers, pseudo_numbers) self._centers = centers self._numbers = numbers self._pseudo_numbers = pseudo_numbers # check if the mode argument is valid if mode not in ['discard', 'keep', 'only']: raise ValueError( 'The mode argument must be \'discard\', \'keep\' or \'only\'.') # transform agspec into a usable format if not isinstance(agspec, AtomicGridSpec): agspec = AtomicGridSpec(agspec) self._agspec = agspec # assign attributes self._k = k self._random_rotate = random_rotate self._mode = mode # allocate memory for the grid size = sum( agspec.get_size(self.numbers[i], self.pseudo_numbers[i]) for i in xrange(natom)) points = np.zeros((size, 3), float) weights = np.zeros(size, float) self._becke_weights = np.ones(size, float) # construct the atomic grids if mode != 'discard': atgrids = [] else: atgrids = None offset = 0 if mode != 'only': # More recent covalent radii are used than in the original work of Becke. # No covalent radius is defined for elements heavier than Curium and a # default value of 3.0 Bohr is used for heavier elements. cov_radii = np.array([(periodic[n].cov_radius or 3.0) for n in self.numbers]) # The actual work: if log.do_medium: log('Preparing Becke-Lebedev molecular integration grid.') pb = log.progress(natom) for i in xrange(natom): atsize = agspec.get_size(self.numbers[i], self.pseudo_numbers[i]) atgrid = AtomicGrid(self.numbers[i], self.pseudo_numbers[i], self.centers[i], agspec, random_rotate, points[offset:offset + atsize]) if mode != 'only': atbecke_weights = self._becke_weights[offset:offset + atsize] becke_helper_atom(points[offset:offset + atsize], atbecke_weights, cov_radii, self.centers, i, self._k) weights[offset:offset + atsize] = atgrid.weights * atbecke_weights if mode != 'discard': atgrids.append(atgrid) offset += atsize pb() # finish IntGrid.__init__(self, points, weights, atgrids) # Some screen info self._log_init()
def __init__(self, system, agspec='medium', k=3, random_rotate=True, mode='discard'): ''' **Arguments:** system The System object for which the molecular grid must be made. Alternatively, this may also be a tuple (centers, numbers, pseudo_numbers). **Optional arguments:** agspec A specifications of the atomic grid. This can either be an instance of the AtomicGridSpec object, or the first argument of its constructor. k The order of the switching function in Becke's weighting scheme. random_rotate Flag to control random rotation of spherical grids. mode Select one of the following options regarding atomic subgrids: * ``'discard'`` (the default) means that all information about subgrids gets discarded. * ``'keep'`` means that a list of subgrids is kept, including the integration weights of the local grids. * ``'only'`` means that only the subgrids are constructed and that the computation of the molecular integration weights (based on the Becke partitioning) is skipped. ''' if isinstance(system, System): self._centers = system.coordinates.copy() self._numbers = system.numbers.copy() self._pseudo_numbers = system.pseudo_numbers.copy() natom = system.natom else: self._centers, self._numbers, self._pseudo_numbers = system natom = len(self.centers) # check if the mode argument is valid if mode not in ['discard', 'keep', 'only']: raise ValueError('The mode argument must be \'discard\', \'keep\' or \'only\'.') # transform agspec into a usable format if not isinstance(agspec, AtomicGridSpec): agspec = AtomicGridSpec(agspec) self._agspec = agspec # assign attributes self._k = k self._random_rotate = random_rotate self._mode = mode # allocate memory for the grid size = sum(agspec.get_size(self.numbers[i], self.pseudo_numbers[i]) for i in xrange(natom)) points = np.zeros((size, 3), float) weights = np.zeros(size, float) log.mem.announce(points.nbytes + weights.nbytes) # construct the atomic grids if mode != 'discard': atgrids = [] else: atgrids = None offset = 0 if mode != 'only': # More recent covalent radii are used than in the original work of Becke. cov_radii = np.array([periodic[n].cov_radius for n in self.numbers]) # The actual work: if log.do_medium: log('Preparing Becke-Lebedev molecular integration grid.') pb = log.progress(natom) for i in xrange(natom): atsize = agspec.get_size(self.numbers[i], self.pseudo_numbers[i]) atgrid = AtomicGrid( self.numbers[i], self.pseudo_numbers[i], self.centers[i], agspec, random_rotate, points[offset:offset+atsize]) if mode != 'only': weights[offset:offset+atsize] = atgrid.weights becke_helper_atom( points[offset:offset+atsize], weights[offset:offset+atsize], cov_radii, self.centers, i, self._k) if mode != 'discard': atgrids.append(atgrid) offset += atsize pb() # finish IntGrid.__init__(self, points, weights, atgrids) # Some screen info self._log_init()