Beispiel #1
0
def fast_newton(mf,
                mo_coeff=None,
                mo_occ=None,
                dm0=None,
                auxbasis=None,
                projectbasis=None,
                **newton_kwargs):
    '''Wrap function to quickly setup and call Newton solver.
    Newton solver attributes [max_cycle_inner, max_stepsize, ah_start_tol,
    ah_conv_tol, ah_grad_trust_region, ...] can be passed through **newton_kwargs.
    '''
    import copy
    from pyscf.lib import logger
    from pyscf import df
    if auxbasis is None:
        auxbasis = df.addons.aug_etb_for_dfbasis(mf.mol, 'ahlrichs', beta=2.5)
    if projectbasis:
        mf1 = newton(mf)
        pmol = mf1.mol = newton_ah.project_mol(mf.mol, projectbasis)
        mf1 = density_fit(mf1, auxbasis)
    else:
        mf1 = density_fit(newton(mf), auxbasis)
    mf1.direct_scf_tol = 1e-7

    if hasattr(mf, 'grids'):
        from pyscf.dft import gen_grid
        approx_grids = gen_grid.Grids(mf.mol)
        approx_grids.verbose = 0
        approx_grids.level = max(0, mf.grids.level - 2)
        mf1.grids = approx_grids

        approx_numint = copy.copy(mf._numint)
        mf1._numint = approx_numint
    for key in newton_kwargs:
        setattr(mf1, key, newton_kwargs[key])

    if mo_coeff is None or mo_occ is None:
        mo_coeff, mo_occ = mf.mo_coeff, mf.mo_occ

    if dm0 is not None:
        mo_coeff, mo_occ = mf1.from_dm(dm0)
    elif mo_coeff is None or mo_occ is None:
        logger.note(
            mf, '========================================================')
        logger.note(
            mf, 'Generating initial guess with DIIS-SCF for newton solver')
        logger.note(
            mf, '========================================================')
        if projectbasis:
            mf0 = copy.copy(mf)
            mf0.mol = pmol
            mf0 = density_fit(mf0, auxbasis)
        else:
            mf0 = density_fit(mf, auxbasis)
        mf0.direct_scf_tol = 1e-7
        mf0.conv_tol = 3.
        mf0.conv_tol_grad = 1.
        if mf0.level_shift == 0:
            mf0.level_shift = .2
        if hasattr(mf, 'grids'):
            mf0.grids = approx_grids
            mf0._numint = approx_numint
            # Note: by setting small_rho_cutoff, dft.get_veff function may overwrite
            # approx_grids and approx_numint.  It will further changes the corresponding
            # mf1 grids and _numint.  If inital guess dm0 or mo_coeff/mo_occ were given,
            # dft.get_veff are not executed so that more grid points may be found in
            # approx_grids.
            mf0.small_rho_cutoff = mf.small_rho_cutoff * 10
        mf0.kernel()
        mo_coeff, mo_occ = mf0.mo_coeff, mf0.mo_occ

        if projectbasis:
            if mo_occ.ndim == 2:
                mo_coeff = (project_mo_nr2nr(pmol, mo_coeff[0], mf.mol),
                            project_mo_nr2nr(pmol, mo_coeff[1], mf.mol))
            else:
                mo_coeff = project_mo_nr2nr(pmol, mo_coeff, mf.mol)
            mo_coeff, mo_occ = mf1.from_dm(mf.make_rdm1(mo_coeff, mo_occ))

        logger.note(mf, '============================')
        logger.note(mf, 'Generating initial guess end')
        logger.note(mf, '============================')

    mf1.kernel(mo_coeff, mo_occ)
    mf.converged = mf1.converged
    mf.e_tot = mf1.e_tot
    mf.mo_energy = mf1.mo_energy
    mf.mo_coeff = mf1.mo_coeff
    mf.mo_occ = mf1.mo_occ

    mf = copy.copy(mf)

    def mf_kernel(*args, **kwargs):
        logger.warn(
            mf,
            "fast_newton is a wrap function to quickly setup and call Newton solver. "
            "There's no need to call kernel function again for fast_newton.")
        del (mf.kernel)  # warn once and remove circular depdence
        return mf.e_tot

    mf.kernel = mf_kernel
    return mf
Beispiel #2
0
def fast_newton(mf, mo_coeff=None, mo_occ=None, dm0=None,
                auxbasis=None, projectbasis=None, **newton_kwargs):
    '''Wrap function to quickly setup and call Newton solver.
    Newton solver attributes [max_cycle_inner, max_stepsize, ah_start_tol,
    ah_conv_tol, ah_grad_trust_region, ...] can be passed through **newton_kwargs.
    '''
    import copy
    from pyscf.lib import logger
    from pyscf import df
    if auxbasis is None:
        auxbasis = df.addons.aug_etb_for_dfbasis(mf.mol, 'ahlrichs', beta=2.5)
    if projectbasis:
        mf1 = newton(mf)
        pmol = mf1.mol = newton_ah.project_mol(mf.mol, projectbasis)
        mf1 = density_fit(mf1, auxbasis)
    else:
        mf1 = density_fit(newton(mf), auxbasis)
    mf1.direct_scf_tol = 1e-7

    if hasattr(mf, 'grids'):
        from pyscf.dft import gen_grid
        approx_grids = gen_grid.Grids(mf.mol)
        approx_grids.verbose = 0
        approx_grids.level = 0
        mf1.grids = approx_grids

        approx_numint = copy.copy(mf._numint)
        mf1._numint = approx_numint
    for key in newton_kwargs:
        setattr(mf1, key, newton_kwargs[key])

    if mo_coeff is None or mo_occ is None:
        mo_coeff, mo_occ = mf.mo_coeff, mf.mo_occ

    if dm0 is not None:
        mo_coeff, mo_occ = mf1.from_dm(dm0)
    elif mo_coeff is None or mo_occ is None:
        logger.note(mf, '========================================================')
        logger.note(mf, 'Generating initial guess with DIIS-SCF for newton solver')
        logger.note(mf, '========================================================')
        if projectbasis:
            mf0 = copy.copy(mf)
            mf0.mol = pmol
            mf0 = density_fit(mf0, auxbasis)
        else:
            mf0 = density_fit(mf, auxbasis)
        mf0.direct_scf_tol = 1e-7
        mf0.conv_tol = 3.
        mf0.conv_tol_grad = 1.
        if mf0.level_shift == 0:
            mf0.level_shift = .2
        if hasattr(mf, 'grids'):
            mf0.grids = approx_grids
            mf0._numint = approx_numint
# Note: by setting small_rho_cutoff, dft.get_veff function may overwrite
# approx_grids and approx_numint.  It will further changes the corresponding
# mf1 grids and _numint.  If inital guess dm0 or mo_coeff/mo_occ were given,
# dft.get_veff are not executed so that more grid points may be found in
# approx_grids.
            mf0.small_rho_cutoff = 1e-5
        mf0.kernel()
        mo_coeff, mo_occ = mf0.mo_coeff, mf0.mo_occ

        if projectbasis:
            if mo_occ.ndim == 2:
                mo_coeff =(project_mo_nr2nr(pmol, mo_coeff[0], mf.mol),
                           project_mo_nr2nr(pmol, mo_coeff[1], mf.mol))
            else:
                mo_coeff = project_mo_nr2nr(pmol, mo_coeff, mf.mol)
            mo_coeff, mo_occ = mf1.from_dm(mf.make_rdm1(mo_coeff,mo_occ))

        logger.note(mf, '============================')
        logger.note(mf, 'Generating initial guess end')
        logger.note(mf, '============================')

    mf1.kernel(mo_coeff, mo_occ)
    mf.converged = mf1.converged
    mf.e_tot     = mf1.e_tot
    mf.mo_energy = mf1.mo_energy
    mf.mo_coeff  = mf1.mo_coeff
    mf.mo_occ    = mf1.mo_occ

    def mf_kernel(*args, **kwargs):
        logger.warn(mf, "fast_newton is a wrap function to quickly setup and call Newton solver. "
                    "There's no need to call kernel function again for fast_newton.")
        del(mf.kernel)  # warn once and remove circular depdence
        return mf.e_tot
    mf.kernel = mf_kernel
    return mf