示例#1
0
def gradient_forte(name, **kwargs):
    r"""Function encoding sequence of PSI module and plugin calls so that
    forte can be called via :py:func:`~driver.energy`. For post-scf plugins.

    >>> gradient('forte')
        available for : CASSCF
    """

    # # Start Forte, initialize ambit
    # my_proc_n_nodes = forte.startup()
    # my_proc, n_nodes = my_proc_n_nodes

    # Get the psi4 option object
    optstash = p4util.OptionsState(['GLOBALS', 'DERTYPE'])
    psi4.core.set_global_option('DERTYPE', 'FIRST')

    # Build Forte options
    options = prepare_forte_options()

    # Print the banner
    forte.banner()

    # Run a method
    job_type = options.get_str('JOB_TYPE')

    if job_type not in {"CASSCF", "MCSCF_TWO_STEP"}:
        raise Exception(
            'Analytic energy gradients are only implemented for job_types CASSCF and MCSCF_TWO_STEP.'
        )

    # Prepare Forte objects: state_weights_map, mo_space_info, scf_info
    forte_objects = prepare_forte_objects(options, name, **kwargs)
    ref_wfn, state_weights_map, mo_space_info, scf_info, fcidump = forte_objects

    # Make an integral object
    time_pre_ints = time.time()

    ints = forte.make_ints_from_psi4(ref_wfn, options, mo_space_info)

    start = time.time()

    # Rotate orbitals before computation
    orb_type = options.get_str("ORBITAL_TYPE")
    if orb_type != 'CANONICAL':
        orb_t = forte.make_orbital_transformation(orb_type, scf_info, options,
                                                  ints, mo_space_info)
        orb_t.compute_transformation()
        Ua = orb_t.get_Ua()
        Ub = orb_t.get_Ub()
        ints.rotate_orbitals(Ua, Ub)

    if job_type == "CASSCF":
        casscf = forte.make_casscf(state_weights_map, scf_info, options,
                                   mo_space_info, ints)
        energy = casscf.compute_energy()
        casscf.compute_gradient()

    if job_type == "MCSCF_TWO_STEP":
        casscf = forte.make_mcscf_two_step(state_weights_map, scf_info,
                                           options, mo_space_info, ints)
        energy = casscf.compute_energy()

    time_pre_deriv = time.time()

    derivobj = psi4.core.Deriv(ref_wfn)
    derivobj.set_deriv_density_backtransformed(True)
    derivobj.set_ignore_reference(True)
    grad = derivobj.compute(psi4.core.DerivCalcType.Correlated)
    ref_wfn.set_gradient(grad)
    optstash.restore()

    end = time.time()

    # Close ambit, etc.
    # forte.cleanup()

    # Print timings
    psi4.core.print_out('\n\n ==> Forte Timings <==\n')
    times = [('prepare integrals', start - time_pre_ints),
             ('run forte energy', time_pre_deriv - start),
             ('compute derivative integrals', end - time_pre_deriv)]
    max_key_size = max(len(k) for k, v in times)
    for key, value in times:
        psi4.core.print_out(f'\n  Time to {key:{max_key_size}} :'
                            f' {value:12.3f} seconds')
    psi4.core.print_out(f'\n  {"Total":{max_key_size + 8}} :'
                        f' {end - time_pre_ints:12.3f} seconds\n')

    # Dump orbitals if needed
    if options.get_bool('DUMP_ORBITALS'):
        dump_orbitals(ref_wfn)

    return ref_wfn
示例#2
0
def run_forte(name, **kwargs):
    r"""Function encoding sequence of PSI module and plugin calls so that
    forte can be called via :py:func:`~driver.energy`. For post-scf plugins.

    >>> energy('forte')

    """

    # # Start Forte, initialize ambit
    # my_proc_n_nodes = forte.startup()
    # my_proc, n_nodes = my_proc_n_nodes

    # Build Forte options
    options = prepare_forte_options()

    # Print the banner
    forte.banner()

    # Prepare Forte objects: state_weights_map, mo_space_info, scf_info
    forte_objects = prepare_forte_objects(options, name, **kwargs)
    ref_wfn, state_weights_map, mo_space_info, scf_info, fcidump = forte_objects

    job_type = options.get_str('JOB_TYPE')
    if job_type == 'NONE' and options.get_str("ORBITAL_TYPE") == 'CANONICAL':
        psi4.core.set_scalar_variable('CURRENT ENERGY', 0.0)
        return ref_wfn

    start_pre_ints = time.time()

    if 'FCIDUMP' in options.get_str('INT_TYPE'):
        psi4.core.print_out('\n  Forte will use custom integrals')
        # Make an integral object from the psi4 wavefunction object
        ints = make_ints_from_fcidump(fcidump, options, mo_space_info)
    else:
        psi4.core.print_out('\n  Forte will use psi4 integrals')
        # Make an integral object from the psi4 wavefunction object
        ints = forte.make_ints_from_psi4(ref_wfn, options, mo_space_info)

    start = time.time()

    # Rotate orbitals before computation (e.g. localization, MP2 natural orbitals, etc.)
    orb_type = options.get_str("ORBITAL_TYPE")
    if orb_type != 'CANONICAL':
        orb_t = forte.make_orbital_transformation(orb_type, scf_info, options,
                                                  ints, mo_space_info)
        orb_t.compute_transformation()
        Ua = orb_t.get_Ua()
        Ub = orb_t.get_Ub()
        ints.rotate_orbitals(Ua, Ub, job_type != 'NONE')

    # Run a method
    if job_type == 'NONE':
        psi4.core.set_scalar_variable('CURRENT ENERGY', 0.0)
        # forte.cleanup()
        return ref_wfn

    energy = 0.0

    if (options.get_bool("CASSCF_REFERENCE") or job_type == "CASSCF"):
        if options.get_str('INT_TYPE') == 'FCIDUMP':
            raise Exception('Forte: the CASSCF code cannot use integrals read'
                            ' from a FCIDUMP file')

        casscf = forte.make_casscf(state_weights_map, scf_info, options,
                                   mo_space_info, ints)
        energy = casscf.compute_energy()

    if (job_type == "MCSCF_TWO_STEP"):
        casscf = forte.make_mcscf_two_step(state_weights_map, scf_info,
                                           options, mo_space_info, ints)
        energy = casscf.compute_energy()

    if (job_type == 'NEWDRIVER'):
        energy = forte_driver(state_weights_map, scf_info, options, ints,
                              mo_space_info)
    elif (job_type == 'MR-DSRG-PT2'):
        energy = mr_dsrg_pt2(job_type, forte_objects, ints, options)

    end = time.time()

    # Close ambit, etc.
    # forte.cleanup()

    psi4.core.set_scalar_variable('CURRENT ENERGY', energy)

    psi4.core.print_out(
        f'\n\n  Time to prepare integrals: {start - start_pre_ints:12.3f} seconds'
    )
    psi4.core.print_out(
        f'\n  Time to run job          : {end - start:12.3f} seconds')
    psi4.core.print_out(
        f'\n  Total                    : {end - start_pre_ints:12.3f} seconds\n'
    )

    if 'FCIDUMP' not in options.get_str('INT_TYPE'):
        if options.get_bool('DUMP_ORBITALS'):
            dump_orbitals(ref_wfn)
        return ref_wfn