Exemple #1
0
    def __init__(self, p1, p2, size, extend=0):
        '''
           **Arguments:**

           p1, p2
                Two points defining the line segment

           size
                The number of grid points

           **Optional arguments:**

           extend
                Used to control how far the grid points extrapolate from the
                line segment.
        '''
        self._p1 = p1
        self._p2 = p2
        norm = np.linalg.norm(p2 - p1)
        self._x = norm * (np.arange(size, dtype=float) / (size - 1) - 0.5)
        self._x *= 1 + 2 * extend
        points = np.outer(self._x, (p2 - p1) / norm) + 0.5 * (p2 + p1)
        assert points.shape == (size, 3)
        weight = norm / (size - 1)
        weights = np.empty(size)
        weights.fill(weight)
        IntGrid.__init__(self, points, weights)
Exemple #2
0
    def __init__(self, p1, p2, size, extend=0):
        '''
           **Arguments:**

           p1, p2
                Two points defining the line segment

           size
                The number of grid points

           **Optional arguments:**

           extend
                Used to control how far the grid points extrapolate from the
                line segment.
        '''
        self._p1 = p1
        self._p2 = p2
        norm = np.linalg.norm(p2 - p1)
        self._x = norm*(np.arange(size, dtype=float)/(size-1)-0.5)
        self._x *= 1 + 2*extend
        points = np.outer(self._x, (p2 - p1)/norm) + 0.5*(p2 + p1)
        assert points.shape == (size, 3)
        weight = norm/(size-1)
        weights = np.empty(size)
        weights.fill(weight)
        IntGrid.__init__(self, points, weights)
Exemple #3
0
    def __init__(self,
                 number,
                 pseudo_number,
                 center,
                 agspec='medium',
                 random_rotate=True,
                 points=None):
        '''
           **Arguments:**

           number
                The element number for which this grid will be used.

           pseudo_number
                The effective core charge for which this grid will be used.

           center
                The center of the radial grid

           **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.

           random_rotate
                When set to False, the random rotation of the grid points is
                disabled. Such random rotation improves the accuracy of the
                integration, but leads to small random changes in the results
                that are not reproducible.

           points
                Array to store the grid points
        '''
        self._number = number
        self._pseudo_number = pseudo_number
        self._center = center
        if not isinstance(agspec, AtomicGridSpec):
            agspec = AtomicGridSpec(agspec)
        self._agspec = agspec
        self._rgrid, self._nlls = self._agspec.get(number, pseudo_number)
        self._random_rotate = random_rotate

        size = self._nlls.sum()
        if points is None:
            points = np.zeros((size, 3), float)
        else:
            assert len(points) == size
        weights = np.zeros(size, float)
        self._av_weights = np.zeros(size, float)

        self._init_low(points, weights)
        IntGrid.__init__(self, points, weights)
        self._log_init()
Exemple #4
0
    def __init__(self, number, pseudo_number, center, agspec='medium', random_rotate=True, points=None):
        '''
           **Arguments:**

           number
                The element number for which this grid will be used.

           pseudo_number
                The effective core charge for which this grid will be used.

           center
                The center of the radial grid

           **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.

           random_rotate
                When set to False, the random rotation of the grid points is
                disabled. Such random rotation improves the accuracy of the
                integration, but leads to small random changes in the results
                that are not reproducible.

           points
                Array to store the grid points
        '''
        self._number = number
        self._pseudo_number = pseudo_number
        self._center = center
        if not isinstance(agspec, AtomicGridSpec):
            agspec = AtomicGridSpec(agspec)
        self._agspec = agspec
        self._rgrid, self._nlls = self._agspec.get(number, pseudo_number)
        self._random_rotate = random_rotate

        size = self._nlls.sum()
        if points is None:
            points = np.zeros((size, 3), float)
        else:
            assert len(points) == size
        weights = np.zeros(size, float)
        self._av_weights = np.zeros(size, float)

        self._init_low(points, weights)
        IntGrid.__init__(self, points, weights)
        self._log_init()
Exemple #5
0
    def __init__(self, origin, axis0, axis1, l0, h0, l1, h1):
        '''
           **Arguments:**

           origin
                The origin for the definition of the rectangle.

           axis0, axis1
                The basis vectors that define the plane of the rectangle and
                the 2D space in this plane.

           l0, h0
                The lowest and highest position along axis0. (These must be
                integers.) Hence, along the first axis, there are (h0-l0+1)
                grid points.

           l1, h1
                The lowest and highest position along axis1.
        '''
        if h0 <= l0:
            raise ValueError('l0 should be lower than h0.')
        if h1 <= l1:
            raise ValueError('l1 should be lower than h1.')

        self._origin = origin
        self._axis0 = axis0
        self._axis1 = axis1
        self._l0 = l0
        self._h0 = h0
        self._l1 = l1
        self._h1 = h1

        size = (h0-l0+1)*(h1-l1+1)
        points = np.zeros((size, 3), float)
        weights = np.empty(size, float)
        weights[:] = np.sqrt(
            (np.linalg.norm(axis0)*np.linalg.norm(axis1))**2 -
            np.dot(axis0, axis1)**2
        )
        counter = 0
        for i0 in xrange(l0, h0+1):
            for i1 in xrange(l1, h1+1):
                points[counter] = origin + axis0*i0 + axis1*i1
                counter += 1
        IntGrid.__init__(self, points, weights)
Exemple #6
0
    def __init__(self, origin, axis0, axis1, l0, h0, l1, h1):
        '''
           **Arguments:**

           origin
                The origin for the definition of the rectangle.

           axis0, axis1
                The basis vectors that define the plane of the rectangle and
                the 2D space in this plane.

           l0, h0
                The lowest and highest position along axis0. (These must be
                integers.) Hence, along the first axis, there are (h0-l0+1)
                grid points.

           l1, h1
                The lowest and highest position along axis1.
        '''
        if h0 <= l0:
            raise ValueError('l0 should be lower than h0.')
        if h1 <= l1:
            raise ValueError('l1 should be lower than h1.')

        self._origin = origin
        self._axis0 = axis0
        self._axis1 = axis1
        self._l0 = l0
        self._h0 = h0
        self._l1 = l1
        self._h1 = h1

        size = (h0-l0+1)*(h1-l1+1)
        points = np.zeros((size, 3), float)
        weights = np.empty(size, float)
        weights[:] = np.sqrt(
            (np.linalg.norm(axis0)*np.linalg.norm(axis1))**2 -
            np.dot(axis0, axis1)**2
        )
        counter = 0
        for i0 in xrange(l0, h0+1):
            for i1 in xrange(l1, h1+1):
                points[counter] = origin + axis0*i0 + axis1*i1
                counter += 1
        IntGrid.__init__(self, points, weights)
Exemple #7
0
    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()
Exemple #8
0
 def integrate(self, *args, **kwargs):
     if self.mode == 'only':
         raise NotImplementedError('When mode==\'only\', only the subgrids can be used for integration.')
     return IntGrid.integrate(self, *args, **kwargs)
Exemple #9
0
    def __init__(self,
                 number,
                 pseudo_number,
                 center,
                 agspec='medium',
                 random_rotate=True,
                 points=None):
        '''
           **Arguments:**

           number
                The element number for which this grid will be used.

           pseudo_number
                The effective core charge for which this grid will be used.

           center
                The center of the radial grid

           **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.

           random_rotate
                When set to False, the random rotation of the grid points is
                disabled. Such random rotation improves the accuracy of the
                integration, but leads to small random changes in the results
                that are not reproducible.

           points
                Array to store the grid points
        '''
        self._number = number
        self._pseudo_number = pseudo_number
        self._center = center
        if not isinstance(agspec, AtomicGridSpec):
            agspec = AtomicGridSpec(agspec)
        self._agspec = agspec
        self._rgrid, self._nlls = self._agspec.get(number, pseudo_number)
        self._random_rotate = random_rotate

        # Obtain the total size and allocate arrays for this grid.
        size = self._nlls.sum()
        if points is None:
            points = np.zeros((size, 3), float)
        else:
            assert len(points) == size
        weights = np.zeros(size, float)

        # Fill the points and weights arrays
        offset = 0
        nsphere = len(self._nlls)
        radii = self._rgrid.radii
        rweights = self._rgrid.weights

        for i in xrange(nsphere):
            nll = self._nlls[i]
            my_points = points[offset:offset + nll]
            my_weights = weights[offset:offset + nll]

            lebedev_laikov_sphere(my_points, my_weights)
            my_points *= radii[i]
            if self.random_rotate:
                rotmat = get_random_rotation()
                my_points[:] = np.dot(my_points, rotmat)
            my_weights *= rweights[i]

            offset += nll

        points[:] += self.center

        IntGrid.__init__(self, points, weights)
        self._log_init()
Exemple #10
0
    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()
Exemple #11
0
 def integrate(self, *args, **kwargs):
     if self.mode == 'only':
         raise NotImplementedError(
             'When mode==\'only\', only the subgrids can be used for integration.'
         )
     return IntGrid.integrate(self, *args, **kwargs)
Exemple #12
0
    def __init__(self, number, pseudo_number, center, agspec='medium', random_rotate=True, points=None):
        '''
           **Arguments:**

           number
                The element number for which this grid will be used.

           pseudo_number
                The effective core charge for which this grid will be used.

           center
                The center of the radial grid

           **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.

           random_rotate
                When set to False, the random rotation of the grid points is
                disabled. Such random rotation improves the accuracy of the
                integration, but leads to small random changes in the results
                that are not reproducible.

           points
                Array to store the grid points
        '''
        self._number = number
        self._pseudo_number = pseudo_number
        self._center = center
        if not isinstance(agspec, AtomicGridSpec):
            agspec = AtomicGridSpec(agspec)
        self._agspec = agspec
        self._rgrid, self._nlls = self._agspec.get(number, pseudo_number)
        self._random_rotate = random_rotate

        # Obtain the total size and allocate arrays for this grid.
        size = self._nlls.sum()
        if points is None:
            points = np.zeros((size, 3), float)
        else:
            assert len(points) == size
        weights = np.zeros(size, float)

        # Fill the points and weights arrays
        offset = 0
        nsphere = len(self._nlls)
        radii = self._rgrid.radii
        rweights = self._rgrid.weights

        for i in xrange(nsphere):
            nll = self._nlls[i]
            my_points = points[offset:offset+nll]
            my_weights = weights[offset:offset+nll]

            lebedev_laikov_sphere(my_points, my_weights)
            my_points *= radii[i]
            if self.random_rotate:
                rotmat = get_random_rotation()
                my_points[:] = np.dot(my_points, rotmat)
            my_weights *= rweights[i]

            offset += nll

        points[:] += self.center

        IntGrid.__init__(self, points, weights)
        self._log_init()
Exemple #13
0
    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()
Exemple #14
0
    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()