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)
Example #2
0
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
Example #3
0
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)
Example #4
0
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)
Example #5
0
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()
Example #6
0
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])
Example #7
0
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)