def test_input_multistate(): """Test input for a multi-state computation using the `AVG_STATE` keyword.""" psi4.geometry(""" Li H 1 3.0 units bohr """) ref_energies = { '1A1': [-8.008550659909, -7.890309067618, -7.776162395969], '1A2': [-7.396156201690, -7.321587400358, -7.262899599968], '1B1': [-7.853436217153, -7.749808606728, -7.382069881110], '1B2': [-7.853436217170, -7.749808606704, -7.382069881071], } # need to clean the options otherwise this job will interfere forte.clean_options() psi4.set_options({'basis': 'DZ', 'scf_type': 'pk', 'e_convergence': 12}) psi4.set_module_options( 'FORTE', { 'active_space_solver': 'fci', 'active': [8, 0, 2, 2], 'restricted_docc': [0, 0, 0, 0], 'avg_state': [[0, 1, 3], [1, 1, 3], [2, 1, 3], [3, 1, 3]], 'ms': 0.0 }) efci = psi4.energy('forte') for k, vals in ref_energies.items(): for i in range(3): assert psi4.core.variable(f'ENERGY ROOT {i} {k}') == pytest.approx( vals[i], 1.0e-9)
def test_options(): import math import forte from forte import forte_options forte.clean_options() # read an option via the ForteOption class interface test1 = forte_options.get_double('E_CONVERGENCE') # get the py::dict object in the ForteOption object d = forte_options.dict() # grab one variable e_conv = d['E_CONVERGENCE'] # read option type and value assert test1 == 1e-09 assert e_conv['type'] == 'float' assert e_conv['value'] == 1e-09 # compare the value to the one obtained via the class interface assert e_conv['value'] == test1 # write options via the python dictionary and test propagation to the ForteOption object e_conv['value'] = 1e-05 test2 = forte_options.get_double('E_CONVERGENCE') assert e_conv['value'] == 1e-05 assert test2 == 1e-05
def test_input_simple(): """Test input for a simple computation using the `ROOT_SYM` keyword.""" import math import psi4 import forte import pytest psi4.geometry(""" Li H 1 3.0 units bohr """) ref_efci_0 = -8.008550659909 ref_efci_1 = -7.396156201698 ref_efci_2 = -7.853436217184 ref_efci_3 = -7.853436217157 # need to clean the options otherwise this job will interfere forte.clean_options() psi4.set_options({'basis': 'DZ', 'scf_type': 'pk', 'e_convergence': 12}) psi4.set_module_options( 'FORTE', { 'active_space_solver': 'fci', 'active': [8, 0, 2, 2], 'restricted_docc': [0, 0, 0, 0], 'root_sym': 0, 'multiplicity' : 1, 'ms': 0.0 } ) psi4.core.set_output_file('debug.txt',False) efci = psi4.energy('forte') print('Test 1') assert efci == pytest.approx(ref_efci_0, 1.0e-9) print('Test 2') psi4.set_module_options('FORTE', { 'root_sym': 1, }) efci = psi4.energy('forte') assert efci == pytest.approx(ref_efci_1, 1.0e-9) psi4.set_module_options('FORTE', { 'root_sym': 2, }) efci = psi4.energy('forte') assert efci == pytest.approx(ref_efci_2, 1.0e-9) psi4.set_module_options('FORTE', { 'root_sym': 3, }) efci = psi4.energy('forte') assert efci == pytest.approx(ref_efci_3, 1.0e-9)
def test_input_example_1(): """Run a FCI computation on methylene using ROHF orbitals optimized for the 3B1 state. Computes the lowest 3B1 state and the lowest two 1A1 states.""" ref_e_3b1 = -38.924726774489 ref_e_1a1 = -38.866616413802 ref_e_1a1_ex = -38.800424868719 psi4.geometry(""" 0 3 C H 1 1.085 H 1 1.085 2 135.5 """) forte.clean_options() psi4.set_options({ 'basis': 'DZ', 'scf_type': 'pk', 'e_convergence': 12, 'reference': 'rohf', 'forte__active_space_solver': 'fci', 'forte__restricted_docc': [1, 0, 0, 0], 'forte__active': [3, 0, 2, 2], 'forte__multiplicity': 3, 'forte__root_sym': 2, }) efci = psi4.energy('forte') assert efci == pytest.approx(ref_e_3b1, 1.0e-9) psi4.set_options({ 'forte__active_space_solver': 'fci', 'forte__restricted_docc': [1, 0, 0, 0], 'forte__active': [3, 0, 2, 2], 'forte__multiplicity': 1, 'forte__root_sym': 0, 'forte__nroot': 2 }) efci = psi4.energy('forte') assert efci == pytest.approx(ref_e_1a1, 1.0e-9) psi4.set_options({ 'forte__active_space_solver': 'fci', 'forte__restricted_docc': [1, 0, 0, 0], 'forte__active': [3, 0, 2, 2], 'forte__multiplicity': 1, 'forte__root_sym': 0, 'forte__nroot': 2, 'forte__root': 1 }) efci = psi4.energy('forte') assert efci == pytest.approx(ref_e_1a1_ex, 1.0e-9)
def test_sparse_ci2(): import math import psi4 import forte import itertools import numpy as np import pytest from forte import forte_options ref_fci = -5.623851783330647 psi4.core.clean() # need to clean the options otherwise this job will interfere forte.clean_options() h2o = psi4.geometry(""" He He 1 1.0 """) psi4.set_options({'basis': 'cc-pVDZ'}) _, wfn = psi4.energy('scf', return_wfn=True) na = wfn.nalpha() nb = wfn.nbeta() nirrep = wfn.nirrep() wfn_symmetry = 0 forte.startup() forte.banner() psi4_options = psi4.core.get_options() psi4_options.set_current_module('FORTE') forte_options.get_options_from_psi4(psi4_options) # Setup forte and prepare the active space integral class nmopi = wfn.nmopi() point_group = wfn.molecule().point_group().symbol() mo_space_info = forte.make_mo_space_info(nmopi, point_group, forte_options) ints = forte.make_ints_from_psi4(wfn, forte_options, mo_space_info) as_ints = forte.make_active_space_ints(mo_space_info, ints, 'ACTIVE', ['RESTRICTED_DOCC']) print('\n\n => Sparse FCI Test <=') print(' Number of irreps: {}'.format(nirrep)) nmo = wfn.nmo() nmopi = [wfn.nmopi()[h] for h in range(nirrep)] nmopi_str = [str(wfn.nmopi()[h]) for h in range(nirrep)] mo_sym = [] for h in range(nirrep): for i in range(nmopi[h]): mo_sym.append(h) print(' Number of orbitals per irreps: [{}]'.format(','.join(nmopi_str))) print(' Symmetry of the MOs: ', mo_sym) hf_reference = forte.Determinant() hf_reference.create_alfa_bit(0) hf_reference.create_beta_bit(0) print(' Hartree-Fock determinant: {}'.format(hf_reference.str(10))) # Compute the HF energy hf_energy = as_ints.nuclear_repulsion_energy() + as_ints.slater_rules(hf_reference, hf_reference) print(' Nuclear repulsion energy: {}'.format(as_ints.nuclear_repulsion_energy())) print(' Reference energy: {}'.format(hf_energy)) # Build a list of determinants orblist = [i for i in range(nmo)] dets = [] for astr in itertools.combinations(orblist, na): for bstr in itertools.combinations(orblist, nb): sym = 0 d = forte.Determinant() for a in astr: d.create_alfa_bit(a) sym = sym ^ mo_sym[a] for b in bstr: d.create_beta_bit(b) sym = sym ^ mo_sym[b] if (sym == wfn_symmetry): dets.append(d) print(' Determinant {} has symmetry {}'.format(d.str(nmo), sym)) print(f'\n Size of the derminant basis: {len(dets)}') energy, evals, evecs, spin = forte.diag(dets, as_ints, 1, 1, "FULL") print(energy) efci = energy[0] + as_ints.nuclear_repulsion_energy() print('\n FCI Energy: {}\n'.format(efci)) assert efci == pytest.approx(ref_fci, abs=1e-9) # Clean up forte (necessary) forte.cleanup()
def test_options(): forte.clean_options() # read an option via the ForteOption class interface test1 = forte_options.get_double('E_CONVERGENCE') # get the py::dict object in the ForteOption object d = forte_options.dict() # grab one variable e_conv = d['E_CONVERGENCE'] # read option type and value assert test1 == 1e-09 assert e_conv['type'] == 'float' assert e_conv['value'] == 1e-09 # compare the value to the one obtained via the class interface assert e_conv['value'] == test1 # write options via the python dictionary and test propagation to the ForteOption object e_conv['value'] = 1e-05 test2 = forte_options.get_double('E_CONVERGENCE') assert e_conv['value'] == 1e-05 assert test2 == 1e-05 forte_options.add_bool('MY_BOOL', False, 'A boolean') forte_options.add_int('MY_INT', 0, 'An integer') forte_options.add_double('MY_FLOAT', 0, 'A float') forte_options.add_str('MY_STR', 0, 'A string') forte_options.add_int_list('MY_INT_LIST', 'A list of integers') forte_options.add_double_list('MY_FLOAT_LIST', 'A list of floating point numbers') forte_options.add_list('MY_GEN_LIST', 'A general list') # test setting an option from a dictionary forte_options.set_from_dict( { 'MY_BOOL': True, 'MY_INT': 2, 'MY_FLOAT': 1.0e-12, 'MY_STR': 'NEW STRING', # this also tests conversion of string options to upper case 'MY_INT_LIST': [1, 1, 2, 3, 5, 8], 'MY_FLOAT_LIST': [1.0, 2.0, 3.0], 'MY_GEN_LIST': ['singlet', 'triplet', 42] } ) assert forte_options.get_bool('MY_BOOL') assert forte_options.get_int('MY_INT') == 2 assert forte_options.get_double('MY_FLOAT') == 1.0e-12 assert forte_options.get_str('MY_STR') == 'NEW STRING' assert forte_options.get_int_list('MY_INT_LIST') == [1, 1, 2, 3, 5, 8] assert forte_options.get_double_list('MY_FLOAT_LIST') == [1.0, 2.0, 3.0] assert forte_options.get_list('MY_GEN_LIST') == ['singlet', 'triplet', 42] forte_options.set_from_dict({'E_CONVERGENCE': 1.0e-12}) assert forte_options.get_double('E_CONVERGENCE') == 1.0e-12 # test setting an option with the wrong label with pytest.raises(RuntimeError): forte_options.set_from_dict({'E_CONVERGENCEE': 1.0e-12}) # test setting an option with the wrong type (here list instead of float) with pytest.raises(RuntimeError): forte_options.set_from_dict({'E_CONVERGENCE': [1.0]}) # create a new ForteOptions object new_options = forte.ForteOptions() # call set_dict to copy the dictionary from another ForteOptions # this does a deepcopy new_options.set_dict(forte_options.dict()) # verify that the option value was copied assert new_options.get_double('E_CONVERGENCE') == 1.0e-12 # verify that changing an option in one object does not affect the other new_options.set_double('E_CONVERGENCE', 1.0e-2) assert forte_options.get_double('E_CONVERGENCE') == 1.0e-12 assert new_options.get_double('E_CONVERGENCE') == 1.0e-2 # now reset new_options, define new options, and print them to test str() new_options = ForteOptions() new_options.add_bool('MY_BOOL', False, 'A boolean') new_options.add_int('MY_INT', 0, 'An integer') new_options.add_double('MY_FLOAT', 0, 'A float') new_options.add_str('MY_STR', 0, 'A string') new_options.add_int_list('MY_INT_LIST', 'A list of integers') new_options.add_double_list('MY_FLOAT_LIST', 'A list of floating point numbers') new_options.add_list('MY_GEN_LIST', 'A general list') new_options.add_int('MY_NONE', None, 'An integer') new_options.set_str('MY_STR', 'NEW STRING') new_options.set_from_dict( { 'MY_BOOL': True, 'MY_INT': 2, 'MY_FLOAT': 1.0e-12, 'MY_STR': 'NEW STRING', 'MY_INT_LIST': [1, 1, 2, 3, 5, 8], 'MY_FLOAT_LIST': [1.0, 2.0, 3.0], 'MY_GEN_LIST': ['singlet', 'triplet', 42] } ) test_str = """MY_BOOL: 1 MY_INT: 2 MY_FLOAT: 0.000000 MY_STR: NEW STRING MY_INT_LIST: [1,1,2,3,5,8,] MY_FLOAT_LIST: [1.000000,2.000000,3.000000,] MY_GEN_LIST: gen_list() MY_NONE: None """ assert str(new_options) == test_str # test catching impossible type conversions with pytest.raises(RuntimeError): new_options.set_int_list('MY_FLOAT', [1, 2, 3]) with pytest.raises(RuntimeError): new_options.set_double_list('MY_FLOAT', [1, 2, 3]) with pytest.raises(RuntimeError): new_options.set_list('MY_FLOAT', [1, 2, 3])
def test_sparse_ci(): import math import psi4 import forte import itertools import numpy as np import pytest from forte import forte_options ref_fci = -1.101150330132956 psi4.core.clean() # need to clean the options otherwise this job will interfere forte.clean_options() psi4.geometry(""" H H 1 1.0 """) psi4.set_options({'basis': 'sto-3g'}) E_scf, wfn = psi4.energy('scf', return_wfn=True) na = wfn.nalpha() nb = wfn.nbeta() nirrep = wfn.nirrep() wfn_symmetry = 0 psi4_options = psi4.core.get_options() psi4_options.set_current_module('FORTE') forte_options.get_options_from_psi4(psi4_options) # Setup forte and prepare the active space integral class nmopi = wfn.nmopi() point_group = wfn.molecule().point_group().symbol() mo_space_info = forte.make_mo_space_info(nmopi, point_group, forte_options) ints = forte.make_ints_from_psi4(wfn, forte_options, mo_space_info) as_ints = forte.make_active_space_ints(mo_space_info, ints, 'ACTIVE', ['RESTRICTED_DOCC']) as_ints.print() print('\n\n => Sparse FCI Test <=') print(' Number of irreps: {}'.format(nirrep)) nmo = wfn.nmo() nmopi = [wfn.nmopi()[h] for h in range(nirrep)] nmopi_str = [str(wfn.nmopi()[h]) for h in range(nirrep)] mo_sym = [] for h in range(nirrep): for i in range(nmopi[h]): mo_sym.append(h) print(' Number of orbitals per irreps: [{}]'.format(','.join(nmopi_str))) print(' Symmetry of the MOs: ', mo_sym) hf_reference = forte.Determinant() hf_reference.create_alfa_bit(0) hf_reference.create_beta_bit(0) print(' Hartree-Fock determinant: {}'.format(hf_reference.str(2))) # Compute the HF energy hf_energy = as_ints.nuclear_repulsion_energy() + as_ints.slater_rules(hf_reference, hf_reference) print(' Nuclear repulsion energy: {}'.format(as_ints.nuclear_repulsion_energy())) print(' Reference energy: {}'.format(hf_energy)) # Build a list of determinants orblist = [i for i in range(nmo)] dets = [] for astr in itertools.combinations(orblist, na): for bstr in itertools.combinations(orblist, nb): sym = 0 d = forte.Determinant() for a in astr: d.create_alfa_bit(a) sym = sym ^ mo_sym[a] for b in bstr: d.create_beta_bit(b) sym = sym ^ mo_sym[b] if (sym == wfn_symmetry): dets.append(d) print(' Determinant {} has symmetry {}'.format(d.str(nmo), sym)) # Build the Hamiltonian matrix using 'slater_rules' nfci = len(dets) H = np.ndarray((nfci, nfci)) for I in range(nfci): # off-diagonal terms for J in range(I + 1, nfci): HIJ = as_ints.slater_rules(dets[I], dets[J]) H[I][J] = H[J][I] = HIJ # diagonal term H[I][I] = as_ints.nuclear_repulsion_energy() + as_ints.slater_rules(dets[I], dets[I]) # Find the lowest eigenvalue efci = np.linalg.eigh(H)[0][0] print('\n FCI Energy: {}\n'.format(efci)) assert efci == pytest.approx(ref_fci, 1.0e-9)