예제 #1
0
def mulliken_meta(cell,
                  dm_ao_kpts,
                  verbose=logger.DEBUG,
                  pre_orth_method=PRE_ORTH_METHOD,
                  s=None):
    '''A modified Mulliken population analysis, based on meta-Lowdin AOs.

    Note this function only computes the Mulliken population for the gamma
    point density matrix.
    '''
    from pyscf.lo import orth
    if s is None:
        s = get_ovlp(cell)
    log = logger.new_logger(cell, verbose)
    log.note('Analyze output for *gamma point*')
    log.info('    To include the contributions from k-points, transform to a '
             'supercell then run the population analysis on the supercell\n'
             '        from pyscf.pbc.tools import k2gamma\n'
             '        k2gamma.k2gamma(mf).mulliken_meta()')
    log.note("KRHF mulliken_meta")
    dm_ao_gamma = dm_ao_kpts[0, :, :].real
    s_gamma = s[0, :, :].real
    c = orth.restore_ao_character(cell, pre_orth_method)
    orth_coeff = orth.orth_ao(cell, 'meta_lowdin', pre_orth_ao=c, s=s_gamma)
    c_inv = np.dot(orth_coeff.T, s_gamma)
    dm = reduce(np.dot, (c_inv, dm_ao_gamma, c_inv.T.conj()))

    log.note(' ** Mulliken pop on meta-lowdin orthogonal AOs **')
    return mol_hf.mulliken_pop(cell, dm, np.eye(orth_coeff.shape[0]), log)
예제 #2
0
파일: kuhf.py 프로젝트: chrinide/pyscf
def mulliken_meta(cell, dm_ao_kpts, verbose=logger.DEBUG,
                  pre_orth_method=PRE_ORTH_METHOD, s=None):
    '''A modified Mulliken population analysis, based on meta-Lowdin AOs.

    Note this function only computes the Mulliken population for the gamma
    point density matrix.
    '''
    from pyscf.lo import orth
    if s is None:
        s = khf.get_ovlp(cell)
    log = logger.new_logger(cell, verbose)
    log.note('Analyze output for *gamma point*.')
    log.info('    To include the contributions from k-points, transform to a '
             'supercell then run the population analysis on the supercell\n'
             '        from pyscf.pbc.tools import k2gamma\n'
             '        k2gamma.k2gamma(mf).mulliken_meta()')
    log.note("KUHF mulliken_meta")
    dm_ao_gamma = dm_ao_kpts[:,0,:,:].real
    s_gamma = s[0,:,:].real
    c = orth.restore_ao_character(cell, pre_orth_method)
    orth_coeff = orth.orth_ao(cell, 'meta_lowdin', pre_orth_ao=c, s=s_gamma)
    c_inv = np.dot(orth_coeff.T, s_gamma)
    dm_a = reduce(np.dot, (c_inv, dm_ao_gamma[0], c_inv.T.conj()))
    dm_b = reduce(np.dot, (c_inv, dm_ao_gamma[1], c_inv.T.conj()))

    log.note(' ** Mulliken pop alpha/beta on meta-lowdin orthogonal AOs **')
    return mol_uhf.mulliken_pop(cell, (dm_a,dm_b), np.eye(orth_coeff.shape[0]), log)
예제 #3
0
def mulliken_meta(cell,
                  dm_ao_kpts,
                  verbose=logger.DEBUG,
                  pre_orth_method=PRE_ORTH_METHOD,
                  s=None):
    '''Mulliken population analysis, based on meta-Lowdin AOs.

    Note this function only computes the Mulliken population for the gamma
    point density matrix.
    '''
    from pyscf.lo import orth
    if s is None:
        s = get_ovlp(cell)
    log = logger.new_logger(cell, verbose)
    log.note('Analyze output for the gamma point')
    log.note("KRHF mulliken_meta")
    dm_ao_gamma = dm_ao_kpts[0, :, :].real
    s_gamma = s[0, :, :].real
    c = orth.restore_ao_character(cell, pre_orth_method)
    orth_coeff = orth.orth_ao(cell, 'meta_lowdin', pre_orth_ao=c, s=s_gamma)
    c_inv = np.dot(orth_coeff.T, s_gamma)
    dm = reduce(np.dot, (c_inv, dm_ao_gamma, c_inv.T.conj()))

    log.note(' ** Mulliken pop on meta-lowdin orthogonal AOs **')
    return mol_hf.mulliken_pop(cell, dm, np.eye(orth_coeff.shape[0]), log)
예제 #4
0
def mulliken_meta(mol, dm_ao, verbose=logger.DEBUG,
                  pre_orth_method=PRE_ORTH_METHOD, s=None):
    '''Mulliken population analysis, based on meta-Lowdin AOs.
    '''
    from pyscf.lo import orth
    if s is None: s = hf.get_ovlp(mol)
    log = logger.new_logger(mol, verbose)
    if isinstance(dm_ao, numpy.ndarray) and dm_ao.ndim == 2:
        dm_ao = numpy.array((dm_ao*.5, dm_ao*.5))
    c = orth.restore_ao_character(mol, pre_orth_method)
    orth_coeff = orth.orth_ao(mol, 'meta_lowdin', pre_orth_ao=c, s=s)
    c_inv = numpy.dot(orth_coeff.T, s)
    dm_a = reduce(numpy.dot, (c_inv, dm_ao[0], c_inv.T.conj()))
    dm_b = reduce(numpy.dot, (c_inv, dm_ao[1], c_inv.T.conj()))

    log.note(' ** Mulliken pop alpha/beta on meta-lowdin orthogonal AOs **')
    return mulliken_pop(mol, (dm_a,dm_b), numpy.eye(orth_coeff.shape[0]), log)
예제 #5
0
파일: uhf.py 프로젝트: sunqm/pyscf
def mulliken_meta(mol, dm_ao, verbose=logger.DEBUG,
                  pre_orth_method=PRE_ORTH_METHOD, s=None):
    '''Mulliken population analysis, based on meta-Lowdin AOs.
    '''
    from pyscf.lo import orth
    if s is None: s = hf.get_ovlp(mol)
    log = logger.new_logger(mol, verbose)
    if isinstance(dm_ao, numpy.ndarray) and dm_ao.ndim == 2:
        dm_ao = numpy.array((dm_ao*.5, dm_ao*.5))
    c = orth.restore_ao_character(mol, pre_orth_method)
    orth_coeff = orth.orth_ao(mol, 'meta_lowdin', pre_orth_ao=c, s=s)
    c_inv = numpy.dot(orth_coeff.T, s)
    dm_a = reduce(numpy.dot, (c_inv, dm_ao[0], c_inv.T.conj()))
    dm_b = reduce(numpy.dot, (c_inv, dm_ao[1], c_inv.T.conj()))

    log.note(' ** Mulliken pop alpha/beta on meta-lowdin orthogonal AOs **')
    return mulliken_pop(mol, (dm_a,dm_b), numpy.eye(orth_coeff.shape[0]), log)
예제 #6
0
def atomic_pops(mol, mo_coeff, method='meta_lowdin'):
    '''
    Kwargs:
        method : string
            one of mulliken, lowdin, meta_lowdin

    Returns:
        A 3-index tensor [A,i,j] indicates the population of any orbital-pair
        density |i><j| for each species (atom in this case).  This tensor is
        used to construct the population and gradients etc.
        
        You can customize the PM localization wrt other population metric,
        such as the charge of a site, the charge of a fragment (a group of
        atoms) by overwriting this tensor.  See also the example
        pyscf/examples/loc_orb/40-hubbard_model_PM_localization.py for the PM
        localization of site-based population for hubbard model.
    '''
    if getattr(mol, 'pbc_intor', None):  # whether mol object is a cell
        s = mol.pbc_intor('int1e_ovlp_sph', hermi=1)
    else:
        s = mol.intor_symmetric('int1e_ovlp')
    nmo = mo_coeff.shape[1]
    proj = numpy.empty((mol.natm, nmo, nmo))

    if method.lower() == 'mulliken':
        for i, (b0, b1, p0, p1) in enumerate(mol.offset_nr_by_atom()):
            csc = reduce(numpy.dot,
                         (mo_coeff[p0:p1].conj().T, s[p0:p1], mo_coeff))
            proj[i] = (csc + csc.conj().T) * .5

    elif method.lower() in ('lowdin', 'meta_lowdin'):
        c = orth.restore_ao_character(mol, 'ANO')
        csc = reduce(lib.dot,
                     (mo_coeff.conj().T, s, orth.orth_ao(mol, method, c, s=s)))
        for i, (b0, b1, p0, p1) in enumerate(mol.offset_nr_by_atom()):
            proj[i] = numpy.dot(csc[:, p0:p1], csc[:, p0:p1].conj().T)
    else:
        raise KeyError('method = %s' % method)

    return proj
예제 #7
0
def atomic_pops(mol, mo_coeff, method='meta_lowdin'):
    '''kwarg method can be one of mulliken, lowdin, meta_lowdin
    '''
    s = mol.intor_symmetric('int1e_ovlp')
    nmo = mo_coeff.shape[1]
    proj = numpy.empty((mol.natm, nmo, nmo))

    if method.lower() == 'mulliken':
        for i, (b0, b1, p0, p1) in enumerate(mol.offset_nr_by_atom()):
            csc = reduce(numpy.dot, (mo_coeff[p0:p1].T, s[p0:p1], mo_coeff))
            proj[i] = (csc + csc.T) * .5

    elif method.lower() in ('lowdin', 'meta_lowdin'):
        c = orth.restore_ao_character(mol, 'ANO')
        csc = reduce(lib.dot,
                     (mo_coeff.T, s, orth.orth_ao(mol, method, c, s=s)))
        for i, (b0, b1, p0, p1) in enumerate(mol.offset_nr_by_atom()):
            proj[i] = numpy.dot(csc[:, p0:p1], csc[:, p0:p1].T)
    else:
        raise KeyError('method = %s' % method)

    return proj
예제 #8
0
def atomic_pops(mol, mo_coeff, method='meta_lowdin', mf=None):
    '''
    Kwargs:
        method : string
            The atomic population projection scheme. It can be mulliken,
            lowdin, meta_lowdin, iao, or becke

    Returns:
        A 3-index tensor [A,i,j] indicates the population of any orbital-pair
        density |i><j| for each species (atom in this case).  This tensor is
        used to construct the population and gradients etc.

        You can customize the PM localization wrt other population metric,
        such as the charge of a site, the charge of a fragment (a group of
        atoms) by overwriting this tensor.  See also the example
        pyscf/examples/loc_orb/40-hubbard_model_PM_localization.py for the PM
        localization of site-based population for hubbard model.
    '''
    method = method.lower().replace('_', '-')
    nmo = mo_coeff.shape[1]
    proj = numpy.empty((mol.natm, nmo, nmo))

    if getattr(mol, 'pbc_intor', None):  # whether mol object is a cell
        s = mol.pbc_intor('int1e_ovlp_sph', hermi=1)
    else:
        s = mol.intor_symmetric('int1e_ovlp')

    if method == 'becke':
        from pyscf.dft import gen_grid
        if not (getattr(mf, 'grids', None) and getattr(mf, '_numint', None)):
            # Call DFT to initialize grids and numint objects
            mf = mol.RKS()
        grids = mf.grids
        ni = mf._numint

        if not isinstance(grids, gen_grid.Grids):
            raise NotImplementedError('PM becke scheme for PBC systems')

        # The atom-wise Becke grids (without concatenated to a vector of grids)
        coords, weights = grids.get_partition(mol, concat=False)

        for i in range(mol.natm):
            ao = ni.eval_ao(mol, coords[i], deriv=0)
            aow = numpy.einsum('pi,p->pi', ao, weights[i])
            charge_matrix = lib.dot(aow.conj().T, ao)
            proj[i] = reduce(lib.dot,
                             (mo_coeff.conj().T, charge_matrix, mo_coeff))

    elif method == 'mulliken':
        for i, (b0, b1, p0, p1) in enumerate(mol.offset_nr_by_atom()):
            csc = reduce(numpy.dot,
                         (mo_coeff[p0:p1].conj().T, s[p0:p1], mo_coeff))
            proj[i] = (csc + csc.conj().T) * .5

    elif method in ('lowdin', 'meta-lowdin'):
        c = orth.restore_ao_character(mol, 'ANO')
        #csc = reduce(lib.dot, (mo_coeff.conj().T, s, orth_local_ao_coeff))
        csc = reduce(lib.dot,
                     (mo_coeff.conj().T, s, orth.orth_ao(mol, method, c, s=s)))
        for i, (b0, b1, p0, p1) in enumerate(mol.offset_nr_by_atom()):
            proj[i] = numpy.dot(csc[:, p0:p1], csc[:, p0:p1].conj().T)

    elif method in ('iao', 'ibo'):
        from pyscf.lo import iao
        assert mf is not None
        # FIXME: How to handle UHF/UKS object?
        orb_occ = mf.mo_coeff[:, mf.mo_occ > 0]

        iao_coeff = iao.iao(mol, orb_occ)
        #
        # IAO is generally not orthogonalized. For simplicity, we take Lowdin
        # orthogonalization here. Other orthogonalization can be used. Results
        # should be very closed to the Lowdin-orth orbitals
        #
        # PM with Mulliken population of non-orth IAOs can be found in
        # ibo.PipekMezey function
        #
        iao_coeff = orth.vec_lowdin(iao_coeff, s)
        csc = reduce(lib.dot, (mo_coeff.conj().T, s, iao_coeff))

        iao_mol = iao.reference_mol(mol)
        for i, (b0, b1, p0, p1) in enumerate(iao_mol.offset_nr_by_atom()):
            proj[i] = numpy.dot(csc[:, p0:p1], csc[:, p0:p1].conj().T)

    else:
        raise KeyError('method = %s' % method)

    return proj