Exemple #1
0
def make_state_info_from_fcidump(fcidump, options):
    nel = fcidump['nelec']
    if not options.is_none("NEL"):
        nel = options.get_int("NEL")

    multiplicity = fcidump['ms2'] + 1
    if not options.is_none("MULTIPLICITY"):
        multiplicity = options.get_int("MULTIPLICITY")

    # If the user did not specify ms determine the value from the input or
    # take the lowest value consistent with the value of "MULTIPLICITY"
    # For example:
    #    singlet: multiplicity = 1 -> twice_ms = 0 (ms = 0)
    #    doublet: multiplicity = 2 -> twice_ms = 1 (ms = 1/2)
    #    triplet: multiplicity = 3 -> twice_ms = 0 (ms = 0)
    twice_ms = (multiplicity + 1) % 2
    if not options.is_none("MS"):
        twice_ms = int(round(2.0 * options.get_double("MS")))

    if (((nel - twice_ms) % 2) != 0):
        raise Exception(
            f'Forte: the value of MS ({twice_ms}/2) is incompatible with the number of electrons ({nel})'
        )

    na = (nel + twice_ms) // 2
    nb = nel - na

    irrep = fcidump['isym']
    if not options.is_none("ROOT_SYM"):
        irrep = options.get_int("ROOT_SYM")

    return forte.StateInfo(na, nb, multiplicity, twice_ms, irrep)
Exemple #2
0
    def reorder_weights(self, state_ci_wfn_map):
        """
        Check CI overlap and reorder weights between consecutive relaxation steps.
        :param state_ci_wfn_map: the map to be compared to self.state_ci_wfn_map
        """
        # bypass this check if state to CI vectors map not available
        if self.state_ci_wfn_map is None:
            return

        for state in self.states:
            twice_ms = state.twice_ms()
            if twice_ms < 0:
                continue

            # compute overlap between two sets of CI vectors <this|prior>
            overlap = psi4.core.doublet(state_ci_wfn_map[state], self.state_ci_wfn_map[state], True, False)
            overlap.name = f"CI Overlap of {state}"

            # check overlap and determine if we need to permute states
            overlap_np = np.abs(overlap.to_array())
            max_values = np.max(overlap_np, axis=1)
            permutation = np.argmax(overlap_np, axis=1)
            check_pass = len(permutation) == len(set(permutation)) and np.all(max_values > 0.5)

            if not check_pass:
                msg = "Relaxed states are likely wrong. Please increase the number of roots."
                warnings.warn(f"{msg}", UserWarning)
                psi4.core.print_out(f"\n\n  Forte Warning: {msg}")
                psi4.core.print_out(f"\n\n  ==> Overlap of CI Vectors <this|prior> <==\n\n")
                overlap.print_out()
            else:
                if list(permutation) == list(range(len(permutation))):
                    continue

                msg = "Weights will be permuted to ensure consistency before and after relaxation."
                psi4.core.print_out(f"\n\n  Forte Warning: {msg}\n")

                weights_old = self.state_weights_map[state]
                weights_new = [weights_old[i] for i in permutation]
                self.state_weights_map[state] = weights_new

                psi4.core.print_out(f"\n  ==> Weights for {state} <==\n")
                psi4.core.print_out(f"\n    Root    Old       New")
                psi4.core.print_out(f"\n    {'-' * 24}")
                for i, w_old in enumerate(weights_old):
                    w_new = weights_new[i]
                    psi4.core.print_out(f"\n    {i:4d} {w_old:9.3e} {w_new:9.3e}")
                psi4.core.print_out(f"\n    {'-' * 24}\n")

                # try to fix ms < 0
                if twice_ms > 0:
                    state_spin = forte.StateInfo(state.nb(), state.na(),
                                                 state.multiplicity(), -twice_ms,
                                                 state.irrep(), state.irrep_label(),
                                                 state.gas_min(), state.gas_max())
                    if state_spin in self.state_weights_map:
                        self.state_weights_map[state_spin] = weights_new
Exemple #3
0
def test_aci1():
    import math
    import psi4
    import forte
    from forte import forte_options

    ref_aci = -75.010199198896
    rel_tol = 1e-9
    abs_tol = 1e-8

    h2o = psi4.geometry("""
     O
     H 1 0.96
     H 1 0.96 2 104.5
    """)

    psi4.set_options({'basis': "sto-3g"})
    E_scf, wfn = psi4.energy('scf', return_wfn=True)
    state = forte.StateInfo(na=5, nb=5, multiplicity=1, twice_ms=0, irrep=0)
    dim = psi4.core.Dimension([4, 0, 1, 2])

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

    forte.startup()
    forte.banner()
    mo_space_info = forte.make_mo_space_info(wfn, forte_options)
    ints = forte.make_forte_integrals(wfn, options, mo_space_info)

    scf_info = forte.SCFInfo(wfn)

    solver = forte.make_active_space_solver('ACI', state, scf_info,
                                            mo_space_info, ints, forte_options)
    energy = solver.compute_energy()

    assert math.isclose(energy, ref_aci, abs_tol=abs_tol, rel_tol=rel_tol)

    print("\n\nACI Energy = {}".format(energy))
    forte.cleanup()
Exemple #4
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