Beispiel #1
0
def get_frozen_mask(mp):
    '''Boolean mask for orbitals in k-point post-HF method.

    Creates a boolean mask to remove frozen orbitals and keep other orbitals for post-HF
    calculations.

    Args:
        mp (:class:`MP2`): An instantiation of an SCF or post-Hartree-Fock object.

    Returns:
        moidx (list of :obj:`ndarray` of `bool`): Boolean mask of orbitals to include.

    '''
    moidx = [[np.ones(x.size, dtype=bool) for x in mp.mo_occ[s]]
             for s in [0, 1]]

    if mp.frozen is None:
        pass

    elif isinstance(mp.frozen, (int, np.integer)):
        for spin in [0, 1]:
            for idx in moidx[spin]:
                idx[:mp.frozen] = False

    elif (_is_arraylike(mp.frozen[0]) and
          isinstance(mp.frozen[0][0],
                     (int, np.integer))):  # case example: ([0, 4], [0, 5, 6])
        assert (len(mp.frozen) == 2)
        for spin in [0, 1]:
            [
                _frozen_sanity_check(mp.frozen[spin], mp.mo_occ[spin][ikpt],
                                     ikpt) for ikpt in range(mp.nkpts)
            ]
            for ikpt, kpt_occ in enumerate(moidx[spin]):
                kpt_occ[mp.frozen[spin]] = False

    elif (_is_arraylike(mp.frozen[0]) and isinstance(
            mp.frozen[0][0],
        (list, np.ndarray))):  # case example: ([[0,],[]], [[0,1],[4]])
        assert (len(mp.frozen) == 2)
        for spin in [0, 1]:
            nkpts = len(mp.frozen[spin])
            if nkpts != mp.nkpts:
                raise RuntimeError(
                    'Frozen list has a different number of k-points (length) than passed in'
                    'mean-field/correlated calculation.  \n\nCalculation nkpts = %d, frozen'
                    'list = %s (length = %d)' % (mp.nkpts, mp.frozen, nkpts))
        for spin in [0, 1]:
            [
                _frozen_sanity_check(mp.frozen[spin][ikpt],
                                     mp.mo_occ[spin][ikpt], ikpt)
                for ikpt in range(mp.nkpts)
            ]
            for ikpt, kpt_occ in enumerate(moidx[spin]):
                kpt_occ[mp.frozen[spin][ikpt]] = False
    else:
        raise NotImplementedError('No known conversion for frozen %s' %
                                  mp.frozen)

    return moidx
Beispiel #2
0
def get_nmo(mp, per_kpoint=False):
    '''Number of orbitals for k-point calculations.

    Number of orbitals for use in a calculation with k-points, taking into account
    frozen orbitals.

    Note:
        If `per_kpoint` is False, then the number of orbitals here is equal to max(nocc) + max(nvir),
        where each max is done over all k-points.  Otherwise the number of orbitals is returned
        as a list of number of orbitals at each k-point.

    Args:
        mp (:class:`MP2`): An instantiation of an SCF or post-Hartree-Fock object.
        per_kpoint (bool, optional): True returns the number of orbitals at each k-point.
            For a description of False, see Note.

    Returns:
        nmo (int, list of int): Number of orbitals. For return type, see description of arg
            `per_kpoint`.

    '''
    if mp._nmo is not None:
        return mp._nmo

    nmo = [0, 0]
    if isinstance(mp.frozen, (int, np.integer)):
        for spin in [0, 1]:
            nmo[spin] = [
                len(mp.mo_occ[spin][k]) - mp.frozen for k in range(mp.nkpts)
            ]

    elif mp.frozen is None:
        nmo = [[len(mp.mo_occ[0][k]) for k in range(mp.nkpts)],
               [len(mp.mo_occ[1][k]) for k in range(mp.nkpts)]]

    elif (_is_arraylike(mp.frozen[0]) and
          isinstance(mp.frozen[0][0],
                     (int, np.integer))):  # case example: ([0, 4], [0, 5, 6])
        assert (len(mp.frozen) == 2)
        for spin in [0, 1]:
            [
                _frozen_sanity_check(mp.frozen[spin], mp.mo_occ[spin][ikpt],
                                     ikpt) for ikpt in range(mp.nkpts)
            ]
            nmo[spin] = [
                len(mp.mo_occ[spin][ikpt]) - len(mp.frozen[spin])
                for ikpt in range(mp.nkpts)
            ]

    elif (_is_arraylike(mp.frozen[0]) and isinstance(
            mp.frozen[0][0],
        (list, np.ndarray))):  # case example: ([[0,],[]], [[0,1],[4]])
        assert (len(mp.frozen) == 2)
        for spin in [0, 1]:
            nkpts = len(mp.frozen[spin])
            if nkpts != mp.nkpts:
                raise RuntimeError(
                    'Frozen list has a different number of k-points (length) than passed in'
                    'mean-field/correlated calculation.  \n\nCalculation nkpts = %d, frozen'
                    'list = %s (length = %d)' % (mp.nkpts, mp.frozen, nkpts))
        for spin in [0, 1]:
            [
                _frozen_sanity_check(mp.frozen[spin][ikpt],
                                     mp.mo_occ[spin][ikpt], ikpt)
                for ikpt in range(mp.nkpts)
            ]
            nmo[spin] = [
                len(mp.mo_occ[spin][ikpt]) - len(mp.frozen[spin][ikpt])
                for ikpt in range(nkpts)
            ]

    else:
        raise NotImplementedError('No known conversion for frozen %s' %
                                  mp.frozen)

    for spin in [0, 1]:
        assert all(np.array(nmo[spin]) > 0), (
            'Must have a positive number of orbitals! (spin=%d)'
            '\n\nnmo %s\nfrozen %s\nmo_occ %s' %
            (spin, nmo, mp.frozen, mp.mo_occ))

    nmoa, nmob = nmo
    if not per_kpoint:
        # Depending on whether there are more occupied bands, we want to make sure    that
        # nmo has enough room for max(nocc) + max(nvir) number of orbitals for        occupied
        # and virtual space
        nocca, noccb = mp.get_nocc(per_kpoint=True)
        nmoa = np.amax(nocca) + np.max(np.array(nmoa) - np.array(nocca))
        nmob = np.amax(noccb) + np.max(np.array(nmob) - np.array(noccb))

    return nmoa, nmob
Beispiel #3
0
def get_nocc(mp, per_kpoint=False):
    '''Number of occupied orbitals for k-point calculations.

    Number of occupied orbitals for use in a calculation with k-points, taking into
    account frozen orbitals.

    Args:
        mp (:class:`MP2`): An instantiation of an SCF or post-Hartree-Fock object.
        per_kpoint (bool, optional): True returns the number of occupied
            orbitals at each k-point.  False gives the max of this list.

    Returns:
        nocc (int, list of int): Number of occupied orbitals. For return type, see description of arg
            `per_kpoint`.

    Notes:
        For specifying frozen orbitals inside mp, the following options are accepted:

            +=========================+========================================+===============================+
            | Argument (Example)      | Argument Meaning                       | Example Meaning               |
            +=========================+========================================+===============================+
            | int (1)                 | Freeze the same number of orbitals     | Freeze one (lowest) orbital   |
            |                         | regardless of spin and/or kpt          | for all kpts and spin cases   |
            +-------------------------+----------------------------------------+-------------------------------+
            | 2-tuple of list of int  | inner list: List of orbitals indices   | Freeze the orbitals [0,4] for |
            | ([0, 4], [0, 5, 6])     |   to freeze at all kpts                | spin0, and orbitals [0,5,6]   |
            |                         | outer list: Spin index                 | for spin1 at all kpts         |
            +-------------------------+----------------------------------------+-------------------------------+
            | list(2) of list of list | inner list: list of orbital indices to | Freeze orbital 0 for spin0 at |
            | ([[0,],[]],             |   freeze at each kpt for given spin    | kpt0, and freeze orbital 0,1  |
            |  [[0,1],[4]])           | outer list: spin index                 | for spin1 at kpt0 and orbital |
            |                         |                                        | 4 at kpt1                     |
            +-------------------------+----------------------------------------+-------------------------------+

    '''
    for spin in [0, 1]:
        for i, moocc in enumerate(mp.mo_occ[spin]):
            if np.any(moocc % 1 != 0):
                raise RuntimeError(
                    "Fractional occupation numbers encountered @ kp={:d}: {}.  "
                    "This may have been caused by smearing of occupation numbers "
                    "in the mean-field calculation. If so, consider executing "
                    "mf.smearing_method = False; mf.mo_occ = mf.get_occ() prior "
                    "to calling this".format(i, moocc))
    if mp._nocc is not None:
        return mp._nocc

    elif mp.frozen is None:
        nocc = [[
            np.count_nonzero(mp.mo_occ[0][k] > 0) for k in range(mp.nkpts)
        ], [np.count_nonzero(mp.mo_occ[1][k] > 0) for k in range(mp.nkpts)]]

    elif isinstance(mp.frozen, (int, np.integer)):
        nocc = [0] * 2
        for spin in [0, 1]:
            nocc[spin] = [
                (np.count_nonzero(mp.mo_occ[spin][k] > 0) - mp.frozen)
                for k in range(mp.nkpts)
            ]

    elif (_is_arraylike(mp.frozen[0]) and
          isinstance(mp.frozen[0][0],
                     (int, np.integer))):  # case example: ([0, 4], [0, 5, 6])
        nocc = [0] * 2
        assert (len(mp.frozen) == 2)
        for spin in [0, 1]:
            [
                _frozen_sanity_check(mp.frozen[spin], mp.mo_occ[spin][ikpt],
                                     ikpt) for ikpt in range(mp.nkpts)
            ]
            nocc_spin = []
            for ikpt in range(mp.nkpts):
                max_occ_idx = np.max(np.where(mp.mo_occ[spin][ikpt] > 0))
                frozen_nocc = np.sum(np.array(mp.frozen[spin]) <= max_occ_idx)
                nocc_spin.append(
                    np.count_nonzero(mp.mo_occ[spin][ikpt]) - frozen_nocc)
            nocc[spin] = nocc_spin

    elif (_is_arraylike(mp.frozen[0]) and isinstance(
            mp.frozen[0][0],
        (list, np.ndarray))):  # case example: ([[0,],[]], [[0,1],[4]])
        assert (len(mp.frozen) == 2)
        for spin in [0, 1]:
            nkpts = len(mp.frozen[spin])
            if nkpts != mp.nkpts:
                raise RuntimeError(
                    'Frozen list has a different number of k-points (length) than passed in'
                    'mean-field/correlated calculation.  \n\nCalculation nkpts = %d, frozen'
                    'list = %s (length = %d)' % (mp.nkpts, mp.frozen, nkpts))
        nocc = [0] * 2
        for spin in [0, 1]:
            [
                _frozen_sanity_check(frozen, mo_occ, ikpt) for ikpt, frozen,
                mo_occ in zip(range(nkpts), mp.frozen[spin], mp.mo_occ[spin])
            ]
            nocc_spin = []
            for ikpt, frozen in enumerate(mp.frozen[spin]):
                max_occ_idx = np.max(np.where(mp.mo_occ[spin][ikpt] > 0))
                frozen_nocc = np.sum(np.array(frozen) <= max_occ_idx)
                nocc_spin.append(
                    np.count_nonzero(mp.mo_occ[spin][ikpt]) - frozen_nocc)
            nocc[spin] = nocc_spin
    else:
        raise NotImplementedError('No known conversion for frozen %s' %
                                  mp.frozen)

    for spin in [0, 1]:
        assert any(np.array(nocc[spin]) > 0), (
            'Must have occupied orbitals (spin=%d)! \n\nnocc %s\nfrozen %s\nmo_occ %s'
            % (spin, nocc, mp.frozen, mp.mo_occ))

    nocca, noccb = nocc
    if not per_kpoint:
        nocca = np.amax(nocca)
        noccb = np.amax(noccb)

    return nocca, noccb