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