!> @file mp2_energy.F90 !> !> @brief Driver for the standalone MP2 ground-state energy method. !> !> MP2 is a post-SCF ground-state correlation correction: the SCF reference !> (RHF/UHF/ROHF) is converged first by the usual PyOQP `reference` step, and !> this driver adds the second-order Moller-Plesset correlation energy on top, !> reusing the validated two-electron driver via `mp2_lib`. It is dispatched !> from Python as `[input] method = mp2` (a ground-state post-SCF method that !> reports no excitations). module mp2_energy_mod implicit none private public :: mp2_energy character(len=*), parameter :: module_name = "mp2_energy_mod" contains !> C-bound entry point: `[input] method = mp2` dispatches here. subroutine mp2_energy_C(c_handle) bind(C, name="mp2_energy") use c_interop, only: oqp_handle_t, oqp_handle_get_info use types, only: information type(oqp_handle_t) :: c_handle type(information), pointer :: inf inf => oqp_handle_get_info(c_handle) call mp2_energy(inf) end subroutine mp2_energy_C !> MP2 ground-state correlation on the converged SCF reference. subroutine mp2_energy(infos) use precision, only: dp use io_constants, only: iw use types, only: information use printing, only: print_module_info use mp2_lib, only: mp2_correlation use messages, only: show_message, with_abort implicit none type(information), target, intent(inout) :: infos real(kind=dp) :: e_mp2, e_aa, e_bb, e_ab, e_ref, e_ss logical :: computed open(unit=iw, file=infos%log_filename, position="append") call print_module_info('MP2_Energy', 'Computing MP2 ground-state correlation') e_ref = infos%mol_energy%energy call mp2_correlation(infos, e_mp2, e_aa, e_bb, e_ab, computed) write(iw,'(/,2X,60("="))') write(iw,'(2X,A)') 'MP2 (Moller-Plesset second order, ground state)' write(iw,'(2X,60("="))') if (computed) then e_ss = e_aa + e_bb write(iw,'(2X,A,F20.10)') 'E(reference, SCF) = ', e_ref write(iw,'(2X,A,F20.10)') 'E(MP2, same-spin aa) = ', e_aa write(iw,'(2X,A,F20.10)') 'E(MP2, same-spin bb) = ', e_bb write(iw,'(2X,A,F20.10)') 'E(MP2, same-spin total)= ', e_ss write(iw,'(2X,A,F20.10)') 'E(MP2, opp-spin ab) = ', e_ab write(iw,'(2X,A,F20.10)') 'MP2 same-spin scale = ', infos%dft%MP2SS_Scale write(iw,'(2X,A,F20.10)') 'MP2 opp-spin scale = ', infos%dft%MP2OS_Scale write(iw,'(2X,A,F20.10)') 'E(MP2, correlation) = ', e_mp2 write(iw,'(2X,A,F20.10)') 'E(MP2, total) = ', e_ref + e_mp2 ! Report the MP2 total as the molecular energy for downstream consumers. infos%mol_energy%energy = e_ref + e_mp2 infos%mol_energy%etot = e_ref + e_mp2 else write(iw,'(2X,A)') 'MP2 not computed: the system exceeds the per-MO-pair' write(iw,'(2X,A)') 'Coulomb-build size guard (raise OQP_MP2_MAX_JBUILDS,' write(iw,'(2X,A)') 'or use a smaller basis).' write(iw,'(2X,60("="),/)') close(iw) call show_message('MP2 aborted: OQP_MP2_MAX_JBUILDS guard was exceeded', with_abort) return end if write(iw,'(2X,60("="),/)') close(iw) end subroutine mp2_energy end module mp2_energy_mod