Example #1
0
    def from_files(cls, fns, agspec='fine'):
        '''
           Construct a ProAtomDB from a series of HORTON checkpoint files.

           **Arguments:**

           fns_chk
                A list of atomic output files.

           **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.
        '''
        if not isinstance(agspec, AtomicGridSpec):
            agspec = AtomicGridSpec(agspec)
        records = []
        for fn in fns:
            # Load atomic data
            with timer.section('Load proatom'):
                mol = IOData.from_file(fn)
            with timer.section('Proatom grid'):
                records.append(ProAtomRecord.from_iodata(mol, agspec))
        return cls(records)
Example #2
0
    def from_files(cls, fns, agspec='fine'):
        '''
           Construct a ProAtomDB from a series of Horton checkpoint files.

           **Arguments:**

           fns_chk
                A list of system files.

           **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.
        '''
        if not isinstance(agspec, AtomicGridSpec):
            agspec = AtomicGridSpec(agspec)
        records = []
        for fn in fns:
            # Load system
            with timer.section('Load proatom'):
                sys = System.from_file(fn, chk=None) # avoid rewriting in case of chk file
            with timer.section('Proatom grid'):
                records.append(ProAtomRecord.from_system(sys, agspec))
        return cls(records)
Example #3
0
    def from_dm(cls,
                center,
                number,
                pseudo_number,
                obasis,
                dm_full,
                energy,
                agspec='fine'):
        '''Construct a proatom record from a single-atom density matrix

           **Arguments:**

           center
                The position of the nuclues (needed for spherical average)

           number
                The atomic number

           pseudo_number
                The effective core charges

           obasis
                The orbital basis

           dm_full
                The spin-summed density matrix object

           energy
                The electronic energy of the atom

           **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.
        '''
        if len(center) != 3:
            raise TypeError('Center should be a vector with three elements.')
        if not isinstance(agspec, AtomicGridSpec):
            agspec = AtomicGridSpec(agspec)

        # Compute the density and the gradient on a grid
        atgrid = AtomicGrid(number, pseudo_number, center, agspec)
        rho_all = obasis.compute_grid_density_dm(dm_full, atgrid.points)
        grad_all = obasis.compute_grid_gradient_dm(dm_full, atgrid.points)
        rho, deriv = atgrid.get_spherical_average(rho_all, grads=[grad_all])

        # Derive the number of electrions and the charge
        overlap = dm_full.new()
        obasis.compute_overlap(overlap)
        nel = overlap.contract_two('ab,ba', dm_full)
        assert abs(nel -
                   int(np.round(nel))) < 1e-4  # only integer nel are supported
        nel = int(np.round(nel))
        charge = pseudo_number - nel

        # Create object
        return cls(number, charge, energy, atgrid.rgrid, rho, deriv,
                   pseudo_number)
Example #4
0
 def from_hdf5(cls, grp, lf):
     return BeckeMolGrid(
         (grp['centers'][:], grp['numbers'][:], grp['psuedo_numbers'][:]),
         AtomicGridSpec.from_hdf5(grp['agspec'], lf),
         grp['k'][()],
         grp['random_rotate'][()],
         grp.attrs['mode'],
     )
Example #5
0
 def from_hdf5(cls, grp, lf):
     return BeckeMolGrid(
         (grp['centers'][:], grp['numbers'][:], grp['psuedo_numbers'][:]),
         AtomicGridSpec.from_hdf5(grp['agspec'], lf),
         grp['k'][()],
         grp['random_rotate'][()],
         grp.attrs['mode'],
     )
Example #6
0
    def from_system(cls, system, agspec='fine'):
        '''Construct a proatom record from a system and an atomic grid

           **Arguments:**

           sys
                The one-atom system.

           **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.
        '''
        if system.natom != 1:
            raise ValueError('Can only construct a proatom record from a one-atom system.')
        if not isinstance(agspec, AtomicGridSpec):
            agspec = AtomicGridSpec(agspec)

        # Compute the density and the gradient on a grid
        atgrid = AtomicGrid(system.numbers[0], system.pseudo_numbers[0], system.coordinates[0], agspec)
        rho_all = system.compute_grid_density(atgrid.points)
        grad_all = system.compute_grid_gradient(atgrid.points)
        rrgrad_all = ((atgrid.points-atgrid.center)*grad_all).sum(axis=1)
        # Compute spherical averages
        rho = atgrid.get_spherical_average(rho_all)
        deriv = atgrid.get_spherical_average(rrgrad_all)/atgrid.rgrid.rtransform.get_radii()

        # Derive the number of electrions
        try:
            nel = system.wfn.nel
        except NotImplementedError:
            nel = int(np.round(atgrid.rgrid.integrate(rho)))

        # Get all the other information from the atom
        energy = system.extra['energy']
        try:
            homo_energy = system.wfn.homo_energy
        except AttributeError:
            homo_energy = None
        number = system.numbers[0]
        pseudo_number = system.pseudo_numbers[0]
        charge = pseudo_number - nel

        # Create object
        return cls(number, charge, energy, homo_energy, atgrid.rgrid, rho, deriv, pseudo_number)
Example #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()
Example #8
0
def main_convert(args):
    # The atomic grid specification
    agspec = AtomicGridSpec(args.grid)

    # The program is detected based on the run script that is present
    run_scripts = glob("run_*.sh")
    if len(run_scripts) != 1:
        raise RuntimeError(
            'Found %i run_*.sh scripts while exactly one is needed to know which program was used to run the atomic computations.'
            % len(run_scripts))
    program = atom_programs[run_scripts[0][4:-3]]

    # Loop over all sensible directories
    energy_table = EnergyTable()
    records = []
    for dn_state in sorted(glob("[01]??_??_[01]??_q[+-]??")):
        number = int(dn_state[:3])
        pop = int(dn_state[7:10])

        cases = []
        for dn_mult in sorted(glob('%s/mult??' % dn_state)):
            if log.do_medium:
                log('Loading from', dn_mult)
            data, energy = program.load_atom(dn_mult)
            if energy is None:
                if log.do_medium:
                    log('No (sensible) results found:  ', dn_mult)
                continue
            cases.append((energy, data))

        if len(cases) == 0:
            if log.do_medium:
                log('Nothing found in:  ', dn_state)
            continue

        # Get the lowest in energy and write to chk file
        cases.sort()
        energy, data = cases[0]

        # Add case to energy table
        energy_table.add(number, pop, energy)

        # Write atom to HORTON file if possible
        if data is not None:
            data.to_file('%s/horton.h5' % dn_state)

        # Construct a record for the proatomdb
        records.append(ProAtomRecord.from_iodata(data, agspec))

        # Release memory
        data = None
        del cases

        # Let user know we are alive.
        if log.do_medium:
            log('Succesfull:        ', dn_state)

    # Report energies
    if log.do_medium:
        energy_table.log()

    # Write out atoms file
    proatomdb = ProAtomDB(records)
    proatomdb.to_file('atoms.h5')
    if log.do_medium:
        log('Written atoms.h5')

    # Make nice figures
    plot_atoms(proatomdb)
Example #9
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()
Example #10
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()
Example #11
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()