Ejemplo n.º 1
0
    class DFTD3(_DFTD3, method_class):
        def __init__(self, method, with_dftd3):
            self.__dict__.update(method.__dict__)
            self.with_dftd3 = with_dftd3
            self._keys.update(['with_dftd3'])

        def dump_flags(self, verbose=None):
            method_class.dump_flags(self, verbose)
            if self.with_dftd3:
                self.with_dftd3.dump_flags(verbose)
            return self

        def energy_nuc(self):
            # Adding DFT D3 correction to nuclear part because it is computed
            # based on nuclear coordinates only.  It does not depend on
            # quantum effects.
            enuc = method_class.energy_nuc(self)
            if self.with_dftd3:
                enuc += self.with_dftd3.kernel()[0]
            return enuc

        def reset(self, mol=None):
            self.with_dftd3.reset(mol)
            return method_class.reset(self, mol)

        def nuc_grad_method(self):
            scf_grad = method_class.nuc_grad_method(self)
            return grad(scf_grad)

        Gradients = lib.alias(nuc_grad_method, alias_name='Gradients')
Ejemplo n.º 2
0
    class DFTD4(_DFTD4, mf.__class__):
        """
        Patched SCF class including DFT-D4 corrections.
        """
        def __init__(self, method, with_dftd4: DFTD4Dispersion):
            self.__dict__.update(method.__dict__)
            self.with_dftd4 = with_dftd4
            self._keys.update(["with_dftd4"])

        def dump_flags(self, verbose=None) -> "DFTD4":
            mf.__class__.dump_flags(self, verbose)
            if self.with_dftd4:
                self.with_dftd4.dump_flags(verbose)
            return self

        def energy_nuc(self) -> float:
            enuc = mf.__class__.energy_nuc(self)
            if self.with_dftd4:
                enuc += self.with_dftd4.kernel()[0]
            return enuc

        def reset(self, mol=None) -> "DFTD4":
            self.with_dftd4.reset(mol)
            return mf.__class__.reset(self, mol)

        def nuc_grad_method(self) -> "DFTD4Grad":
            scf_grad = mf.__class__.nuc_grad_method(self)
            return grad(scf_grad)

        Gradients = lib.alias(nuc_grad_method, alias_name="Gradients")
Ejemplo n.º 3
0
    class DFTD3(method_class, _DFTD3):
        def dump_flags(self, verbose=None):
            method_class.dump_flags(self, verbose)
            if self.with_dftd3:
                self.with_dftd3.dump_flags(verbose)
            return self

        def energy_nuc(self):
            # Adding DFT D3 correction to nuclear part because it is computed
            # based on nuclear coordinates only.  It does not depend on
            # quantum effects.
            enuc = method_class.energy_nuc(self)
            if self.with_dftd3:
                enuc += self.with_dftd3.kernel()[0]
            return enuc

        def nuc_grad_method(self):
            scf_grad = method_class.nuc_grad_method(self)
            return grad(scf_grad)
        Gradients = lib.alias(nuc_grad_method, alias_name='Gradients')
Ejemplo n.º 4
0
class GradientsBasics(lib.StreamObject):
    '''
    Basic nuclear gradient functions for non-relativistic methods
    '''
    def __init__(self, method):
        self.verbose = method.verbose
        self.stdout = method.stdout
        self.mol = method.mol
        self.base = method
        self.max_memory = self.mol.max_memory

        self.atmlst = None
        self.de = None
        self._keys = set(self.__dict__.keys())

    def dump_flags(self, verbose=None):
        log = logger.new_logger(self, verbose)
        log.info('\n')
        if hasattr(self.base, 'converged') and not self.base.converged:
            log.warn('Ground state %s not converged',
                     self.base.__class__.__name__)
        log.info('******** %s for %s ********', self.__class__,
                 self.base.__class__)
        log.info('max_memory %d MB (current use %d MB)', self.max_memory,
                 lib.current_memory()[0])
        return self

    def get_hcore(self, mol=None):
        if mol is None: mol = self.mol
        return get_hcore(mol)

    hcore_generator = hcore_generator

    def get_ovlp(self, mol=None):
        if mol is None: mol = self.mol
        return get_ovlp(mol)

    @lib.with_doc(get_jk.__doc__)
    def get_jk(self, mol=None, dm=None, hermi=0):
        if mol is None: mol = self.mol
        if dm is None: dm = self.base.make_rdm1()
        cpu0 = (time.clock(), time.time())
        vj, vk = get_jk(mol, dm)
        logger.timer(self, 'vj and vk', *cpu0)
        return vj, vk

    def get_j(self, mol=None, dm=None, hermi=0):
        if mol is None: mol = self.mol
        if dm is None: dm = self.base.make_rdm1()
        intor = mol._add_suffix('int2e_ip1')
        return -_vhf.direct_mapdm(intor, 's2kl', 'lk->s1ij', dm, 3, mol._atm,
                                  mol._bas, mol._env)

    def get_k(self, mol=None, dm=None, hermi=0):
        if mol is None: mol = self.mol
        if dm is None: dm = self.base.make_rdm1()
        intor = mol._add_suffix('int2e_ip1')
        return -_vhf.direct_mapdm(intor, 's2kl', 'jk->s1il', dm, 3, mol._atm,
                                  mol._bas, mol._env)

    def grad_nuc(self, mol=None, atmlst=None):
        if mol is None: mol = self.mol
        return grad_nuc(mol, atmlst)

    def optimizer(self, solver='geometric'):
        '''Geometry optimization solver

        Kwargs:
            solver (string) : geometry optimization solver, can be "geomeTRIC"
            (default) or "berny".
        '''
        if solver.lower() == 'geometric':
            from pyscf.geomopt import geometric_solver
            return geometric_solver.GeometryOptimizer(self.as_scanner())
        elif solver.lower() == 'berny':
            from pyscf.geomopt import berny_solver
            return berny_solver.GeometryOptimizer(self.as_scanner())
        else:
            raise RuntimeError('Unknown geometry optimization solver %s' %
                               solver)

    def grad_elec(self):
        raise NotImplementedError

    def kernel(self):
        raise NotImplementedError

    @lib.with_doc(symmetrize.__doc__)
    def symmetrize(self, de, atmlst=None):
        return symmetrize(self.mol, de, atmlst)

    grad = lib.alias(kernel, alias_name='grad')

    def _finalize(self):
        if self.verbose >= logger.NOTE:
            logger.note(self, '--------------- %s gradients ---------------',
                        self.base.__class__.__name__)
            self._write(self.mol, self.de, self.atmlst)
            logger.note(self, '----------------------------------------------')

    _write = _write

    def as_scanner(self):
        '''Generate Gradients Scanner'''
        raise NotImplementedError
Ejemplo n.º 5
0
class HF(scf.hf.SCF):
    '''Hartree Fock for NEO

    Example:

    >>> from pyscf import neo
    >>> mol = neo.Mole()
    >>> mol.build(atom='H 0 0 0; F 0 0 0.917', basis='ccpvdz')
    >>> mf = neo.HF(mol)
    >>> mf.scf()

    '''
    def __init__(self, mol, unrestricted=False):
        scf.hf.SCF.__init__(self, mol)
        if mol.elec.nhomo is not None:
            unrestricted = True
        self.unrestricted = unrestricted
        self.mf_elec = None
        # dm_elec will be the total density after SCF, but can be spin
        # densities during the SCF procedure
        self.dm_elec = None
        self.mf_nuc = []
        self.dm_nuc = []
        self._eri_ne = []
        self._eri_nn = []
        # The verbosity flag is passed now instead of when creating those mol
        # objects because users need time to change mol's verbose level after
        # the mol object is created.
        self.mol.elec.verbose = self.mol.verbose
        for i in range(mol.nuc_num):
            self.mol.nuc[i].verbose = self.mol.verbose

        # initialize sub mf objects for electrons and quantum nuclei
        # electronic part:
        if unrestricted:
            self.mf_elec = scf.UHF(mol.elec)
        else:
            self.mf_elec = scf.RHF(mol.elec)
        self.mf_elec.get_hcore = self.get_hcore_elec
        self.mf_elec.super_mf = self
        if mol.elec.nhomo is not None:
            self.mf_elec.get_occ = self.get_occ_elec(self.mf_elec)

        # nuclear part
        for i in range(mol.nuc_num):
            self.mf_nuc.append(scf.RHF(mol.nuc[i]))
            mf_nuc = self.mf_nuc[-1]
            mf_nuc.occ_state = 0  # for Delta-SCF
            mf_nuc.get_occ = self.get_occ_nuc(mf_nuc)
            mf_nuc.get_hcore = self.get_hcore_nuc
            mf_nuc.get_veff = self.get_veff_nuc_bare
            mf_nuc.energy_qmnuc = self.energy_qmnuc
            mf_nuc.super_mf = self
            self.dm_nuc.append(None)

        # build ne and nn ERIs if there is enough memory
        for i in range(mol.nuc_num):
            self._eri_ne.append(None)
            self._eri_nn.append([None] * mol.nuc_num)
            if mol.incore_anyway or self._is_mem_enough(
                    mol.elec.nao_nr(), mol.nuc[i].nao_nr()):
                atm, bas, env = gto.conc_env(mol.nuc[i]._atm, mol.nuc[i]._bas,
                                             mol.nuc[i]._env, mol.elec._atm,
                                             mol.elec._bas, mol.elec._env)
                self._eri_ne[i] = \
                    gto.moleintor.getints('int2e_sph', atm, bas, env,
                                          shls_slice=(0, mol.nuc[i]._bas.shape[0], 0, mol.nuc[i]._bas.shape[0],
                                                      mol.nuc[i]._bas.shape[0],
                                                      mol.nuc[i]._bas.shape[0] + mol.elec._bas.shape[0],
                                                      mol.nuc[i]._bas.shape[0],
                                                      mol.nuc[i]._bas.shape[0] + mol.elec._bas.shape[0]),
                                          aosym='s4')
        for i in range(mol.nuc_num - 1):
            for j in range(i + 1, mol.nuc_num):
                if mol.incore_anyway or self._is_mem_enough(
                        mol.nuc[i].nao_nr(), mol.nuc[j].nao_nr()):
                    atm, bas, env = gto.conc_env(
                        mol.nuc[i]._atm, mol.nuc[i]._bas, mol.nuc[i]._env,
                        mol.nuc[j]._atm, mol.nuc[j]._bas, mol.nuc[j]._env)
                    self._eri_nn[i][j] = \
                        gto.moleintor.getints('int2e_sph', atm, bas, env,
                                              shls_slice=(0, mol.nuc[i]._bas.shape[0], 0, mol.nuc[i]._bas.shape[0],
                                                          mol.nuc[i]._bas.shape[0],
                                                          mol.nuc[i]._bas.shape[0] + mol.nuc[j]._bas.shape[0],
                                                          mol.nuc[i]._bas.shape[0],
                                                          mol.nuc[i]._bas.shape[0] + mol.nuc[j]._bas.shape[0]),
                                              aosym='s4')

    #def dump_chk():

    def _is_mem_enough(self, nao1, nao2):
        return nao1**2 * nao2**2 * 2 / 1e6 + lib.current_memory(
        )[0] < self.max_memory * .95

    def get_init_guess_elec(self, mol, init_guess):
        if init_guess != 'chkfile':
            return init_guess_elec_by_calculation(mol, self.unrestricted,
                                                  init_guess)
        else:
            return init_guess_elec_by_chkfile(mol, self.chkfile)

    def get_init_guess_nuc(self, mol, init_guess):
        if init_guess != 'chkfile':
            return init_guess_nuc_by_calculation(self.mf_nuc, mol)
        else:
            return init_guess_nuc_by_chkfile(mol, self.chkfile)

    def get_hcore_elec(self, mol):
        return get_hcore_elec(mol,
                              self.dm_nuc,
                              self.mol.nuc,
                              eri_ne=self._eri_ne)

    def get_occ_nuc(self, mf):
        return get_occ_nuc(mf)

    def get_occ_elec(self, mf):
        return get_occ_elec(mf)

    def get_hcore_nuc(self, mol):
        return get_hcore_nuc(mol,
                             self.dm_elec,
                             self.dm_nuc,
                             self.mol.elec,
                             self.mol.nuc,
                             eri_ne=self._eri_ne,
                             eri_nn=self._eri_nn)

    def get_veff_nuc_bare(self, mol, dm):
        return get_veff_nuc_bare(mol, dm)

    def energy_qmnuc(self, mf, h1n, dm_nuc, veff_n=None):
        return energy_qmnuc(mf, h1n, dm_nuc, veff_n=veff_n)

    def energy_tot(self, dm_elec, dm_nuc, h1e, vhf_e, h1n, veff_n=None):
        return energy_tot(self.mf_elec,
                          self.mf_nuc,
                          dm_elec,
                          dm_nuc,
                          h1e,
                          vhf_e,
                          h1n,
                          veff_n=veff_n)

    def scf(self, dm0e=None, dm0n=[], **kwargs):
        cput0 = (logger.process_clock(), logger.perf_counter())

        self.dump_flags()

        if self.max_cycle > 0 or self.mo_coeff is None:
            self.converged, self.e_tot, self.mf_elec.mo_energy, \
                self.mf_elec.mo_coeff, self.mf_elec.mo_occ = \
                    kernel(self, self.conv_tol, self.conv_tol_grad,
                           dm0e=dm0e, dm0n=dm0n, callback=self.callback,
                           conv_check=self.conv_check, **kwargs)[0 : 5]
        else:
            self.e_tot = kernel(self,
                                self.conv_tol,
                                self.conv_tol_grad,
                                dm0e=dm0e,
                                dm0n=dm0n,
                                callback=self.callback,
                                conv_check=self.conv_check,
                                **kwargs)[1]

        logger.timer(self, 'SCF', *cput0)
        self._finalize()
        return self.e_tot

    kernel = lib.alias(scf, alias_name='kernel')
Ejemplo n.º 6
0
        class A:
            def f1(self):
                return 'a'

            f2 = lib.alias(f1)
Ejemplo n.º 7
0
class GradientsMixin(lib.StreamObject):
    '''
    Basic nuclear gradient functions for non-relativistic methods
    '''
    def __init__(self, method):
        self.verbose = method.verbose
        self.stdout = method.stdout
        self.mol = method.mol
        self.base = method
        self.max_memory = self.mol.max_memory
        self.unit = 'au'

        self.atmlst = None
        self.de = None
        self._keys = set(self.__dict__.keys())

    def dump_flags(self, verbose=None):
        log = logger.new_logger(self, verbose)
        log.info('\n')
        if hasattr(self.base, 'converged') and not self.base.converged:
            log.warn('Ground state %s not converged',
                     self.base.__class__.__name__)
        log.info('******** %s for %s ********', self.__class__,
                 self.base.__class__)
        if 'ANG' in self.unit.upper():
            raise NotImplementedError('unit Eh/Ang is not supported')
        else:
            log.info('unit = Eh/Bohr')
        log.info('max_memory %d MB (current use %d MB)', self.max_memory,
                 lib.current_memory()[0])
        return self

    def get_hcore(self, mol=None):
        if mol is None: mol = self.mol
        return get_hcore(mol)

    hcore_generator = hcore_generator

    def get_ovlp(self, mol=None):
        if mol is None: mol = self.mol
        return get_ovlp(mol)

    @lib.with_doc(get_jk.__doc__)
    def get_jk(self, mol=None, dm=None, hermi=0):
        if mol is None: mol = self.mol
        if dm is None: dm = self.base.make_rdm1()
        cpu0 = (time.clock(), time.time())
        vj, vk = get_jk(mol, dm)
        logger.timer(self, 'vj and vk', *cpu0)
        return vj, vk

    def get_j(self, mol=None, dm=None, hermi=0):
        if mol is None: mol = self.mol
        if dm is None: dm = self.base.make_rdm1()
        intor = mol._add_suffix('int2e_ip1')
        return -_vhf.direct_mapdm(intor, 's2kl', 'lk->s1ij', dm, 3, mol._atm,
                                  mol._bas, mol._env)

    def get_k(self, mol=None, dm=None, hermi=0):
        if mol is None: mol = self.mol
        if dm is None: dm = self.base.make_rdm1()
        intor = mol._add_suffix('int2e_ip1')
        return -_vhf.direct_mapdm(intor, 's2kl', 'jk->s1il', dm, 3, mol._atm,
                                  mol._bas, mol._env)

    def get_veff(self, mol=None, dm=None):
        raise NotImplementedError

    def make_rdm1e(self, mo_energy=None, mo_coeff=None, mo_occ=None):
        raise NotImplementedError

    def grad_nuc(self, mol=None, atmlst=None):
        if mol is None: mol = self.mol
        return grad_nuc(mol, atmlst)

    def optimizer(self, solver='geometric'):
        '''Geometry optimization solver

        Kwargs:
            solver (string) : geometry optimization solver, can be "geomeTRIC"
            (default) or "berny".
        '''
        if solver.lower() == 'geometric':
            from pyscf.geomopt import geometric_solver
            return geometric_solver.GeometryOptimizer(self.as_scanner())
        elif solver.lower() == 'berny':
            from pyscf.geomopt import berny_solver
            return berny_solver.GeometryOptimizer(self.as_scanner())
        else:
            raise RuntimeError('Unknown geometry optimization solver %s' %
                               solver)

    @lib.with_doc(symmetrize.__doc__)
    def symmetrize(self, de, atmlst=None):
        return symmetrize(self.mol, de, atmlst)

    def grad_elec(self):
        raise NotImplementedError

    def extra_force(self, atom_id, envs):
        '''Hook for extra contributions in analytical gradients.

        Contributions like the response of auxiliary basis in density fitting
        method, the grid response in DFT numerical integration can be put in
        this function.
        '''
        return 0

    def kernel(self, mo_energy=None, mo_coeff=None, mo_occ=None, atmlst=None):
        cput0 = (time.clock(), time.time())
        if mo_energy is None: mo_energy = self.base.mo_energy
        if mo_coeff is None: mo_coeff = self.base.mo_coeff
        if mo_occ is None: mo_occ = self.base.mo_occ
        if atmlst is None:
            atmlst = self.atmlst
        else:
            self.atmlst = atmlst

        if self.verbose >= logger.WARN:
            self.check_sanity()
        if self.verbose >= logger.INFO:
            self.dump_flags()

        de = self.grad_elec(mo_energy, mo_coeff, mo_occ, atmlst)
        self.de = de + self.grad_nuc(atmlst=atmlst)
        if self.mol.symmetry:
            self.de = self.symmetrize(self.de, atmlst)
        logger.timer(self, 'SCF gradients', *cput0)
        self._finalize()
        return self.de

    grad = lib.alias(kernel, alias_name='grad')

    def _finalize(self):
        if self.verbose >= logger.NOTE:
            logger.note(self, '--------------- %s gradients ---------------',
                        self.base.__class__.__name__)
            self._write(self.mol, self.de, self.atmlst)
            logger.note(self, '----------------------------------------------')

    _write = _write

    as_scanner = as_scanner