Пример #1
0
 def _init_log_scheme(self):
     if log.do_medium:
         log.deflist([
             ('Scheme', 'Hirshfeld'),
             ('Proatomic DB',  self.proatomdb),
         ])
         log.cite('hirshfeld1977', 'the use of Hirshfeld partitioning')
Пример #2
0
def converge_scf_oda(ham, maxiter=128, threshold=1e-6, debug=False):
    '''Minimize the energy of the wavefunction with optimal-damping SCF

       **Arguments:**

       ham
            A Hamiltonian instance.

       **Optional arguments:**

       maxiter
            The maximum number of iterations. When set to None, the SCF loop
            will go one until convergence is reached.

       threshold
            The convergence threshold for the wavefunction

       debug
            Make debug plots with matplotlib of the linear interpolation

       **Raises:**

       NoSCFConvergence
            if the convergence criteria are not met within the specified number
            of iterations.
    '''
    log.cite('cances2001', 'using the optimal damping algorithm (ODA) SCF')
    if isinstance(ham.system.wfn, RestrictedWFN):
        return converge_scf_oda_cs(ham, maxiter, threshold, debug)
    elif isinstance(ham.system.wfn, UnrestrictedWFN):
        return converge_scf_oda_os(ham, maxiter, threshold, debug)
    else:
        raise NotImplementedError
Пример #3
0
def converge_scf_oda(ham, maxiter=128, threshold=1e-6, debug=False):
    '''Minimize the energy of the wavefunction with optimal-damping SCF

       **Arguments:**

       ham
            A Hamiltonian instance.

       **Optional arguments:**

       maxiter
            The maximum number of iterations. When set to None, the SCF loop
            will go one until convergence is reached.

       threshold
            The convergence threshold for the wavefunction

       debug
            Make debug plots with matplotlib of the linear interpolation

       **Raises:**

       NoSCFConvergence
            if the convergence criteria are not met within the specified number
            of iterations.
    '''
    log.cite('cances2001', 'using the optimal damping algorithm (ODA) SCF')
    if isinstance(ham.system.wfn, RestrictedWFN):
        return converge_scf_oda_cs(ham, maxiter, threshold, debug)
    elif isinstance(ham.system.wfn, UnrestrictedWFN):
        return converge_scf_oda_os(ham, maxiter, threshold, debug)
    else:
        raise NotImplementedError
Пример #4
0
 def __init__(self, prefix, name):
     self.exchange = name.startswith('x')
     name = '%s_%s' % (prefix, name)
     self._name = name
     self._libxc_wrapper = LibXCWrapper(name)
     log.cite('marques2012', 'using LibXC, the library of exchange and correlation functionals')
     Observable.__init__(self, 'libxc_%s' % name)
Пример #5
0
 def _init_log_scheme(self):
     if log.do_medium:
         log.deflist([
             ('Scheme', 'Hirshfeld'),
             ('Proatomic DB',  self.proatomdb),
         ])
         log.cite('hirshfeld1977', 'the use of Hirshfeld partitioning')
Пример #6
0
    def __init__(self,
                 threshold=1e-6,
                 maxiter=128,
                 nvector=6,
                 skip_energy=False,
                 prune_old_states=False):
        '''
           **Optional arguments:**

           maxiter
                The maximum number of iterations. When set to None, the SCF loop
                will go one until convergence is reached.

           threshold
                The convergence threshold for the wavefunction

           skip_energy
                When set to True, the final energy is not computed. Note that some
                DIIS variants need to compute the energy anyway. for these methods
                this option is irrelevant.

           prune_old_states
                When set to True, old states are pruned from the history when their
                coefficient is zero. Pruning starts at the oldest state and stops
                as soon as a state is encountered with a non-zero coefficient. Even
                if some newer states have a zero coefficient.
        '''
        log.cite('kudin2002', 'the EDIIS method.')
        DIISSCFSolver.__init__(self, EDIIS2History, threshold, maxiter,
                               nvector, skip_energy, prune_old_states)
Пример #7
0
def setup_weights(system, grid, dens=None, near=None, far=None):
    '''Define a weight function for the ESPCost

       **Arguments:**

       system
            The system for which the weight function must be defined

       grid
            A UniformGrid object.

       **Optional arguments:**

       dens
            The density-based criterion. This is a three-tuple with rho, lnrho0
            and sigma. rho is the atomic or the pro-atomic electron density on
            the same grid as the ESP data. lnrho0 and sigma are parameters
            defined in JCTC, 3, 1004 (2007), DOI:10.1021/ct600295n. The weight
            function takes the form::

                exp(-sigma*(ln(rho) - lnrho0)**2)

            Note that the density, rho, should not contain depletions in the
            atomic cores, as is often encountered with pseudo-potential
            computations. In that case it is recommended to construct a
            promolecular density as input for this option.

       near
            Exclude points near the nuclei. This is a dictionary with as items
            (number, (R0, gamma)).

       far
            Exclude points far away. This is a two-tuple: (R0, gamma).
    '''
    weights = np.ones(grid.shape)

    # combine three possible mask functions
    if dens is not None:
        log.cite('hu2007', 'for the ESP fitting weight function')
        rho, lnrho0, sigma = dens
        assert (rho.shape == grid.shape).all()
        multiply_dens_mask(rho, lnrho0, sigma, weights)
    if near is not None:
        for i in xrange(system.natom):
            pair = near.get(system.numbers[i])
            if pair is None:
                pair = near.get(0)
            if pair is None:
                continue
            r0, gamma = pair
            if r0 > 5*angstrom:
                raise ValueError('The wnear radius is excessive. Please keep it below 5 angstrom.')
            multiply_near_mask(system.coordinates[i], grid, r0, gamma, weights)
    if far is not None:
        r0, gamma = far
        multiply_far_mask(system.coordinates, grid, r0, gamma, weights)

    # double that weight goes to zero at non-periodic edges
    return weights
Пример #8
0
 def _init_log_scheme(self):
     if log.do_medium:
         log.deflist([
             ('Scheme', 'Iterative Stockholder'),
             ('Convergence threshold', '%.1e' % self._threshold),
             ('Maximum iterations', self._maxiter),
         ])
         log.cite('lillestolen2008', 'the use of Iterative Stockholder partitioning')
Пример #9
0
 def _init_log_scheme(self):
     if log.do_medium:
         log.deflist([
             ('Scheme', 'Iterative Stockholder'),
             ('Convergence threshold', '%.1e' % self._threshold),
             ('Maximum iterations', self._maxiter),
         ])
         log.cite('lillestolen2008', 'the use of Iterative Stockholder partitioning')
Пример #10
0
 def _init_log_scheme(self):
     if log.do_medium:
         log.deflist([
             ('Scheme', 'Becke'),
             ('Switching function', 'k=%i' % self._k),
         ])
         log.cite('becke1988_multicenter', 'the use of Becke partitioning')
         log.cite('slater1964', 'the Brag-Slater radii used in the Becke partitioning')
Пример #11
0
 def _init_log_scheme(self):
     if log.do_medium:
         log.deflist([
             ('Scheme', 'Minimal Basis Iterative Stockholder (MBIS)'),
             ('Convergence threshold', '%.1e' % self._threshold),
             ('Maximum iterations', self._maxiter),
         ])
         log.cite('verstraelen2016', 'the use of MBIS partitioning')
Пример #12
0
 def __init__(self, prefix, name):
     self.exchange = name.startswith('x')
     name = '%s_%s' % (prefix, name)
     self._name = name
     self._libxc_wrapper = LibXCWrapper(name)
     log.cite(
         'marques2012',
         'using LibXC, the library of exchange and correlation functionals')
     Observable.__init__(self, 'libxc_%s' % name)
Пример #13
0
 def _init_log_scheme(self):
     if log.do_medium:
         log.deflist([
             ('Scheme', 'Hirshfeld-I'),
             ('Convergence threshold', '%.1e' % self._threshold),
             ('Maximum iterations', self._maxiter),
             ('Proatomic DB',  self._proatomdb),
         ])
         log.cite('bultinck2007', 'the use of Hirshfeld-I partitioning')
Пример #14
0
 def _init_log_scheme(self):
     if log.do_medium:
         log.deflist([
             ('Scheme', 'Hirshfeld-I'),
             ('Convergence threshold', '%.1e' % self._threshold),
             ('Maximum iterations', self._maxiter),
             ('Proatomic DB', self._proatomdb),
         ])
         log.cite('bultinck2007', 'the use of Hirshfeld-I partitioning')
Пример #15
0
def solve_poisson_becke(density_decomposition):
    '''Compute the electrostatic potential of a density expanded in real spherical harmonics

       **Arguments:**

       density_decomposition
            A list of cubic splines returned by the method
            AtomicGrid.get_spherical_decomposition.

       The returned list of splines is a spherical decomposition of the
       hartree potential (felt by a particle with the same charge unit as the
       density).
    '''
    log.cite('becke1988_poisson',
             'the numerical integration of the Poisson equation')

    lmax = np.sqrt(len(density_decomposition)) - 1
    assert lmax == int(lmax)
    lmax = int(lmax)

    result = []
    counter = 0
    for l in xrange(0, lmax + 1):
        for m in xrange(-l, l + 1):
            rho = density_decomposition[counter]
            rtf = rho.rtransform
            rgrid = RadialGrid(rtf)
            radii = rtf.get_radii()
            # The approach followed here is obtained after substitution of
            # u = r*V in Eq. (21) in Becke's paper. After this transformation,
            # the boundary conditions can be implemented such that the output
            # is more accurate.
            fy = -4 * np.pi * rho.y
            fd = -4 * np.pi * rho.dx
            f = CubicSpline(fy, fd, rtf)
            b = CubicSpline(2 / radii, -2 / radii**2, rtf)
            a = CubicSpline(-l * (l + 1) * radii**-2,
                            2 * l * (l + 1) * radii**-3, rtf)
            # Derivation of boundary condition at rmax:
            # Multiply differential equation with r**l and integrate. Using
            # partial integration and the fact that V(r)=A/r**(l+1) for large
            # r, we find -(2l+1)A=-4pi*int_0^infty r**2 r**l rho(r) and so
            # V(rmax) = A/rmax**(l+1) = integrate(r**l rho(r))/(2l+1)/rmax**(l+1)
            V_rmax = rgrid.integrate(
                rho.y * radii**l) / radii[-1]**(l + 1) / (2 * l + 1)
            # Derivation of boundary condition at rmin:
            # Same as for rmax, but multiply differential equation with r**(-l-1)
            # and assume that V(r)=B*r**l for small r.
            V_rmin = rgrid.integrate(
                rho.y * radii**(-l - 1)) * radii[0]**(l) / (2 * l + 1)
            bcs = (V_rmin, None, V_rmax, None)
            v = solve_ode2(b, a, f, bcs, PotentialExtrapolation(l))
            result.append(v)
            counter += 1

    return result
Пример #16
0
 def _log_init(self):
     if log.do_medium:
         log('Initialized: %s' % self)
         log.deflist([
             ('Size', self.size),
             ('Switching function', 'k=%i' % self._k),
         ])
         log.blank()
     # Cite reference
     log.cite('becke1988_multicenter', 'the multicenter integration scheme used for the molecular integration grid')
     log.cite('cordero2008', 'the covalent radii used for the Becke-Lebedev molecular integration grid')
Пример #17
0
 def _log_init(self):
     if log.do_medium:
         log('Initialized: %s' % self)
         log.deflist([
             ('Size', self.size),
             ('Switching function', 'k=%i' % self._k),
         ])
         log.blank()
     # Cite reference
     log.cite('becke1988_multicenter', 'the multicenter integration scheme used for the molecular integration grid')
     log.cite('cordero2008', 'the covalent radii used for the Becke-Lebedev molecular integration grid')
Пример #18
0
def solve_poisson_becke(density_decomposition):
    '''Compute the electrostatic potential of a density expanded in real spherical harmonics

       **Arguments:**

       density_decomposition
            A list of cubic splines returned by the method
            AtomicGrid.get_spherical_decomposition.

       The returned list of splines is a spherical decomposition of the
       hartree potential (felt by a particle with the same charge unit as the
       density).
    '''
    log.cite('becke1988_poisson', 'the numerical integration of the Poisson equation')

    lmax = np.sqrt(len(density_decomposition)) - 1
    assert lmax == int(lmax)
    lmax = int(lmax)

    result = []
    counter = 0
    for l in xrange(0, lmax+1):
        for m in xrange(-l, l+1):
            rho = density_decomposition[counter]
            rtf = rho.rtransform
            rgrid = RadialGrid(rtf)
            radii = rtf.get_radii()
            # The approach followed here is obtained after substitution of
            # u = r*V in Eq. (21) in Becke's paper. After this transformation,
            # the boundary conditions can be implemented such that the output
            # is more accurate.
            fy = -4*np.pi*rho.y
            fd = -4*np.pi*rho.dx
            f = CubicSpline(fy, fd, rtf)
            b = CubicSpline(2/radii, -2/radii**2, rtf)
            a = CubicSpline(-l*(l+1)*radii**-2, 2*l*(l+1)*radii**-3, rtf)
            # Derivation of boundary condition at rmax:
            # Multiply differential equation with r**l and integrate. Using
            # partial integration and the fact that V(r)=A/r**(l+1) for large
            # r, we find -(2l+1)A=-4pi*int_0^infty r**2 r**l rho(r) and so
            # V(rmax) = A/rmax**(l+1) = integrate(r**l rho(r))/(2l+1)/rmax**(l+1)
            V_rmax = rgrid.integrate(rho.y*radii**l)/radii[-1]**(l+1)/(2*l+1)
            # Derivation of boundary condition at rmin:
            # Same as for rmax, but multiply differential equation with r**(-l-1)
            # and assume that V(r)=B*r**l for small r.
            V_rmin = rgrid.integrate(rho.y*radii**(-l-1))*radii[0]**(l)/(2*l+1)
            bcs = (V_rmin, None, V_rmax, None)
            v = solve_ode2(b, a, f, bcs, PotentialExtrapolation(l))
            result.append(v)
            counter += 1

    return result
Пример #19
0
 def _log_init(self):
     if log.do_high:
         log('Initialized: %s' % self)
         log.deflist([
             ('Size', self.size),
             ('Number of radii', self.nsphere),
             ('Min LL sphere', self._nlls.min()),
             ('Max LL sphere', self._nlls.max()),
             ('Radial Transform', self._rgrid.rtransform.to_string()),
             ('1D Integrator', self._rgrid.int1d),
         ])
     # Cite reference
     log.cite('lebedev1999', 'the use of Lebedev-Laikov grids (quadrature on a sphere)')
Пример #20
0
    def __init__(self, name):
        '''
           **Arguments:**

           name
                The name of the functional in LibXC, without the ``lda_``,
                ``gga_`` or ``hyb_gga_`` prefix. (The type of functional is
                determined by the subclass.)
        '''
        name = '%s_%s' % (self.prefix, name)
        self._name = name
        self._libxc_wrapper = self.LibXCWrapper(name)
        log.cite('marques2012', 'using LibXC, the library of exchange and correlation functionals')
        GridObservable.__init__(self, 'libxc_%s' % name)
Пример #21
0
    def __init__(self, *noccs, **kwargs):
        r'''
           **Arguments:**

           nalpha, nbeta, ...
                The number of electrons in each channel.

           **Optional keyword arguments:**

           temperature
                Controls the width of the distribution (derivative)

           eps
                The error on the sum of the occupation number when searching for
                the right Fermi level.

           For each channel, the orbital occupations are assigned with the Fermi
           distribution:

           .. math::

                n_i = \frac{1}{1 + e^{(\epsilon_i - \mu)/k_B T}}

           where, for a given set of energy levels, :math:`\{\epsilon_i\}`, the
           chemical potential, :math:`\mu`, is optimized as to satisfy the
           following constraint:

           .. math::

               \sum_i n_i = n_\text{occ}

           where :math:`n_\text{occ}` can be set per (spin) channel. This is
           only a part of the methodology presented in [rabuck1999]_.
        '''
        temperature = kwargs.pop('temperature', 300)
        eps = kwargs.pop('eps', 1e-8)
        if len(kwargs) > 0:
            raise TypeError('Unknown keyword arguments: %s' % kwargs.keys())
        if temperature <= 0:
            raise ValueError('The temperature must be strictly positive')
        if eps <= 0:
            raise ValueError(
                'The root-finder threshold (eps) must be strictly positive.')
        self.temperature = float(temperature)
        self.eps = eps
        AufbauOccModel.__init__(self, *noccs)
        log.cite('rabuck1999',
                 'the Fermi broading method to assign orbital occupations')
Пример #22
0
    def __init__(self, name):
        '''
           **Arguments:**

           name
                The name of the functional in LibXC, without the ``lda_``,
                ``gga_`` or ``hyb_gga_`` prefix. (The type of functional is
                determined by the subclass.)
        '''
        name = '%s_%s' % (self.prefix, name)
        self._name = name
        self._libxc_wrapper = self.LibXCWrapper(name)
        log.cite(
            'marques2012',
            'using LibXC, the library of exchange and correlation functionals')
        GridObservable.__init__(self, 'libxc_%s' % name)
Пример #23
0
    def __init__(self, name):
        """Initialize a LibXCEnergy instance.

        Parameters
        ----------
        name : str
            The name of the functional in LibXC, without the ``lda_``, ``gga_`` or
            ``hyb_gga_`` prefix. (The type of functional is determined by the subclass.)
        """
        name = '%s_%s' % (self.prefix, name)
        self._name = name
        self._libxc_wrapper = self.LibXCWrapper(name)
        log.cite(
            'marques2012',
            'using LibXC, the library of exchange and correlation functionals')
        GridObservable.__init__(self, 'libxc_%s' % name)
Пример #24
0
def converge_scf_ediis(ham,
                       maxiter=128,
                       threshold=1e-6,
                       nvector=6,
                       prune_old_states=False,
                       scf_step='regular'):
    '''Minimize the energy of the wavefunction with the EDIIS algorithm

       **Arguments:**

       ham
            A Hamiltonian instance.

       **Optional arguments:**

       maxiter
            The maximum number of iterations. When set to None, the SCF loop
            will go one until convergence is reached.

       threshold
            The convergence threshold for the wavefunction

       prune_old_states
            When set to True, old states are pruned from the history when their
            coefficient is zero. Pruning starts at the oldest state and stops
            as soon as a state is encountered with a non-zero coefficient. Even
            if some newer states have a zero coefficient.

       scf_step
            The type of SCF step to take after the interpolated states was
            create from the DIIS history. This can be 'regular', 'oda2' or
            'oda3'.

       **Raises:**

       NoSCFConvergence
            if the convergence criteria are not met within the specified number
            of iterations.

       **Returns:** the number of iterations
    '''
    log.cite('kudin2002', 'using the energy DIIS SCF algorithm')
    if isinstance(ham.system.wfn, RestrictedWFN):
        return converge_scf_ediis_cs(ham, maxiter, threshold, nvector,
                                     prune_old_states, scf_step)
    else:
        raise NotImplementedError
Пример #25
0
    def __init__(self, *noccs, **kwargs):
        r'''
           **Arguments:**

           nalpha, nbeta, ...
                The number of electrons in each channel.

           **Optional keyword arguments:**

           temperature
                Controls the width of the distribution (derivative)

           eps
                The error on the sum of the occupation number when searching for
                the right Fermi level.

           For each channel, the orbital occupations are assigned with the Fermi
           distribution:

           .. math::

                n_i = \frac{1}{1 + e^{(\epsilon_i - \mu)/k_B T}}

           where, for a given set of energy levels, :math:`\{\epsilon_i\}`, the
           chemical potential, :math:`\mu`, is optimized as to satisfy the
           following constraint:

           .. math::

               \sum_i n_i = n_\text{occ}

           where :math:`n_\text{occ}` can be set per (spin) channel. This is
           only a part of the methodology presented in [rabuck1999]_.
        '''
        temperature = kwargs.pop('temperature', 300)
        eps = kwargs.pop('eps', 1e-8)
        if len(kwargs) > 0:
            raise TypeError('Unknown keyword arguments: %s' % kwargs.keys())
        if temperature <= 0:
            raise ValueError('The temperature must be strictly positive')
        if eps <= 0:
            raise ValueError('The root-finder threshold (eps) must be strictly positive.')
        self.temperature = float(temperature)
        self.eps = eps
        AufbauOccModel.__init__(self, *noccs)
        log.cite('rabuck1999', 'the Fermi broading method to assign orbital occupations')
Пример #26
0
def converge_scf_cdiis(ham, maxiter=128, threshold=1e-6, nvector=6, prune_old_states=False, skip_energy=False, scf_step='regular'):
    '''Minimize the energy of the wavefunction with the CDIIS algorithm

       **Arguments:**

       ham
            A Hamiltonian instance.

       **Optional arguments:**

       maxiter
            The maximum number of iterations. When set to None, the SCF loop
            will go one until convergence is reached.

       threshold
            The convergence threshold for the wavefunction

       prune_old_states
            When set to True, old states are pruned from the history when their
            coefficient is zero. Pruning starts at the oldest state and stops
            as soon as a state is encountered with a non-zero coefficient. Even
            if some newer states have a zero coefficient.

       skip_energy
            When set to True, the final energy is not computed.

       scf_step
            The type of SCF step to take after the interpolated states was
            create from the DIIS history. This can be 'regular', 'oda2' or
            'oda3'.

       **Raises:**

       NoSCFConvergence
            if the convergence criteria are not met within the specified number
            of iterations.

       **Returns:** the number of iterations
    '''
    log.cite('pulay1980', 'using the commutator DIIS SCF algorithm')
    if isinstance(ham.system.wfn, RestrictedWFN):
        return converge_scf_cdiis_cs(ham, maxiter, threshold, nvector, prune_old_states, skip_energy, scf_step)
    else:
        raise NotImplementedError
Пример #27
0
def converge_scf_cdiis_cs(ham, maxiter=128, threshold=1e-6, nvector=6, prune_old_states=False, skip_energy=False, scf_step='regular'):
    '''Minimize the energy of the closed-shell wavefunction with CDIIS

       **Arguments:**

       ham
            A Hamiltonian instance.

       **Optional arguments:**

       maxiter
            The maximum number of iterations. When set to None, the SCF loop
            will go one until convergence is reached.

       threshold
            The convergence threshold for the wavefunction

       prune_old_states
            When set to True, old states are pruned from the history when their
            coefficient is zero. Pruning starts at the oldest state and stops
            as soon as a state is encountered with a non-zero coefficient. Even
            if some newer states have a zero coefficient.

       skip_energy
            When set to True, the final energy is not computed.

       scf_step
            The type of SCF step to take after the interpolated states was
            create from the DIIS history. This can be 'regular', 'oda2' or
            'oda3'.

       **Raises:**

       NoSCFConvergence
            if the convergence criteria are not met within the specified number
            of iterations.

       **Returns:** the number of iterations
    '''
    log.cite('pulay1980', 'the use of the commutator DIIS method')
    return converge_scf_diis_cs(ham, PulayDIISHistory, maxiter, threshold, nvector, prune_old_states, skip_energy, scf_step)
Пример #28
0
def converge_scf_ediis_cs(ham, maxiter=128, threshold=1e-6, nvector=6, prune_old_states=False, scf_step='regular'):
    '''Minimize the energy of the closed-shell wavefunction with EDIIS

       **Arguments:**

       ham
            A Hamiltonian instance.

       **Optional arguments:**

       maxiter
            The maximum number of iterations. When set to None, the SCF loop
            will go one until convergence is reached.

       threshold
            The convergence threshold for the wavefunction

       prune_old_states
            When set to True, old states are pruned from the history when their
            coefficient is zero. Pruning starts at the oldest state and stops
            as soon as a state is encountered with a non-zero coefficient. Even
            if some newer states have a zero coefficient.

       scf_step
            The type of SCF step to take after the interpolated states was
            create from the DIIS history. This can be 'regular', 'oda2' or
            'oda3'.

       **Raises:**

       NoSCFConvergence
            if the convergence criteria are not met within the specified number
            of iterations.

       **Returns:** the number of iterations
    '''
    log.cite('kudin2002', 'the use of the EDIIS method.')
    return converge_scf_diis_cs(ham, EnergyDIISHistory, maxiter, threshold, nvector, prune_old_states, scf_step)
Пример #29
0
    def __init__(self, threshold=1e-6, maxiter=128, nvector=6, skip_energy=False, prune_old_states=False):
        '''
           **Optional arguments:**

           maxiter
                The maximum number of iterations. When set to None, the SCF loop
                will go one until convergence is reached.

           threshold
                The convergence threshold for the wavefunction

           skip_energy
                When set to True, the final energy is not computed. Note that some
                DIIS variants need to compute the energy anyway. for these methods
                this option is irrelevant.

           prune_old_states
                When set to True, old states are pruned from the history when their
                coefficient is zero. Pruning starts at the oldest state and stops
                as soon as a state is encountered with a non-zero coefficient. Even
                if some newer states have a zero coefficient.
        '''
        log.cite('pulay1980', 'the commutator DIIS SCF algorithm')
        DIISSCFSolver.__init__(self, CDIISHistory, threshold, maxiter, nvector, skip_energy, prune_old_states)
Пример #30
0
    def do_dispersion(self):
        if self.lmax < 3:
            if log.do_warning:
                log.warn(
                    'Skipping the computation of dispersion coefficients because lmax=%i<3'
                    % self.lmax)
            return

        if log.do_medium:
            log.cite(
                'tkatchenko2009',
                'the method to evaluate atoms-in-molecules C6 parameters')
            log.cite('chu2004',
                     'the reference C6 parameters of isolated atoms')
            log.cite('yan1996', 'the isolated hydrogen C6 parameter')

        ref_c6s = { # reference C6 values in atomic units
            1: 6.499, 2: 1.42, 3: 1392.0, 4: 227.0, 5: 99.5, 6: 46.6, 7: 24.2,
            8: 15.6, 9: 9.52, 10: 6.20, 11: 1518.0, 12: 626.0, 13: 528.0, 14:
            305.0, 15: 185.0, 16: 134.0, 17: 94.6, 18: 64.2, 19: 3923.0, 20:
            2163.0, 21: 1383.0, 22: 1044.0, 23: 832.0, 24: 602.0, 25: 552.0, 26:
            482.0, 27: 408.0, 28: 373.0, 29: 253.0, 30: 284.0, 31: 498.0, 32:
            354.0, 33: 246.0, 34: 210.0, 35: 162.0, 36: 130.0, 37: 4769.0, 38:
            3175.0, 49: 779.0, 50: 659.0, 51: 492.0, 52: 445.0, 53: 385.0,
        }

        volumes, new_volumes = self._cache.load('volumes',
                                                alloc=self.natom,
                                                tags='o')
        volume_ratios, new_volume_ratios = self._cache.load('volume_ratios',
                                                            alloc=self.natom,
                                                            tags='o')
        c6s, new_c6s = self._cache.load('c6s', alloc=self.natom, tags='o')

        if new_volumes or new_volume_ratios or new_c6s:
            self.do_moments()
            radial_moments = self._cache.load('radial_moments')

            if log.do_medium:
                log('Computing atomic dispersion coefficients.')

            for i in xrange(self.natom):
                n = self.numbers[i]
                volumes[i] = radial_moments[i, 3]
                ref_volume = self.proatomdb.get_record(n, 0).get_moment(3)
                volume_ratios[i] = volumes[i] / ref_volume
                if n in ref_c6s:
                    c6s[i] = (volume_ratios[i])**2 * ref_c6s[n]
                else:
                    c6s[i] = -1  # This is just to indicate that no value is available.
Пример #31
0
    def do_dispersion(self):
        if self.lmax < 3:
            if log.do_warning:
                log.warn('Skipping the computation of dispersion coefficients because lmax=%i<3' % self.lmax)
            return

        if log.do_medium:
            log.cite('tkatchenko2009', 'the method to evaluate atoms-in-molecules C6 parameters')
            log.cite('chu2004', 'the reference C6 parameters of isolated atoms')
            log.cite('yan1996', 'the isolated hydrogen C6 parameter')

        ref_c6s = { # reference C6 values in atomic units
            1: 6.499, 2: 1.42, 3: 1392.0, 4: 227.0, 5: 99.5, 6: 46.6, 7: 24.2,
            8: 15.6, 9: 9.52, 10: 6.20, 11: 1518.0, 12: 626.0, 13: 528.0, 14:
            305.0, 15: 185.0, 16: 134.0, 17: 94.6, 18: 64.2, 19: 3923.0, 20:
            2163.0, 21: 1383.0, 22: 1044.0, 23: 832.0, 24: 602.0, 25: 552.0, 26:
            482.0, 27: 408.0, 28: 373.0, 29: 253.0, 30: 284.0, 31: 498.0, 32:
            354.0, 33: 246.0, 34: 210.0, 35: 162.0, 36: 130.0, 37: 4769.0, 38:
            3175.0, 49: 779.0, 50: 659.0, 51: 492.0, 52: 445.0, 53: 385.0,
        }

        volumes, new_volumes = self._cache.load('volumes', alloc=self.natom, tags='o')
        volume_ratios, new_volume_ratios = self._cache.load('volume_ratios', alloc=self.natom, tags='o')
        c6s, new_c6s = self._cache.load('c6s', alloc=self.natom, tags='o')

        if new_volumes or new_volume_ratios or new_c6s:
            self.do_populations()
            self.do_moments()
            radial_moments = self._cache.load('radial_moments')
            populations = self._cache.load('populations')

            if log.do_medium:
                log('Computing atomic dispersion coefficients.')

            for i in xrange(self.natom):
                n = self.numbers[i]
                volumes[i] = radial_moments[i,2]/populations[i]
                ref_volume = self.proatomdb.get_record(n, 0).get_moment(3)/n
                volume_ratios[i] = volumes[i]/ref_volume
                if n in ref_c6s:
                    c6s[i] = (volume_ratios[i])**2*ref_c6s[n]
                else:
                    c6s[i] = -1 # This is just to indicate that no value is available.
Пример #32
0
    def __call__(self, orb, select, **kwargs):
        '''Localizes the orbitals using a unitary transformation to rotate the
           AO/MO coefficient matrix. The orbitals are optimized by minimizing
           an objective function.

           This works only for restricted orbitals.

           **Arguments:**

           orb
                The AO/MO coefficients. An Expansion instance.

           select
                The orbital block to be localised (str). Any of ``occ`` (occupied
                orbitals), ``virt`` (virtual orbitals)

           **Keywords:**

           :maxiter: (int) maximum number of iterations for localization
                     (default 2000)
           :threshold: (float) localization threshold for objective function
                       (default 1e-6)
           :levelshift: level shift of Hessian (float) (default 1e-8)
           :stepsearch: step search options (dictionary) containing:

                        * method: step search method used (str). One of
                          ``trust-region`` (default), ``None``, ``backtracking``
                        * alpha: scaling factor for Newton step (float), used in
                          ``backtracking`` and ``None`` method (default 0.75)
                        * c1: parameter used in ``backtracking`` (float)
                          (default 1e-4)
                        * minalpha: minimum step length used in ``backracking``
                          (float) (default 1e-6)
                        * maxiterouter: maximum number of search steps (int)
                          (default 10)
                        * maxiterinner: maximum number of optimization
                          steps in each search step (int) (used only in ``pcg``,
                          default 500)
                        * maxeta: upper bound for estimated vs actual change in
                          ``trust-region`` (float) (default 0.75)
                        * mineta: lower bound for estimated vs actual change in
                          ``trust-region`` (float) (default 0.25)
                        * upscale: scaling factor to increase trustradius in
                          ``trust-region`` (float) (default 2.0)
                        * downscale: scaling factor to decrease trustradius in
                          ``trust-region`` (float) and scaling factor in
                          ``backtracking`` (default 0.25)
                        * trustradius: initial trustradius (float) (default
                          0.75)
                        * maxtrustradius: maximum trustradius (float) (default
                          0.75)
                        * threshold: trust-region optimization threshold, only
                          used in ``pcg`` (float) (default 1e-8)
                        * optimizer: optimizes step to boundary of trustradius
                          (str). One of ``pcg``, ``dogleg``, ``ddl`` (default
                          ddl)
        '''
        if log.do_medium:
            log('Performing localization of %s block' % (select))
        log.cite('pipek1989', 'the Pipek-Mezey localization scheme')
        #
        # Assign default keyword arguements
        #
        names = []

        def _helper(x, y):
            names.append(x)
            return kwargs.get(x, y)

        maxiter = _helper('maxiter', 2000)
        thresh = _helper('threshold', 1e-6)
        lshift = _helper('levelshift', 1e-8)
        stepsearch = _helper('stepsearch', dict({}))
        stepsearch.setdefault('method', 'trust-region')
        stepsearch.setdefault('minalpha', 1e-6)
        stepsearch.setdefault('alpha', 1.0)
        stepsearch.setdefault('c1', 0.0001)
        stepsearch.setdefault('maxiterouter', 10)
        stepsearch.setdefault('maxiterinner', 500)
        stepsearch.setdefault('maxeta', 0.75)
        stepsearch.setdefault('mineta', 0.25)
        stepsearch.setdefault('upscale', 2.0)
        stepsearch.setdefault('downscale', 0.25)
        stepsearch.setdefault('trustradius', 0.75)
        stepsearch.setdefault('maxtrustradius', 0.75)
        stepsearch.setdefault('threshold', 1e-8)
        stepsearch.setdefault('optimizer', 'ddl')

        for name, value in kwargs.items():
            if name not in names:
                raise ValueError("Unknown keyword argument %s" % name)
            if value < 0:
                raise ValueError('Illegal value for %s: %s' % (name, value))

        #
        # Update information about localization block
        #
        self.update_locblock(select)

        if log.do_medium:
            log('%3s  %12s  %10s' %
                ('Iter', 'D(ObjectiveFunction)', 'Steplength'))
        #
        # Initialize step search
        #
        stepsearch_ = RStepSearch(self.lf, **stepsearch)
        #
        # Calculate initial objective function
        #
        self.solve_model(orb)
        objfct_ref = self.compute_objective_function()

        maxThresh = True
        maxIter = True
        it = 0
        while maxThresh and maxIter:
            #
            # Update population matrix for new orbitals
            #
            self.compute_population_matrix(orb)
            #
            # Calculate orbital gradient and diagonal approximation to the Hessian
            #
            kappa, gradient, hessian = self.orbital_rotation_step(lshift)
            #
            # Apply steps search to orbital rotation step 'kappa' and perform
            # orbital rotation
            #
            stepsearch_(
                self, None, None, orb, **{
                    'kappa': kappa,
                    'gradient': gradient,
                    'hessian': hessian
                })
            #
            # update objective function
            #
            objfct = self.compute_objective_function()
            it += 1
            #
            # Print localization progress
            #
            if log.do_medium:
                log('%4i   %14.8f' % (it, abs(objfct - objfct_ref)))
            #
            # Check convergence
            #
            maxThresh = abs(objfct - objfct_ref) > thresh
            maxIter = it < maxiter
            #
            # Prepare for new iteration
            #
            objfct_ref = objfct
        if maxThresh and not maxIter:
            if log.do_medium:
                log(' ')
                log('Warning: Orbital localization not converged in %i iteration'
                    % (it - 1))
                log(' ')
        else:
            if log.do_medium:
                log(' ')
                log('Orbital localization converged in %i iteration' %
                    (it - 1))
                log(' ')
Пример #33
0
    def __call__(self, orb, select, **kwargs):
        '''Localizes the orbitals using a unitary transformation to rotate the
           AO/MO coefficient matrix. The orbitals are optimized by minimizing
           an objective function.

           This works only for restricted orbitals.

           **Arguments:**

           orb
                The AO/MO coefficients. An Expansion instance.

           select
                The orbital block to be localised (str). Any of ``occ`` (occupied
                orbitals), ``virt`` (virtual orbitals)

           **Keywords:**

           :maxiter: (int) maximum number of iterations for localization
                     (default 2000)
           :threshold: (float) localization threshold for objective function
                       (default 1e-6)
           :levelshift: level shift of Hessian (float) (default 1e-8)
           :stepsearch: step search options (dictionary) containing:

                        * method: step search method used (str). One of
                          ``trust-region`` (default), ``None``, ``backtracking``
                        * alpha: scaling factor for Newton step (float), used in
                          ``backtracking`` and ``None`` method (default 0.75)
                        * c1: parameter used in ``backtracking`` (float)
                          (default 1e-4)
                        * minalpha: minimum step length used in ``backracking``
                          (float) (default 1e-6)
                        * maxiterouter: maximum number of search steps (int)
                          (default 10)
                        * maxiterinner: maximum number of optimization
                          steps in each search step (int) (used only in ``pcg``,
                          default 500)
                        * maxeta: upper bound for estimated vs actual change in
                          ``trust-region`` (float) (default 0.75)
                        * mineta: lower bound for estimated vs actual change in
                          ``trust-region`` (float) (default 0.25)
                        * upscale: scaling factor to increase trustradius in
                          ``trust-region`` (float) (default 2.0)
                        * downscale: scaling factor to decrease trustradius in
                          ``trust-region`` (float) and scaling factor in
                          ``backtracking`` (default 0.25)
                        * trustradius: initial trustradius (float) (default
                          0.75)
                        * maxtrustradius: maximum trustradius (float) (default
                          0.75)
                        * threshold: trust-region optimization threshold, only
                          used in ``pcg`` (float) (default 1e-8)
                        * optimizer: optimizes step to boundary of trustradius
                          (str). One of ``pcg``, ``dogleg``, ``ddl`` (default
                          ddl)
        '''
        if log.do_medium:
            log('Performing localization of %s block' %(select))
        log.cite('pipek1989', 'the Pipek-Mezey localization scheme')
        #
        # Assign default keyword arguements
        #
        names = []
        def _helper(x,y):
            names.append(x)
            return kwargs.get(x,y)
        maxiter = _helper('maxiter', 2000)
        thresh = _helper('threshold', 1e-6)
        lshift = _helper('levelshift', 1e-8)
        stepsearch = _helper('stepsearch', dict({}))
        stepsearch.setdefault('method', 'trust-region')
        stepsearch.setdefault('minalpha', 1e-6)
        stepsearch.setdefault('alpha', 1.0)
        stepsearch.setdefault('c1', 0.0001)
        stepsearch.setdefault('maxiterouter', 10)
        stepsearch.setdefault('maxiterinner', 500)
        stepsearch.setdefault('maxeta', 0.75)
        stepsearch.setdefault('mineta', 0.25)
        stepsearch.setdefault('upscale', 2.0)
        stepsearch.setdefault('downscale', 0.25)
        stepsearch.setdefault('trustradius', 0.75)
        stepsearch.setdefault('maxtrustradius', 0.75)
        stepsearch.setdefault('threshold', 1e-8)
        stepsearch.setdefault('optimizer', 'ddl')

        for name, value in kwargs.items():
            if name not in names:
                raise ValueError("Unknown keyword argument %s" % name)
            if value < 0:
                raise ValueError('Illegal value for %s: %s' %(name, value))

        #
        # Update information about localization block
        #
        self.update_locblock(select)

        if log.do_medium:
            log('%3s  %12s  %10s' %('Iter', 'D(ObjectiveFunction)', 'Steplength'))
        #
        # Initialize step search
        #
        stepsearch_ = RStepSearch(self.lf, **stepsearch)
        #
        # Calculate initial objective function
        #
        self.solve_model(orb)
        objfct_ref = self.compute_objective_function()

        maxThresh = True
        maxIter = True
        it = 0
        while maxThresh and maxIter:
            #
            # Update population matrix for new orbitals
            #
            self.compute_population_matrix(orb)
            #
            # Calculate orbital gradient and diagonal approximation to the Hessian
            #
            kappa, gradient, hessian = self.orbital_rotation_step(lshift)
            #
            # Apply steps search to orbital rotation step 'kappa' and perform
            # orbital rotation
            #
            stepsearch_(self, None, None, orb,
                       **{'kappa': kappa, 'gradient': gradient, 'hessian': hessian
                         })
            #
            # update objective function
            #
            objfct = self.compute_objective_function()
            it += 1
            #
            # Print localization progress
            #
            if log.do_medium:
                log('%4i   %14.8f' %(it, abs(objfct-objfct_ref)))
            #
            # Check convergence
            #
            maxThresh = abs(objfct-objfct_ref)>thresh
            maxIter = it<maxiter
            #
            # Prepare for new iteration
            #
            objfct_ref = objfct
        if maxThresh and not maxIter:
            if log.do_medium:
                log(' ')
                log('Warning: Orbital localization not converged in %i iteration' %(it-1))
                log(' ')
        else:
            if log.do_medium:
                log(' ')
                log('Orbital localization converged in %i iteration' %(it-1))
                log(' ')
Пример #34
0
def setup_weights(system, grid, dens=None, near=None, far=None):
    '''Define a weight function for the ESPCost

       **Arguments:**

       system
            The system for which the weight function must be defined

       grid
            A UniformGrid object.

       **Optional arguments:**

       dens
            The density-based criterion. This is a three-tuple with rho, lnrho0
            and sigma. rho is the atomic or the pro-atomic electron density on
            the same grid as the ESP data. lnrho0 and sigma are parameters
            defined in JCTC, 3, 1004 (2007), DOI:10.1021/ct600295n. The weight
            function takes the form::

                exp(-sigma*(ln(rho) - lnrho0)**2)

            Note that the density, rho, should not contain depletions in the
            atomic cores, as is often encountered with pseudo-potential
            computations. In that case it is recommended to construct a
            promolecular density as input for this option.

       near
            Exclude points near the nuclei. This is a dictionary with as items
            (number, (R0, gamma)).

       far
            Exclude points far away. This is a two-tuple: (R0, gamma).
    '''
    weights = np.ones(grid.shape)

    # combine three possible mask functions
    if dens is not None:
        log.cite('hu2007', 'for the ESP fitting weight function')
        rho, lnrho0, sigma = dens
        assert (rho.shape == grid.shape).all()
        multiply_dens_mask(rho, lnrho0, sigma, weights)
    if near is not None:
        for i in xrange(system.natom):
            pair = near.get(system.numbers[i])
            if pair is None:
                pair = near.get(0)
            if pair is None:
                continue
            r0, gamma = pair
            if r0 > 5 * angstrom:
                raise ValueError(
                    'The wnear radius is excessive. Please keep it below 5 angstrom.'
                )
            multiply_near_mask(system.coordinates[i], grid, r0, gamma, weights)
    if far is not None:
        r0, gamma = far
        multiply_far_mask(system.coordinates, grid, r0, gamma, weights)

    # double that weight goes to zero at non-periodic edges
    return weights