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)
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
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()
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