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' ]
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)
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
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)
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