Ejemplo n.º 1
0
def test_uccsd_3():
    """Test projective UCCSD on Ne using RHF/cc-pVDZ orbitals"""

    import forte.proc.scc as scc
    import forte
    import psi4
    import os.path

    forte.startup()

    ref_energy = -107.655681875111

    psi4.set_options({'FORTE__FROZEN_DOCC': [2]})
    options = forte.prepare_forte_options()
    forte_objects = forte.prepare_forte_objects_from_fcidump(
        options, os.path.dirname(__file__))
    state_weights_map, mo_space_info, scf_info, fcidump = forte_objects
    ints = forte.make_ints_from_fcidump(fcidump, options, mo_space_info)
    as_ints = forte.make_active_space_ints(mo_space_info, ints, 'CORRELATED',
                                           [])
    calc_data = scc.run_cc(as_ints,
                           scf_info,
                           mo_space_info,
                           cc_type='ucc',
                           max_exc=2,
                           e_convergence=1.0e-10)

    forte.cleanup()
    psi4.core.clean()

    energy = calc_data[-1][1]

    print(f'  UCCSD energy: {energy}')
    assert energy == pytest.approx(ref_energy, 1.0e-9)
Ejemplo n.º 2
0
def mr_dsrg_pt2(job_type, forte_objects, ints, options):
    """
    Driver to perform a MCSRGPT2_MO computation.

    :return: the computed energy
    """
    final_energy = 0.0
    ref_wfn, state_weights_map, mo_space_info, scf_info, fcidump = forte_objects

    state = forte.make_state_info_from_psi(options)
    # generate a list of states with their own weights
    state_map = forte.to_state_nroots_map(state_weights_map)

    cas_type = options.get_str("ACTIVE_SPACE_SOLVER")
    actv_type = options.get_str("FCIMO_ACTV_TYPE")
    if actv_type == "CIS" or actv_type == "CISD":
        raise Exception('Forte: VCIS/VCISD is not supported for MR-DSRG-PT2')
    max_rdm_level = 2 if options.get_str("THREEPDC") == "ZERO" else 3
    as_ints = forte.make_active_space_ints(mo_space_info, ints, "ACTIVE",
                                           ["RESTRICTED_DOCC"])
    ci = forte.make_active_space_solver(cas_type, state_map, scf_info,
                                        mo_space_info, as_ints, options)
    ci.compute_energy()

    rdms = ci.compute_average_rdms(state_weights_map, max_rdm_level,
                                   forte.RDMsType.spin_dependent)
    semi = forte.SemiCanonical(mo_space_info, ints, options)
    semi.semicanonicalize(rdms)

    mcsrgpt2_mo = forte.MCSRGPT2_MO(rdms, options, ints, mo_space_info)
    energy = mcsrgpt2_mo.compute_energy()
    return energy
Ejemplo n.º 3
0
    def _run(self):
        """Run an active space solver computation"""

        # compute the guess orbitals
        if not self.input_nodes[0].executed:
            flog('info', 'ActiveSpaceSolver: MOs not available in mo_solver. Calling mo_solver run()')
            self.input_nodes[0].run()
        else:
            flog('info', 'ActiveSpaceSolver: MOs read from mo_solver object')

        # make the state_map
        state_map = to_state_nroots_map(self._states)

        # make the mo_space_info object
        self.make_mo_space_info(self._mo_space_info_map)

        # prepare the options
        options = {'E_CONVERGENCE': self.e_convergence, 'R_CONVERGENCE': self.r_convergence}

        # values from self._options (user specified) replace those from options
        full_options = {**options, **self._options}

        flog('info', 'ActiveSpaceSolver: adding options')
        local_options = ForteOptions(forte_options)
        local_options.set_from_dict(full_options)

        flog('info', 'ActiveSpaceSolver: getting integral from the model object')
        self.ints = self.model.ints(self.data, local_options)

        # Make an active space integral object
        flog('info', 'ActiveSpaceSolver: making active space integrals')
        self.as_ints = make_active_space_ints(self.mo_space_info, self.ints, "ACTIVE", ["RESTRICTED_DOCC"])

        # create an active space solver object and compute the energy
        flog('info', 'ActiveSpaceSolver: creating active space solver object')
        self._active_space_solver = make_active_space_solver(
            self._type, state_map, self.scf_info, self.mo_space_info, self.as_ints, local_options
        )

        flog('info', 'ActiveSpaceSolver: calling compute_energy() on active space solver object')
        state_energies_list = self._active_space_solver.compute_energy()
        flog('info', 'ActiveSpaceSolver: compute_energy() done')

        flog('info', f'ActiveSpaceSolver: active space energy = {state_energies_list}')
        self._results.add('active space energy', state_energies_list, 'Active space energy', 'Eh')

        return self
Ejemplo n.º 4
0
def forte_driver(state_weights_map, scf_info, options, ints, mo_space_info):
    """
    Driver to perform a Forte calculation using new solvers.

    :param state_weights_map: dictionary of {state: weights}
    :param scf_info: a SCFInfo object of Forte
    :param options: a ForteOptions object of Forte
    :param ints: a ForteIntegrals object of Forte
    :param mo_space_info: a MOSpaceInfo object of Forte

    :return: the computed energy
    """
    # map state to number of roots
    state_map = forte.to_state_nroots_map(state_weights_map)

    # create an active space solver object and compute the energy
    active_space_solver_type = options.get_str('ACTIVE_SPACE_SOLVER')
    as_ints = forte.make_active_space_ints(mo_space_info, ints, "ACTIVE",
                                           ["RESTRICTED_DOCC"])
    active_space_solver = forte.make_active_space_solver(
        active_space_solver_type, state_map, scf_info, mo_space_info, as_ints,
        options)
    state_energies_list = active_space_solver.compute_energy()

    if options.get_bool('SPIN_ANALYSIS'):
        rdms = active_space_solver.compute_average_rdms(
            state_weights_map, 2, forte.RDMsType.spin_dependent)
        forte.perform_spin_analysis(rdms, options, mo_space_info, as_ints)

    # solver for dynamical correlation from DSRG
    correlation_solver_type = options.get_str('CORRELATION_SOLVER')
    if correlation_solver_type != 'NONE':
        dsrg_proc = ProcedureDSRG(active_space_solver, state_weights_map,
                                  mo_space_info, ints, options, scf_info)
        return_en = dsrg_proc.compute_energy()
        dsrg_proc.print_summary()
        dsrg_proc.push_to_psi4_environment()
    else:
        average_energy = forte.compute_average_state_energy(
            state_energies_list, state_weights_map)
        return_en = average_energy

    return return_en
Ejemplo n.º 5
0
def test_ul_uccsd_1():
    """Test projective unlinked UCCSD on H4 using RHF/STO-3G orbitals"""

    import pytest
    import forte.proc.scc as scc
    import forte
    import psi4
    import os.path

    forte.startup()

    ref_energy = -1.9437216535661626  # from Jonathon

    psi4.set_options({
        'FORTE__FCIDUMP_FILE': 'INTDUMP2',
        'FORTE__FCIDUMP_DOCC': [2],
        'FORTE__FROZEN_DOCC': [0],
    })

    options = forte.prepare_forte_options()
    forte_objects = forte.prepare_forte_objects_from_fcidump(
        options, os.path.dirname(__file__))
    state_weights_map, mo_space_info, scf_info, fcidump = forte_objects
    ints = forte.make_ints_from_fcidump(fcidump, options, mo_space_info)
    as_ints = forte.make_active_space_ints(mo_space_info, ints, 'CORRELATED',
                                           [])
    calc_data = scc.run_cc(as_ints,
                           scf_info,
                           mo_space_info,
                           cc_type='ucc',
                           max_exc=2,
                           e_convergence=1.0e-10,
                           linked=False,
                           diis_start=2)

    forte.cleanup()
    psi4.core.clean()

    energy = calc_data[-1][2]

    assert energy == pytest.approx(ref_energy, 1.0e-6)
Ejemplo n.º 6
0
def forte_driver(state_weights_map, scf_info, options, ints, mo_space_info):
    max_rdm_level = 3  # TODO: set this (Francesco)
    return_en = 0.0

    state_map = forte.to_state_nroots_map(state_weights_map)

    # Create an active space solver object and compute the energy
    active_space_solver_type = options.get_str('ACTIVE_SPACE_SOLVER')
    as_ints = forte.make_active_space_ints(mo_space_info, ints, "ACTIVE",
                                           ["RESTRICTED_DOCC"])
    active_space_solver = forte.make_active_space_solver(
        active_space_solver_type, state_map, scf_info, mo_space_info, as_ints,
        options)
    active_space_solver.set_max_rdm_level(max_rdm_level)
    state_energies_list = active_space_solver.compute_energy()

    # Notes (York):
    #     cases to run active space solver: reference relaxation, state-average dsrg
    #     cases to run contracted ci solver (will be put in ActiveSpaceSolver): contracted state-average dsrg
    Etemp1, Etemp2 = 0.0, 0.0

    # Create a dynamical correlation solver object
    correlation_solver_type = options.get_str('CORRELATION_SOLVER')
    if correlation_solver_type != 'NONE':
        # Grab the reference
        reference = active_space_solver.compute_average_reference(
            state_weights_map)  # TODO: this should be chosen in a smart way

        # Compute unitary matrices Ua and Ub that rotate the orbitals to the semicanonical basis
        semi = forte.SemiCanonical(mo_space_info, ints, options)
        if options.get_bool("SEMI_CANONICAL"):
            semi.semicanonicalize(reference, max_rdm_level)
        Ua = semi.Ua_t()
        Ub = semi.Ub_t()

        dsrg = forte.make_dsrg_method(correlation_solver_type, reference,
                                      scf_info, options, ints, mo_space_info)
        dsrg.set_Uactv(Ua, Ub)
        Edsrg = dsrg.compute_energy()
        psi4.core.set_scalar_variable('UNRELAXED ENERGY', Edsrg)

        # dipole moment related
        do_dipole = options.get_bool("DSRG_DIPOLE")
        if do_dipole:
            if correlation_solver_type == 'MRDSRG' or correlation_solver_type == 'THREE-DSRG-MRPT2':
                do_dipole = False
                psi4.core.print_out(
                    "\n  !Dipole moment is not implemented for {}.".format(
                        correlation_solver_type))
                warnings.warn("Dipole moment is not implemented for MRDSRG.",
                              UserWarning)
            udm_x = psi4.core.variable('UNRELAXED DIPOLE X')
            udm_y = psi4.core.variable('UNRELAXED DIPOLE Y')
            udm_z = psi4.core.variable('UNRELAXED DIPOLE Z')
            udm_t = psi4.core.variable('UNRELAXED DIPOLE')

        def dipole_routine(dsrg_method, reference):
            dipole_moments = dsrg_method.nuclear_dipole()
            dipole_dressed = dsrg_method.deGNO_DMbar_actv()
            for i in range(3):
                dipole_moments[i] += dipole_dressed[i].contract_with_densities(
                    reference)
            dm_total = math.sqrt(sum([i * i for i in dipole_moments]))
            dipole_moments.append(dm_total)
            return dipole_moments

        # determine the relaxation procedure
        relax_mode = options.get_str("RELAX_REF")
        is_multi_state = True if options.get_str(
            "CALC_TYPE") != "SS" else False

        if relax_mode == 'NONE' and is_multi_state:
            relax_mode = 'ONCE'

        if relax_mode == 'NONE':
            return Edsrg
        elif relax_mode == 'ONCE':
            maxiter = 1
        elif relax_mode == 'TWICE':
            maxiter = 2
        else:
            maxiter = options.get_int('MAXITER_RELAX_REF')

        # filter out some ms-dsrg algorithms
        ms_dsrg_algorithm = options.get_str("DSRG_MULTI_STATE")
        if is_multi_state and ("SA" not in ms_dsrg_algorithm):
            raise NotImplementedError(
                "MS or XMS is disabled due to the reconstruction.")
        if ms_dsrg_algorithm == "SA_SUB" and relax_mode != 'ONCE':
            raise NotImplementedError(
                "Need to figure out how to compute relaxed SA density.")

        # prepare for reference relaxation iteration
        relax_conv = options.get_double("RELAX_E_CONVERGENCE")
        e_conv = options.get_double("E_CONVERGENCE")
        converged = False if relax_mode != 'ONCE' and relax_mode != 'TWICE' else True

        # store (unrelaxed, relaxed) quantities
        dsrg_energies = []
        dsrg_dipoles = []

        for N in range(maxiter):
            # Grab the effective Hamiltonian in the actice space
            ints_dressed = dsrg.compute_Heff_actv()

            # Compute the energy
            if is_multi_state and ms_dsrg_algorithm == "SA_SUB":
                state_energies_list = active_space_solver.compute_contracted_energy(
                    ints_dressed)
                Erelax = forte.compute_average_state_energy(
                    state_energies_list, state_weights_map)
                return Erelax
            else:
                # Make a new ActiveSpaceSolver with the new ints
                as_solver_relaxed = forte.make_active_space_solver(
                    active_space_solver_type, state_map, scf_info,
                    mo_space_info, ints_dressed, options)
                as_solver_relaxed.set_max_rdm_level(max_rdm_level)
                state_energies_list = as_solver_relaxed.compute_energy()
                Erelax = forte.compute_average_state_energy(
                    state_energies_list, state_weights_map)

            dsrg_energies.append((Edsrg, Erelax))

            if do_dipole:
                if is_multi_state:
                    psi4.core.print_out(
                        "\n  !DSRG transition dipoles are disabled temporarily."
                    )
                    warnings.warn(
                        "DSRG transition dipoles are disabled temporarily.",
                        UserWarning)
                else:
                    reference = as_solver_relaxed.compute_average_reference(
                        state_weights_map)
                    x, y, z, t = dipole_routine(dsrg, reference)
                    dsrg_dipoles.append(
                        ((udm_x, udm_y, udm_z, udm_t), (x, y, z, t)))
                    psi4.core.print_out(
                        "\n\n    {} partially relaxed dipole moment:".format(
                            correlation_solver_type))
                    psi4.core.print_out(
                        "\n      X: {:10.6f}  Y: {:10.6f}"
                        "  Z: {:10.6f}  Total: {:10.6f}\n".format(x, y, z, t))

            # test convergence and break loop
            if abs(Edsrg - Etemp1) < relax_conv and abs(Erelax - Etemp2) < relax_conv \
                and abs(Edsrg - Erelax) < e_conv:
                converged = True
                break

            Etemp1, Etemp2 = Edsrg, Erelax

            # continue iterations
            if N + 1 != maxiter:
                # Compute the reference in the original basis
                # reference available if done relaxed dipole
                if do_dipole and (not is_multi_state):
                    reference = semi.transform_reference(
                        Ua, Ub, reference, max_rdm_level)
                else:
                    reference = semi.transform_reference(
                        Ua, Ub,
                        as_solver_relaxed.compute_average_reference(
                            state_weights_map), max_rdm_level)

                # Now semicanonicalize the reference and orbitals
                semi.semicanonicalize(reference, max_rdm_level)
                Ua = semi.Ua_t()
                Ub = semi.Ub_t()

                # Compute DSRG in the semicanonical basis
                dsrg = forte.make_dsrg_method(correlation_solver_type,
                                              reference, scf_info, options,
                                              ints, mo_space_info)
                dsrg.set_Uactv(Ua, Ub)
                Edsrg = dsrg.compute_energy()

                if do_dipole:
                    udm_x = psi4.core.variable('UNRELAXED DIPOLE X')
                    udm_y = psi4.core.variable('UNRELAXED DIPOLE Y')
                    udm_z = psi4.core.variable('UNRELAXED DIPOLE Z')
                    udm_t = psi4.core.variable('UNRELAXED DIPOLE')

        # printing
        if (not is_multi_state) or maxiter > 1:
            psi4.core.print_out(
                "\n\n  => {} Reference Relaxation Energy Summary <=\n".format(
                    correlation_solver_type))
            indent = ' ' * 4
            dash = '-' * 71
            title = indent + "{:5}  {:>31}  {:>31}\n".format(
                ' ', "Fixed Ref. (a.u.)", "Relaxed Ref. (a.u.)")
            title += indent + "{}  {}  {}\n".format(' ' * 5, '-' * 31,
                                                    '-' * 31)
            title += indent + "{:5}  {:>20} {:>10}  {:>20} {:>10}\n".format(
                "Iter.", "Total Energy", "Delta", "Total Energy", "Delta")
            psi4.core.print_out("\n{}".format(title + indent + dash))
            E0_old, E1_old = 0.0, 0.0
            for n, pair in enumerate(dsrg_energies):
                E0, E1 = pair
                psi4.core.print_out("\n{}{:>5}  {:>20.12f} {:>10.3e}"
                                    "  {:>20.12f} {:>10.3e}".format(
                                        indent, n + 1, E0, E0 - E0_old, E1,
                                        E1 - E1_old))
                E0_old, E1_old = E0, E1

            psi4.core.print_out("\n{}{}".format(indent, dash))

        if do_dipole and (not is_multi_state):
            psi4.core.print_out(
                "\n\n  => {} Reference Relaxation Dipole Summary <=\n".format(
                    correlation_solver_type))
            psi4.core.print_out("\n    {} unrelaxed dipole moment:".format(
                correlation_solver_type))
            psi4.core.print_out(
                "\n      X: {:10.6f}  Y: {:10.6f}  "
                "Z: {:10.6f}  Total: {:10.6f}\n".format(*dsrg_dipoles[0][0]))
            psi4.core.set_scalar_variable('UNRELAXED DIPOLE',
                                          dsrg_dipoles[0][0][-1])

            psi4.core.print_out(
                "\n    {} partially relaxed dipole moment:".format(
                    correlation_solver_type))
            psi4.core.print_out(
                "\n      X: {:10.6f}  Y: {:10.6f}  "
                "Z: {:10.6f}  Total: {:10.6f}\n".format(*dsrg_dipoles[0][1]))
            psi4.core.set_scalar_variable('PARTIALLY RELAXED DIPOLE',
                                          dsrg_dipoles[0][1][-1])

            if maxiter > 1:
                psi4.core.print_out("\n    {} relaxed dipole moment:".format(
                    correlation_solver_type))
                psi4.core.print_out("\n      X: {:10.6f}  Y: {:10.6f}  "
                                    "Z: {:10.6f}  Total: {:10.6f}\n".format(
                                        *dsrg_dipoles[1][0]))
                psi4.core.set_scalar_variable('RELAXED DIPOLE',
                                              dsrg_dipoles[1][0][-1])

        # set energies to environment
        psi4.core.set_scalar_variable('PARTIALLY RELAXED ENERGY',
                                      dsrg_energies[0][1])
        if maxiter > 1:
            psi4.core.set_scalar_variable('RELAXED ENERGY',
                                          dsrg_energies[1][0])

        # throw not converging error if relaxation not converged
        if not converged:
            psi4.core.set_scalar_variable('CURRENT UNRELAXED ENERGY',
                                          dsrg_energies[-1][0])
            psi4.core.set_scalar_variable('CURRENT RELAXED ENERGY',
                                          dsrg_energies[-1][1])
            psi4.core.set_scalar_variable('CURRENT ENERGY',
                                          dsrg_energies[-1][1])
            raise psi4.core.ConvergenceError(
                "DSRG relaxation does not converge in {} cycles".format(
                    maxiter))
        else:
            if relax_mode != 'ONCE' and relax_mode != 'TWICE':
                psi4.core.set_scalar_variable('FULLY RELAXED ENERGY',
                                              dsrg_energies[-1][1])
                psi4.core.set_scalar_variable('CURRENT ENERGY',
                                              dsrg_energies[-1][1])
                if do_dipole and (not is_multi_state):
                    psi4.core.print_out(
                        "\n    {} fully relaxed dipole moment:".format(
                            correlation_solver_type))
                    psi4.core.print_out(
                        "\n      X: {:10.6f}  Y: {:10.6f}  "
                        "Z: {:10.6f}  Total: {:10.6f}\n".format(
                            *dsrg_dipoles[-1][1]))
                    psi4.core.set_scalar_variable('FULLY RELAXED DIPOLE',
                                                  dsrg_dipoles[-1][1][-1])

        return Erelax
    else:

        average_energy = forte.compute_average_state_energy(
            state_energies_list, state_weights_map)
        return_en = average_energy

    return return_en
Ejemplo n.º 7
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()
Ejemplo n.º 8
0
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)
Ejemplo n.º 9
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()

    h2o = 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

    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
    mo_space_info = forte.make_mo_space_info(wfn, forte_options)
    ints = forte.make_forte_integrals(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)

    # Clean up forte (necessary)
    forte.cleanup()
Ejemplo n.º 10
0
def forte_driver(state_weights_map, scf_info, options, ints, mo_space_info):
    max_rdm_level = 3 # TODO: set this (Francesco)
    return_en = 0.0

    state_map = forte.to_state_nroots_map(state_weights_map)

    # Create an active space solver object and compute the energy
    active_space_solver_type = options.get_str('ACTIVE_SPACE_SOLVER')
    as_ints = forte.make_active_space_ints(mo_space_info, ints, "ACTIVE", ["RESTRICTED_DOCC"]);
    active_space_solver = forte.make_active_space_solver(active_space_solver_type,state_map,scf_info,mo_space_info,as_ints,options)
    state_energies_list = active_space_solver.compute_energy()


    # Notes (York):
    #     cases to run active space solver: reference relaxation, state-average dsrg
    #     cases to run contracted ci solver (will be put in ActiveSpaceSolver): contracted state-average dsrg
    Etemp1, Etemp2 = 0.0, 0.0

    # Create a dynamical correlation solver object
    correlation_solver_type = options.get_str('CORRELATION_SOLVER')
    if correlation_solver_type != 'NONE':
        # Grab the reference
        rdms = active_space_solver.compute_average_rdms(state_weights_map, 3) # TODO: max_rdm_level should be chosen in a smart way

        # Compute unitary matrices Ua and Ub that rotate the orbitals to the semicanonical basis
        semi = forte.SemiCanonical(mo_space_info, ints, options)
        if options.get_bool("SEMI_CANONICAL"):
            semi.semicanonicalize(rdms, max_rdm_level)
        Ua = semi.Ua_t()
        Ub = semi.Ub_t()

        dsrg = forte.make_dsrg_method(correlation_solver_type, rdms,
                                      scf_info, options, ints, mo_space_info)
        dsrg.set_Uactv(Ua, Ub)
        Edsrg = dsrg.compute_energy()
        psi4.core.set_scalar_variable('UNRELAXED ENERGY', Edsrg)

        # dipole moment related
        do_dipole = options.get_bool("DSRG_DIPOLE")
        if do_dipole:
            if correlation_solver_type == 'MRDSRG' or correlation_solver_type == 'THREE-DSRG-MRPT2':
                do_dipole = False
                psi4.core.print_out("\n  !Dipole moment is not implemented for {}.".format(correlation_solver_type))
                warnings.warn("Dipole moment is not implemented for MRDSRG.", UserWarning)
            udm_x = psi4.core.variable('UNRELAXED DIPOLE X')
            udm_y = psi4.core.variable('UNRELAXED DIPOLE Y')
            udm_z = psi4.core.variable('UNRELAXED DIPOLE Z')
            udm_t = psi4.core.variable('UNRELAXED DIPOLE')

        def dipole_routine(dsrg_method, rdms):
            dipole_moments = dsrg_method.nuclear_dipole()
            dipole_dressed = dsrg_method.deGNO_DMbar_actv()
            for i in range(3):
                dipole_moments[i] += dipole_dressed[i].contract_with_rdms(rdms)
            dm_total = math.sqrt(sum([i * i for i in dipole_moments]))
            dipole_moments.append(dm_total)
            return dipole_moments

        # determine the relaxation procedure
        relax_mode = options.get_str("RELAX_REF")
        is_multi_state = True if options.get_str("CALC_TYPE") != "SS" else False

        if relax_mode == 'NONE' and is_multi_state:
            relax_mode = 'ONCE'

        if relax_mode == 'NONE':
            return Edsrg
        elif relax_mode == 'ONCE':
            maxiter = 1
        elif relax_mode == 'TWICE':
            maxiter = 2
        else:
            maxiter = options.get_int('MAXITER_RELAX_REF')

        # filter out some ms-dsrg algorithms
        ms_dsrg_algorithm = options.get_str("DSRG_MULTI_STATE")
        if is_multi_state and ("SA" not in ms_dsrg_algorithm):
            raise NotImplementedError("MS or XMS is disabled due to the reconstruction.")
        if ms_dsrg_algorithm == "SA_SUB" and relax_mode != 'ONCE':
            raise NotImplementedError("Need to figure out how to compute relaxed SA density.")

        # prepare for reference relaxation iteration
        relax_conv = options.get_double("RELAX_E_CONVERGENCE")
        e_conv = options.get_double("E_CONVERGENCE")
        converged = False if relax_mode != 'ONCE' and relax_mode != 'TWICE' else True

        # store (unrelaxed, relaxed) quantities
        dsrg_energies = []
        dsrg_dipoles = []

        for N in range(maxiter):
            # Grab the effective Hamiltonian in the actice space
            ints_dressed = dsrg.compute_Heff_actv()

            # Compute the energy
            if is_multi_state and ms_dsrg_algorithm == "SA_SUB":
                sa_sub_max_rdm = 2 # TODO: This should be 3 if do_hbar3 is true
                state_energies_list = active_space_solver.compute_contracted_energy(ints_dressed, sa_sub_max_rdm)
                Erelax = forte.compute_average_state_energy(state_energies_list,state_weights_map)
                return Erelax
            else:
                # Make a new ActiveSpaceSolver with the new ints
                as_solver_relaxed = forte.make_active_space_solver(active_space_solver_type,
                                                                   state_map,scf_info,
                                                                   mo_space_info,ints_dressed,
                                                                   options)
                state_energies_list = as_solver_relaxed.compute_energy()
                Erelax = forte.compute_average_state_energy(state_energies_list,state_weights_map)

            dsrg_energies.append((Edsrg, Erelax))

            if do_dipole:
                if is_multi_state:
                    psi4.core.print_out("\n  !DSRG transition dipoles are disabled temporarily.")
                    warnings.warn("DSRG transition dipoles are disabled temporarily.", UserWarning)
                else:
                    rdms = as_solver_relaxed.compute_average_rdms(state_weights_map, 3)
                    x, y, z, t = dipole_routine(dsrg, rdms)
                    dsrg_dipoles.append(((udm_x, udm_y, udm_z, udm_t), (x, y, z, t)))
                    psi4.core.print_out("\n\n    {} partially relaxed dipole moment:".format(correlation_solver_type))
                    psi4.core.print_out("\n      X: {:10.6f}  Y: {:10.6f}"
                                        "  Z: {:10.6f}  Total: {:10.6f}\n".format(x, y, z, t))

            # test convergence and break loop
            if abs(Edsrg - Etemp1) < relax_conv and abs(Erelax - Etemp2) < relax_conv \
                and abs(Edsrg - Erelax) < e_conv:
                converged = True
                break

            Etemp1, Etemp2 = Edsrg, Erelax

            # continue iterations
            if N + 1 != maxiter:
                # Compute the rdms in the original basis
                # rdms available if done relaxed dipole
                if do_dipole and (not is_multi_state):
                    rdms = semi.transform_rdms(Ua, Ub, rdms, max_rdm_level)
                else:
                    rdms = semi.transform_rdms(Ua, Ub, as_solver_relaxed.compute_average_rdms(state_weights_map, 3),
                                                         max_rdm_level)

                # Now semicanonicalize the reference and orbitals
                semi.semicanonicalize(rdms, max_rdm_level)
                Ua = semi.Ua_t()
                Ub = semi.Ub_t()

                # Compute DSRG in the semicanonical basis
                dsrg = forte.make_dsrg_method(correlation_solver_type, rdms,
                                              scf_info, options, ints, mo_space_info)
                dsrg.set_Uactv(Ua, Ub)
                Edsrg = dsrg.compute_energy()

                if do_dipole:
                    udm_x = psi4.core.variable('UNRELAXED DIPOLE X')
                    udm_y = psi4.core.variable('UNRELAXED DIPOLE Y')
                    udm_z = psi4.core.variable('UNRELAXED DIPOLE Z')
                    udm_t = psi4.core.variable('UNRELAXED DIPOLE')

        # printing
        if (not is_multi_state) or maxiter > 1:
            psi4.core.print_out("\n\n  => {} Reference Relaxation Energy Summary <=\n".format(correlation_solver_type))
            indent = ' ' * 4
            dash = '-' * 71
            title = indent + "{:5}  {:>31}  {:>31}\n".format(' ', "Fixed Ref. (a.u.)",
                                                             "Relaxed Ref. (a.u.)")
            title += indent + "{}  {}  {}\n".format(' ' * 5, '-' * 31, '-' * 31)
            title += indent + "{:5}  {:>20} {:>10}  {:>20} {:>10}\n".format("Iter.", "Total Energy", "Delta",
                                                                        "Total Energy", "Delta")
            psi4.core.print_out("\n{}".format(title + indent + dash))
            E0_old, E1_old = 0.0, 0.0
            for n, pair in enumerate(dsrg_energies):
                E0, E1 = pair
                psi4.core.print_out("\n{}{:>5}  {:>20.12f} {:>10.3e}"
                                    "  {:>20.12f} {:>10.3e}".format(indent, n + 1,
                                                                    E0, E0 - E0_old, E1, E1 - E1_old))
                E0_old, E1_old = E0, E1

            psi4.core.print_out("\n{}{}".format(indent, dash))

        if do_dipole and (not is_multi_state):
            psi4.core.print_out("\n\n  => {} Reference Relaxation Dipole Summary <=\n".format(correlation_solver_type))
            psi4.core.print_out("\n    {} unrelaxed dipole moment:".format(correlation_solver_type))
            psi4.core.print_out("\n      X: {:10.6f}  Y: {:10.6f}  "
                                "Z: {:10.6f}  Total: {:10.6f}\n".format(*dsrg_dipoles[0][0]))
            psi4.core.set_scalar_variable('UNRELAXED DIPOLE', dsrg_dipoles[0][0][-1])

            psi4.core.print_out("\n    {} partially relaxed dipole moment:".format(correlation_solver_type))
            psi4.core.print_out("\n      X: {:10.6f}  Y: {:10.6f}  "
                                "Z: {:10.6f}  Total: {:10.6f}\n".format(*dsrg_dipoles[0][1]))
            psi4.core.set_scalar_variable('PARTIALLY RELAXED DIPOLE', dsrg_dipoles[0][1][-1])

            if maxiter > 1:
                psi4.core.print_out("\n    {} relaxed dipole moment:".format(correlation_solver_type))
                psi4.core.print_out("\n      X: {:10.6f}  Y: {:10.6f}  "
                                    "Z: {:10.6f}  Total: {:10.6f}\n".format(*dsrg_dipoles[1][0]))
                psi4.core.set_scalar_variable('RELAXED DIPOLE', dsrg_dipoles[1][0][-1])

        # set energies to environment
        psi4.core.set_scalar_variable('PARTIALLY RELAXED ENERGY', dsrg_energies[0][1])
        if maxiter > 1:
            psi4.core.set_scalar_variable('RELAXED ENERGY', dsrg_energies[1][0])

        # throw not converging error if relaxation not converged
        if not converged:
            psi4.core.set_scalar_variable('CURRENT UNRELAXED ENERGY', dsrg_energies[-1][0])
            psi4.core.set_scalar_variable('CURRENT RELAXED ENERGY', dsrg_energies[-1][1])
            psi4.core.set_scalar_variable('CURRENT ENERGY', dsrg_energies[-1][1])
            raise psi4.core.ConvergenceError("DSRG relaxation does not converge in {} cycles".format(maxiter))
        else:
            if relax_mode != 'ONCE' and relax_mode != 'TWICE':
                psi4.core.set_scalar_variable('FULLY RELAXED ENERGY', dsrg_energies[-1][1])
                psi4.core.set_scalar_variable('CURRENT ENERGY', dsrg_energies[-1][1])
                if do_dipole and (not is_multi_state):
                    psi4.core.print_out("\n    {} fully relaxed dipole moment:".format(correlation_solver_type))
                    psi4.core.print_out("\n      X: {:10.6f}  Y: {:10.6f}  "
                                        "Z: {:10.6f}  Total: {:10.6f}\n".format(*dsrg_dipoles[-1][1]))
                    psi4.core.set_scalar_variable('FULLY RELAXED DIPOLE', dsrg_dipoles[-1][1][-1])

        return Erelax
    else : 

        average_energy = forte.compute_average_state_energy(state_energies_list,state_weights_map)
        return_en = average_energy

    return return_en
Ejemplo n.º 11
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