Exemple #1
0
def test_mospaceinfo():
    """Test the MOSpaceInfo python API"""
    import psi4
    import forte
    from forte import forte_options

    print("Testing the MOSpaceInfo python API")

    geom = "H 0.0 0.0 0.0\nH 0.0 0.0 1.0" ""

    psi4.core.clean()

    mol = psi4.geometry(geom)

    # set basis/options
    psi4.set_options({'basis': 'cc-pVDZ', 'scf_type': 'pk'})

    # pipe output to the file output.dat
    psi4.core.set_output_file('output.dat', False)

    # run scf and return the energy and a wavefunction object (will work only if pass return_wfn=True)
    E_scf, wfn = psi4.energy('scf', return_wfn=True)

    options = psi4.core.get_options()  # options = psi4 option object
    options.set_current_module('FORTE')  # read options labeled 'FORTE'
    forte_options.get_options_from_psi4(options)

    # Setup forte and prepare the active space integral class
    mos_spaces = {
        'FROZEN_DOCC': [1, 0, 0, 0, 0, 0, 0, 0],
        'RESTRICTED_DOCC': [0, 0, 0, 0, 0, 1, 0, 0],
        'FROZEN_UOCC': [1, 0, 0, 0, 0, 0, 0, 0]
    }
    mo_space_info = forte.make_mo_space_info_from_map(wfn, mos_spaces, [])

    assert mo_space_info.nirrep() == 8

    assert mo_space_info.size('FROZEN_DOCC') == 1
    assert mo_space_info.size('RESTRICTED_DOCC') == 1
    assert mo_space_info.size('ACTIVE') == 7
    assert mo_space_info.size('RESTRICTED_UOCC') == 0
    assert mo_space_info.size('FROZEN_UOCC') == 1

    assert mo_space_info.dimension('FROZEN_DOCC').to_tuple() == (1, 0, 0, 0, 0,
                                                                 0, 0, 0)
    assert mo_space_info.dimension('RESTRICTED_DOCC').to_tuple() == (0, 0, 0,
                                                                     0, 0, 1,
                                                                     0, 0)
    assert mo_space_info.dimension('ACTIVE').to_tuple() == (1, 0, 1, 1, 0, 2,
                                                            1, 1)
    assert mo_space_info.dimension('RESTRICTED_UOCC').to_tuple() == (0, 0, 0,
                                                                     0, 0, 0,
                                                                     0, 0)
    assert mo_space_info.dimension('FROZEN_UOCC').to_tuple() == (1, 0, 0, 0, 0,
                                                                 0, 0, 0)

    assert mo_space_info.space_names() == [
        'FROZEN_DOCC', 'RESTRICTED_DOCC', 'ACTIVE', 'RESTRICTED_UOCC',
        'FROZEN_UOCC'
    ]
Exemple #2
0
    def make_mo_space_info(self, mo_spaces):
        """
        Make a MOSpaceInfo object from a dictionary

        Parameters
        ----------
        mo_spaces: dict(str -> list(int))
            A dictionary of orbital space labels to a list of number of orbitals per irrep

        Return
        ------
            A MOSpaceInfo object
        """
        nmopi = self.data.scf_info.nmopi()
        point_group = self.model.point_group
        reorder = []  # TODO: enable reorder
        self.data.mo_space_info = forte.make_mo_space_info_from_map(nmopi, point_group, mo_spaces, reorder)
Exemple #3
0
def test_mospaceinfo2():
    """Test the MOSpaceInfo python API"""
    import psi4
    import forte
    from forte import forte_options

    print("Testing the MOSpaceInfo python API")

    # *
    # * Irrep                 A1(0)       A2(1)    B1(2)   B2(3)
    # *
    # * Indexing:
    # * ALL              | 0 1 2 3 4 | 5 6 7 8 9 | 10 11 | 12 13 | <- absolute index in the full orbital space
    # * CORRELATED       | - 0 1 2 3 | - 4 5 6 7 |  8  - |  9 10 | <- absolute index in the space of non-frozen orbitals
    # * RELATIVE         | 0 1 2 3 4 | 0 1 2 3 4 |  0  1 |  0  1 | <- index relative to the irrep in the full orbital space
    # *
    # * FROZEN_DOCC        *           *
    # * RESTRICTED_DOCC      *           * *        *       *
    # * GAS1                   *             *
    # * GAS2                     *
    # * RESTRICED_UOCC             *           *               *
    # * FROZEN_UOCC                                    *

    # Setup forte and prepare the active space integral class
    mos_spaces = {
        'FROZEN_DOCC': [1, 1, 0, 0],
        'RESTRICTED_DOCC': [1, 2, 1, 1],
        'GAS1': [1, 1, 0, 0],
        'GAS2': [1, 0, 0, 0],
        'RESTRICTED_UOCC': [1, 1, 0, 1],
    }

    nmopi = psi4.core.Dimension([5, 5, 2, 2])
    point_group = 'C2V'

    mo_space_info = forte.make_mo_space_info_from_map(nmopi, point_group,
                                                      mos_spaces, [])

    space_names = [
        'FROZEN_DOCC', 'RESTRICTED_DOCC', 'GAS1', 'GAS2', 'GAS3', 'GAS4',
        'GAS5', 'GAS6', 'RESTRICTED_UOCC', 'FROZEN_UOCC'
    ]

    assert mo_space_info.nirrep() == 4

    assert mo_space_info.space_names() == space_names

    ref_spaces = [
        'FROZEN_DOCC', 'RESTRICTED_DOCC', 'GAS1', 'GAS2', 'GAS3', 'GAS4',
        'GAS5', 'GAS6', 'RESTRICTED_UOCC', 'FROZEN_UOCC', 'ACTIVE'
    ]

    ref_size = [2, 5, 2, 1, 0, 0, 0, 0, 3, 1, 3]
    for name, val in zip(ref_spaces, ref_size):
        assert mo_space_info.size(name) == val

    ref_dimension = [(1, 1, 0, 0), (1, 2, 1, 1), (1, 1, 0, 0), (1, 0, 0, 0),
                     (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0),
                     (1, 1, 0, 1), (0, 0, 1, 0), (2, 1, 0, 0)]
    for name, val in zip(ref_spaces, ref_dimension):
        assert mo_space_info.dimension(name).to_tuple() == val

    ref_absolute_mo = [[0, 5], [1, 6, 7, 10, 12], [2, 8], [3], [], [], [], [],
                       [4, 9, 13], [11], [2, 3, 8]]
    for name, val in zip(ref_spaces, ref_absolute_mo):
        assert mo_space_info.absolute_mo(name) == val

    ref_corr_absolute_mo = [[1000000000, 1000000000], [0, 4, 5, 8, 9], [1, 6],
                            [2], [], [], [], [], [3, 7, 10], [1000000000],
                            [1, 2, 6]]
    for name, val in zip(ref_spaces, ref_corr_absolute_mo):
        assert mo_space_info.corr_absolute_mo(name) == val

    ref_relative_mo = [[(0, 0), (1, 0)],
                       [(0, 1), (1, 1), (1, 2), (2, 0), (3, 0)],
                       [(0, 2), (1, 3)], [(0, 3)], [], [], [], [],
                       [(0, 4), (1, 4), (3, 1)], [(2, 1)],
                       [(0, 2), (0, 3), (1, 3)]]
    for name, val in zip(ref_spaces, ref_relative_mo):
        assert mo_space_info.relative_mo(name) == val

    assert mo_space_info.pos_in_space('GAS1', 'ACTIVE') == [0, 2]
    assert mo_space_info.pos_in_space('GAS2', 'ACTIVE') == [1]
    assert mo_space_info.pos_in_space('ACTIVE', 'ACTIVE') == [0, 1, 2]
    assert mo_space_info.pos_in_space('ACTIVE', 'ALL') == [2, 3, 8]

    for name, val in zip(ref_spaces, ref_absolute_mo):
        assert mo_space_info.pos_in_space(name, 'ALL') == val

    ref_spaces_non_frozen = [
        'RESTRICTED_DOCC', 'GAS1', 'GAS2', 'GAS3', 'GAS4', 'GAS5', 'GAS6',
        'RESTRICTED_UOCC', 'ACTIVE'
    ]
    ref_corr_absolute_mo_non_frozen = [[0, 4, 5, 8, 9], [1, 6], [2], [], [],
                                       [], [], [3, 7, 10], [1, 2, 6]]

    for name, val in zip(ref_spaces_non_frozen,
                         ref_corr_absolute_mo_non_frozen):
        assert mo_space_info.pos_in_space(name, 'CORRELATED') == val
Exemple #4
0
def prepare_forte_objects(wfn,
                          mo_spaces=None,
                          active_space='ACTIVE',
                          core_spaces=['RESTRICTED_DOCC'],
                          localize=False,
                          localize_spaces=[]):
    """Take a psi4 wavefunction object and prepare the ForteIntegrals, SCFInfo, and MOSpaceInfo objects

    Parameters
    ----------
    wfn : psi4 Wavefunction
        A psi4 Wavefunction object
    mo_spaces : dict
        A dictionary with the size of each space (e.g., {'ACTIVE' : [3]})
    active_space : str
        The MO space treated as active (default: 'ACTIVE')
    core_spaces : list(str)
        The MO spaces treated as active (default: ['RESTRICTED_DOCC'])
    localize : bool
        Do localize the orbitals? (defaul: False)
    localize_spaces : list(str)
        A list of spaces to localize (default: [])
    Returns
    -------
    tuple(ForteIntegrals, ActiveSpaceIntegrals, SCFInfo, MOSpaceInfo, map(StateInfo : list)
        a tuple containing the ForteIntegrals, SCFInfo, and MOSpaceInfo objects and a map of states and weights
    """
    # fill in the options object
    psi4_options = psi4.core.get_options()
    psi4_options.set_current_module('FORTE')
    options = forte.forte_options
    options.get_options_from_psi4(psi4_options)

    if ('DF' in options.get_str('INT_TYPE')):
        aux_basis = psi4.core.BasisSet.build(
            wfn.molecule(), 'DF_BASIS_MP2',
            psi4.core.get_global_option('DF_BASIS_MP2'), 'RIFIT',
            psi4.core.get_global_option('BASIS'))
        wfn.set_basisset('DF_BASIS_MP2', aux_basis)

    if (options.get_str('MINAO_BASIS')):
        minao_basis = psi4.core.BasisSet.build(
            wfn.molecule(), 'MINAO_BASIS', psi4_options.get_str('MINAO_BASIS'))
        wfn.set_basisset('MINAO_BASIS', minao_basis)

    # Prepare base objects
    scf_info = forte.SCFInfo(wfn)

    nmopi = wfn.nmopi()
    point_group = wfn.molecule().point_group().symbol()

    if mo_spaces == None:
        mo_space_info = forte.make_mo_space_info(nmopi, point_group, options)
    else:
        mo_space_info = forte.make_mo_space_info_from_map(
            nmopi, point_group, mo_spaces, [])

    state_weights_map = forte.make_state_weights_map(options, mo_space_info)

    ints = forte.make_ints_from_psi4(wfn, options, mo_space_info)

    if localize:
        localizer = forte.Localize(forte.forte_options, ints, mo_space_info)
        localizer.set_orbital_space(localize_spaces)
        localizer.compute_transformation()
        Ua = localizer.get_Ua()
        ints.rotate_orbitals(Ua, Ua)

    # the space that defines the active orbitals. We select only the 'ACTIVE' part
    # the space(s) with non-active doubly occupied orbitals

    as_ints = forte.make_active_space_ints(mo_space_info, ints, active_space,
                                           core_spaces)

    return (ints, as_ints, scf_info, mo_space_info, state_weights_map)
Exemple #5
0
def run_sci(ints, scf_info, wfn, selector):

    mo_space_map = {
        'RESTRICTED_DOCC': selector.restricted_docc,
        'ACTIVE': selector.active,
        'RESTRICTED_UOCC': selector.restricted_uocc
    }
    mo_reordering = selector.mo_reorder

    #     print(mo_space_map)
    #     print(mo_reordering)

    mo_space_info = forte.make_mo_space_info_from_map(wfn,
                                                      mo_space_map,
                                                      reorder=mo_reordering)

    #     print(mo_space_info.get_corr_abs_mo('ACTIVE'))
    #     print(mo_space_info.get_corr_abs_mo('RESTRICTED_DOCC'))
    #     print(mo_space_info.get_corr_abs_mo('RESTRICTED_UOCC'))

    nact = 0
    for n in mo_space_map['ACTIVE']:
        nact += n

    nactv = sum(mo_space_map['ACTIVE'])
    nrdocc = sum(mo_space_map['RESTRICTED_DOCC'])

    #    options = psi4.core.get_options()
    #    options.set_current_module('FORTE')
    #    forte.forte_options.update_psi_options(options)

    options = forte.forte_options
    options.set_str('ACTIVE_REF_TYPE', 'CISD')
    options.set_int('SCI_MAX_CYCLE', 3)
    options.set_str('SCI_EXCITED_ALGORITHM', 'AVERAGE')
    options.set_str('INT_TYPE', 'CHOLESKY')
    options.set_int('ASCI_CDET', 50)
    options.set_int('ASCI_TDET', 200)

    as_ints = forte.make_active_space_ints(mo_space_info, ints, "ACTIVE",
                                           ["RESTRICTED_DOCC"])

    na = wfn.nalpha()
    nb = wfn.nbeta()
    npair = (na + nb) // 2
    nunpair = na + nb - 2 * npair
    na = npair + nunpair
    na = npair

    state_vec = []
    state_map = {}
    lowest_twice_ms = abs(na - nb)
    for k in range(2):
        na_act = na - nrdocc + k
        nb_act = nb - nrdocc - k
        #         print("k = ", k)
        #         print("na_act = ", na_act)
        #         print("nb_act = ", nb_act)
        #         print("binom({},{}) = {}".format(na_act,nactv,scipy.special.binom(nactv,na_act)))
        #         print("binom({},{}) = {}".format(nb_act,nactv,scipy.special.binom(nactv,nb_act)))
        num_dets = min(
            3,
            int(
                scipy.special.binom(nactv, na_act) *
                scipy.special.binom(nactv, nb_act)))
        #         print(k, num_dets)
        twice_ms = na - nb + 2 * k
        multiplicity = twice_ms + 1
        state = forte.StateInfo(na=na + k,
                                nb=nb - k,
                                multiplicity=multiplicity,
                                twice_ms=twice_ms,
                                irrep=0)
        #         state_vec.append((,num_dets))
        if num_dets > 0:
            state_map[state] = num_dets


#     state_1 = forte.StateInfo(na=na+1,nb=nb-1,multiplicity=3,twice_ms=1,irrep=0)
#     num_states = 3
#     if nact <= 2:
#         num_states = 1
#     state_map = {state_vec[0][0] : state_vec[0][1], state_vec[1][0] : state_vec[1][1]} #, state_1 : num_states}

    as_solver = forte.make_active_space_solver('ASCI', state_map, scf_info,
                                               mo_space_info, as_ints,
                                               forte.forte_options)
    en = as_solver.compute_energy()

    energies = []
    occs = []
    for key, val in en.items():
        for n, energy in enumerate(val):
            ref = as_solver.rdms({(key, key): [(n, n)]}, 1)
            #            ordm = forte.get_rdm_data(ref[0], 1) # TODO-PR reintroduce
            #            occs.append(get_occ(ordm, nact)) # TODO-PR reintroduce
            occs.append(0.0)
            label = "{}-{}".format(n + 1, key.multiplicity_label())
            energies.append((en[key][n], label, key.multiplicity()))

    return energies, occs