Exemplo n.º 1
0
def cholesky_mos(mo_coeff):
    '''
    Calculates localized orbitals through a pivoted Cholesky factorization
    of the density matrix.

    Args:
        mo_coeff: block of MO coefficients to be localized
    
    Returns:
        the localized MOs
    '''
    assert(mo_coeff.ndim == 2)
    nao, nmo = mo_coeff.shape

    # Factorization of a density matrix-like quantity.
    D = np.dot(mo_coeff, mo_coeff.T)
    L, piv, rank = pivoted_cholesky(D, lower=True)
    if rank < nmo:
        raise RuntimeError('rank of matrix lower than the number of orbitals')
    
    # Permute L back to the original order of the AOs.
    # Superfluous columns are cropped out.
    P = np.zeros((nao, nao))
    P[piv, np.arange(nao)] = 1
    mo_loc = np.dot(P, L[:, :nmo])

    return mo_loc
Exemplo n.º 2
0
def partial_cholesky_orth_(S, canthr=1e-7, cholthr=1e-9):
    '''Partial Cholesky orthogonalization for curing overcompleteness.

    References:

    Susi Lehtola, Curing basis set overcompleteness with pivoted
    Cholesky decompositions, J. Chem. Phys. 151, 241102 (2019),
    doi:10.1063/1.5139948.

    Susi Lehtola, Accurate reproduction of strongly repulsive
    interatomic potentials, Phys. Rev. A 101, 032504 (2020),
    doi:10.1103/PhysRevA.101.032504.
    '''
    # Ensure the basis functions are normalized
    normlz = numpy.power(numpy.diag(S), -0.5)
    Snorm = numpy.dot(numpy.diag(normlz), numpy.dot(S, numpy.diag(normlz)))

    # Sort the basis functions according to the Gershgorin circle
    # theorem so that the Cholesky routine is well-initialized
    odS = numpy.abs(Snorm)
    numpy.fill_diagonal(odS, 0.0)
    odSs = numpy.sum(odS, axis=0)
    sortidx = numpy.argsort(odSs)

    # Run the pivoted Cholesky decomposition
    Ssort = Snorm[numpy.ix_(sortidx, sortidx)].copy()
    c, piv, r_c = pivoted_cholesky(Ssort, tol=cholthr)
    # The functions we're going to use are given by the pivot as
    idx = sortidx[piv[:r_c]]

    # Get the (un-normalized) sub-basis
    Ssub = S[numpy.ix_(idx, idx)].copy()
    # Orthogonalize sub-basis
    Xsub = canonical_orth_(Ssub, thr=canthr)

    # Full X
    X = numpy.zeros((S.shape[0], Xsub.shape[1]))
    X[idx, :] = Xsub

    return X